3

I have spring boot application with undertow container. There is a rest controller that accepts file that look like following:

  @ResponseStatus(HttpStatus.CREATED)
  @PostMapping(value = {"/v2/upload-csv"},
               produces = {MediaType.APPLICATION_JSON_VALUE},
               consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
  public List<ChordInfo> uploadFile(@RequestPart @NotNull(message = "File is not provided!") MultipartFile file) {
    return chordService.handleFile(file);
  }

With MaxUploadSizeExceededException exception handler

  @ExceptionHandler
  @ResponseStatus(HttpStatus.BAD_REQUEST)
  public ErrorResponse handleFileSizeException(MaxUploadSizeExceededException exception) {
    return ErrorResponse.singleError(new Error(
            ErrorCode.UPLOAD_SIZE_EXCEEDED,
            exception.getMessage(),
            new UploadSizeExceededMeta(exception.getMaxUploadSize())
        )
    );
  }

And Basic authentication configuration:

@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
        .cors().and().csrf().disable()
        .authorizeRequests()
        .antMatchers("/**").permitAll()
        .and()
        .httpBasic();
  }
}

It'd worked well until I replaced basic auth to oauth2 resource server with JWT. Now the configuration looks like this

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
        .httpBasic().disable()
        .csrf().disable()
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
        .authorizeRequests()
        .anyRequest().permitAll()
        .and()
        .oauth2ResourceServer()
        .jwt();
  }

If I try to upload file exceeding limit, the application returns 500 with default spring's exception:

{
  "timestamp": "2021-09-03T16:08:13.341+00:00",
  "status": 500,
  "error": "Internal Server Error",
  "message": "",
  "path": "/v2/upload-csv"
}

How could I fix it? I found out that replacing container to Tomcat fixes the problem but I'd like to stay on undertow.

UPD1 Here is stack trace with with enabled jwt

ERROR io.undertow.request - UT005023: Exception handling request to /v2/upload-csv
java.lang.IllegalStateException: io.undertow.server.handlers.form.MultiPartParserDefinition$FileTooLargeException: UT000054: The maximum size 1048576 for an individual file in a multipart request was exceeded
    at io.undertow.servlet.spec.HttpServletRequestImpl.parseFormData(HttpServletRequestImpl.java:855) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.spec.HttpServletRequestImpl.getParameterValues(HttpServletRequestImpl.java:778) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at javax.servlet.ServletRequestWrapper.getParameterValues(ServletRequestWrapper.java:174) ~[jakarta.servlet-api-4.0.4.jar:4.0.4]
    at javax.servlet.ServletRequestWrapper.getParameterValues(ServletRequestWrapper.java:174) ~[jakarta.servlet-api-4.0.4.jar:4.0.4]
    at org.springframework.security.web.firewall.StrictHttpFirewall$StrictFirewalledRequest.getParameterValues(StrictHttpFirewall.java:721) ~[spring-security-web-5.4.2.jar:5.4.2]
    at javax.servlet.ServletRequestWrapper.getParameterValues(ServletRequestWrapper.java:174) ~[jakarta.servlet-api-4.0.4.jar:4.0.4]
    at org.springframework.security.oauth2.server.resource.web.DefaultBearerTokenResolver.resolveFromRequestParameters(DefaultBearerTokenResolver.java:116) ~[spring-security-oauth2-resource-server-5.4.2.jar:5.4.2]
    at org.springframework.security.oauth2.server.resource.web.DefaultBearerTokenResolver.resolve(DefaultBearerTokenResolver.java:52) ~[spring-security-oauth2-resource-server-5.4.2.jar:5.4.2]
    at org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter.doFilterInternal(BearerTokenAuthenticationFilter.java:106) ~[spring-security-oauth2-resource-server-5.4.2.jar:5.4.2]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183) ~[spring-security-web-5.4.2.jar:5.4.2]
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) ~[spring-web-5.3.3.jar:5.3.3]
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) ~[spring-web-5.3.3.jar:5.3.3]
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.3.jar:5.3.3]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.3.jar:5.3.3]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at org.springframework.cloud.sleuth.instrument.web.servlet.TracingFilter.doFilter(TracingFilter.java:89) ~[spring-cloud-sleuth-instrumentation-3.0.1.jar:3.0.1]
    at org.springframework.cloud.sleuth.autoconfig.instrument.web.LazyTracingFilter.doFilter(TraceWebServletConfiguration.java:121) ~[spring-cloud-sleuth-autoconfigure-3.0.1.jar:3.0.1]
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at org.zalando.logbook.servlet.LogbookFilter.doFilter(LogbookFilter.java:71) ~[logbook-servlet-2.4.2.jar:na]
    at org.zalando.logbook.servlet.SecureLogbookFilter.doFilter(SecureLogbookFilter.java:32) ~[logbook-servlet-2.4.2.jar:na]
    at org.zalando.logbook.servlet.HttpFilter.doFilter(HttpFilter.java:31) ~[logbook-servlet-2.4.2.jar:na]
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:93) ~[spring-boot-actuator-2.4.2.jar:2.4.2]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.3.jar:5.3.3]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:117) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) ~[undertow-core-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46) ~[undertow-core-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60) ~[undertow-core-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43) ~[undertow-core-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) ~[undertow-core-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.SendErrorPageHandler.handleRequest(SendErrorPageHandler.java:52) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) ~[undertow-core-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:269) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:78) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:133) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:130) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:249) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:78) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:99) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:387) ~[undertow-core-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:841) ~[undertow-core-2.2.3.Final.jar:2.2.3.Final]
    at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35) ~[jboss-threads-3.1.0.Final.jar:3.1.0.Final]
    at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2019) ~[jboss-threads-3.1.0.Final.jar:3.1.0.Final]
    at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1558) ~[jboss-threads-3.1.0.Final.jar:3.1.0.Final]
    at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1449) ~[jboss-threads-3.1.0.Final.jar:3.1.0.Final]
    at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]
