StandardServletMultipartResolver provides strict Servlet compliance option
Closes gh-26826
This commit is contained in:
parent
ed27ea7aa0
commit
1ff8da3635
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -21,6 +21,7 @@ import javax.servlet.http.Part;
|
|||
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.multipart.MultipartException;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
|
|
@ -32,6 +33,15 @@ import org.springframework.web.multipart.MultipartResolver;
|
|||
* To be added as "multipartResolver" bean to a Spring DispatcherServlet context,
|
||||
* without any extra configuration at the bean level (see below).
|
||||
*
|
||||
* <p>This resolver variant uses your Servlet container's multipart parser as-is,
|
||||
* potentially exposing the application to container implementation differences.
|
||||
* See {@link org.springframework.web.multipart.commons.CommonsMultipartResolver}
|
||||
* for an alternative implementation using a local Commons FileUpload library
|
||||
* within the application, providing maximum portability across Servlet containers.
|
||||
* Also, see this resolver's configuration option for
|
||||
* {@link #setStrictServletCompliance strict Servlet compliance}, narrowing the
|
||||
* applicability of Spring's {@link MultipartHttpServletRequest} to form data only.
|
||||
*
|
||||
* <p><b>Note:</b> In order to use Servlet 3.0 based multipart parsing,
|
||||
* you need to mark the affected servlet with a "multipart-config" section in
|
||||
* {@code web.xml}, or with a {@link javax.servlet.MultipartConfigElement}
|
||||
|
|
@ -55,6 +65,7 @@ import org.springframework.web.multipart.MultipartResolver;
|
|||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
* @see #setResolveLazily
|
||||
* @see #setStrictServletCompliance
|
||||
* @see HttpServletRequest#getParts()
|
||||
* @see org.springframework.web.multipart.commons.CommonsMultipartResolver
|
||||
*/
|
||||
|
|
@ -62,6 +73,8 @@ public class StandardServletMultipartResolver implements MultipartResolver {
|
|||
|
||||
private boolean resolveLazily = false;
|
||||
|
||||
private boolean strictServletCompliance = false;
|
||||
|
||||
|
||||
/**
|
||||
* Set whether to resolve the multipart request lazily at the time of
|
||||
|
|
@ -76,10 +89,32 @@ public class StandardServletMultipartResolver implements MultipartResolver {
|
|||
this.resolveLazily = resolveLazily;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify whether this resolver should strictly comply with the Servlet
|
||||
* specification, only kicking in for "multipart/form-data" requests.
|
||||
* <p>Default is "false", trying to process any request with a "multipart/"
|
||||
* content type as far as the underlying Servlet container supports it
|
||||
* (which works on e.g. Tomcat but not on Jetty). For consistent portability
|
||||
* and in particular for consistent custom handling of non-form multipart
|
||||
* request types outside of Spring's {@link MultipartResolver} mechanism,
|
||||
* switch this flag to "true": Only "multipart/form-data" requests will be
|
||||
* wrapped with a {@link MultipartHttpServletRequest} then; other kinds of
|
||||
* requests will be left as-is, allowing for custom processing in user code.
|
||||
* <p>Note that Commons FileUpload and therefore
|
||||
* {@link org.springframework.web.multipart.commons.CommonsMultipartResolver}
|
||||
* supports any "multipart/" request type. However, it restricts processing
|
||||
* to POST requests which standard Servlet multipart parsers might not do.
|
||||
* @since 5.3.9
|
||||
*/
|
||||
public void setStrictServletCompliance(boolean strictServletCompliance) {
|
||||
this.strictServletCompliance = strictServletCompliance;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isMultipart(HttpServletRequest request) {
|
||||
return StringUtils.startsWithIgnoreCase(request.getContentType(), "multipart/");
|
||||
return StringUtils.startsWithIgnoreCase(request.getContentType(),
|
||||
(this.strictServletCompliance ? MediaType.MULTIPART_FORM_DATA_VALUE : "multipart/"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.multipart.support;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class StandardServletMultipartResolverTests {
|
||||
|
||||
@Test
|
||||
public void isMultipartWithDefaultSetting() {
|
||||
StandardServletMultipartResolver resolver = new StandardServletMultipartResolver();
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/");
|
||||
assertThat(resolver.isMultipart(request)).isFalse();
|
||||
|
||||
request.setContentType(MediaType.MULTIPART_FORM_DATA_VALUE);
|
||||
assertThat(resolver.isMultipart(request)).isTrue();
|
||||
|
||||
request.setContentType(MediaType.MULTIPART_MIXED_VALUE);
|
||||
assertThat(resolver.isMultipart(request)).isTrue();
|
||||
|
||||
request.setContentType(MediaType.MULTIPART_RELATED_VALUE);
|
||||
assertThat(resolver.isMultipart(request)).isTrue();
|
||||
|
||||
request = new MockHttpServletRequest("PUT", "/");
|
||||
assertThat(resolver.isMultipart(request)).isFalse();
|
||||
|
||||
request.setContentType(MediaType.MULTIPART_FORM_DATA_VALUE);
|
||||
assertThat(resolver.isMultipart(request)).isTrue();
|
||||
|
||||
request.setContentType(MediaType.MULTIPART_MIXED_VALUE);
|
||||
assertThat(resolver.isMultipart(request)).isTrue();
|
||||
|
||||
request.setContentType(MediaType.MULTIPART_RELATED_VALUE);
|
||||
assertThat(resolver.isMultipart(request)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isMultipartWithStrictSetting() {
|
||||
StandardServletMultipartResolver resolver = new StandardServletMultipartResolver();
|
||||
resolver.setStrictServletCompliance(true);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/");
|
||||
assertThat(resolver.isMultipart(request)).isFalse();
|
||||
|
||||
request.setContentType(MediaType.MULTIPART_FORM_DATA_VALUE);
|
||||
assertThat(resolver.isMultipart(request)).isTrue();
|
||||
|
||||
request.setContentType(MediaType.MULTIPART_MIXED_VALUE);
|
||||
assertThat(resolver.isMultipart(request)).isFalse();
|
||||
|
||||
request.setContentType(MediaType.MULTIPART_RELATED_VALUE);
|
||||
assertThat(resolver.isMultipart(request)).isFalse();
|
||||
|
||||
request = new MockHttpServletRequest("PUT", "/");
|
||||
assertThat(resolver.isMultipart(request)).isFalse();
|
||||
|
||||
request.setContentType(MediaType.MULTIPART_FORM_DATA_VALUE);
|
||||
assertThat(resolver.isMultipart(request)).isTrue();
|
||||
|
||||
request.setContentType(MediaType.MULTIPART_MIXED_VALUE);
|
||||
assertThat(resolver.isMultipart(request)).isFalse();
|
||||
|
||||
request.setContentType(MediaType.MULTIPART_RELATED_VALUE);
|
||||
assertThat(resolver.isMultipart(request)).isFalse();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1140,18 +1140,30 @@ another based on Servlet 3.0 multipart request parsing.
|
|||
|
||||
To enable multipart handling, you need to declare a `MultipartResolver` bean in your
|
||||
`DispatcherServlet` Spring configuration with a name of `multipartResolver`.
|
||||
The `DispatcherServlet` detects it and applies it to the incoming request. When a POST with
|
||||
content-type of `multipart/form-data` is received, the resolver parses the content and
|
||||
wraps the current `HttpServletRequest` as `MultipartHttpServletRequest` to
|
||||
provide access to resolved parts in addition to exposing them as request parameters.
|
||||
The `DispatcherServlet` detects it and applies it to the incoming request. When a POST
|
||||
with a content type of `multipart/form-data` is received, the resolver parses the
|
||||
content wraps the current `HttpServletRequest` as a `MultipartHttpServletRequest` to
|
||||
provide access to resolved files in addition to exposing parts as request parameters.
|
||||
|
||||
|
||||
[[mvc-multipart-resolver-commons]]
|
||||
==== Apache Commons `FileUpload`
|
||||
|
||||
To use Apache Commons `FileUpload`, you can configure a bean of type
|
||||
`CommonsMultipartResolver` with a name of `multipartResolver`. You also need to
|
||||
have `commons-fileupload` as a dependency on your classpath.
|
||||
`CommonsMultipartResolver` with a name of `multipartResolver`. You also need to have
|
||||
the `commons-fileupload` jar as a dependency on your classpath.
|
||||
|
||||
This resolver variant delegates to a local library within the application, providing
|
||||
maximum portability across Servlet containers. As an alternative, consider standard
|
||||
Servlet multipart resolution through the container's own parser as discussed below.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Commons FileUpload traditionally applies to POST requests only but accepts any
|
||||
`multipart/` content type. See the
|
||||
{api-spring-framework}/web/multipart/commons/CommonsMultipartResolver.html[`CommonsMultipartResolver`]
|
||||
javadoc for details and configuration options.
|
||||
====
|
||||
|
||||
|
||||
[[mvc-multipart-resolver-standard]]
|
||||
|
|
@ -1200,6 +1212,16 @@ The following example shows how to set a `MultipartConfigElement` on the Servlet
|
|||
Once the Servlet 3.0 configuration is in place, you can add a bean of type
|
||||
`StandardServletMultipartResolver` with a name of `multipartResolver`.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
This resolver variant uses your Servlet container's multipart parser as-is,
|
||||
potentially exposing the application to container implementation differences.
|
||||
By default, it will try to parse any `multipart/` content type with any HTTP
|
||||
method but this may not be supported across all Servlet containers. See the
|
||||
{api-spring-framework}/web/multipart/support/StandardServletMultipartResolver.html[`StandardServletMultipartResolver`]
|
||||
javadoc for details and configuration options.
|
||||
====
|
||||
|
||||
|
||||
|
||||
[[mvc-logging]]
|
||||
|
|
|
|||
Loading…
Reference in New Issue