Caused by: io.undertow.server.handlers.form.MultiPartParserDefinition$FileTooLargeException: UT000054: The maximum size 1048576 for an individual file in a multipart request was exceeded
    at io.undertow.server.handlers.form.MultiPartParserDefinition$MultiPartUploadHandler.data(MultiPartParserDefinition.java:272) ~[undertow-core-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.util.MultipartParser$IdentityEncoding.handle(MultipartParser.java:365) ~[undertow-core-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.util.MultipartParser$ParseState.entity(MultipartParser.java:343) ~[undertow-core-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.util.MultipartParser$ParseState.parse(MultipartParser.java:131) ~[undertow-core-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.server.handlers.form.MultiPartParserDefinition$MultiPartUploadHandler.parseBlocking(MultiPartParserDefinition.java:232) ~[undertow-core-2.2.3.Final.jar:2.2.3.Final]
    at io.undertow.servlet.spec.HttpServletRequestImpl.parseFormData(HttpServletRequestImpl.java:853) ~[undertow-servlet-2.2.3.Final.jar:2.2.3.Final]
    ... 86 common frames omitted
Nikita Medvedev
  • 153
  • 1
  • 6
  • Without knowing the actual cause of the exception (the stack trace is probably somewhere in your application) this will be impossible to answer. – M. Deinum Sep 03 '21 at 16:55
  • @M.Deinum sorry for long response, I attached the stack trace in UPD1 – Nikita Medvedev Sep 10 '21 at 15:29
  • The stack trace, kind of clearly, indicates that you are uploading a file larger then the configured (or the default) limit. Change the upload limit. – M. Deinum Sep 13 '21 at 06:00
  • Please, check the topic and problem description. The problem is not related to limit configuration but this type exception handling – Nikita Medvedev Sep 23 '21 at 18:15

1 Answers1

0

This is the default max multipart file size (1048576 Byte = 1MB). Of course you can change this limit.

spring.servlet.multipart.max-file-size = 10MB
spring.servlet.multipart.max-request-size = 10MB
ray
  • 1,512
  • 4
  • 11
  • Please, check the topic and problem description. The problem is not related to limit configuration but this type exception handling. I tried to set limits explicitly but the problem hasn't gone – Nikita Medvedev Sep 23 '21 at 18:16
  • Okay my bad. In the stack trace I see, `FileTooLargeException` not `MaxUploadSizeExceededException`. Have you checked that? – ray Sep 23 '21 at 18:36