Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HiddenHttpMethodFilter does not support multipart requests [SPR-6594] #11260

Closed
spring-projects-issues opened this issue Dec 21, 2009 · 10 comments
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Dec 21, 2009

Oliver Drotbohm opened SPR-6594 and commented

HiddenHttpMethodFilter currently does not work when handling multipart request, as it relies on request.getParameter(..) which does not return the actual parameter's value in multipart requests.

As I can understand that one might want to keep the filter independent of Spring MVC, I'd suggest to introduce a subclass that might lookup a configured multipartResolver from the application context and use it to obtain the parameters. As we deal with a filter this would require the resolver being declared inside the ApplicationContext loaded by the ContextLoaderListener. This feels a little ugly as one probably should tend to avoid web things inside this ApplicationContext.

As the only existing implementation is CommonsMultipartResolver and this implementation uses a static method of ServletFileUpload a reasonable way might also be just to check the availablity of Commons Fileupload in the classpath and using this method to determine the multipart nature of the request then.


Affects: 3.0 GA

Issue Links:

Referenced from: commits 2c9753a, 0eabef0

4 votes, 11 watchers

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

This should work if put a MultipartFilter into your web.xml, kicking in before the HiddenHttpMethodFilter. The latter will then receive a wrapped MultipartHttpServletRequest which should behave properly in terms of parameter retrieval.

MultipartFilter needs a reference to the MultipartResolver bean in the root WebApplicationContext - but at least that's concealed within that extra filter then, outside of HiddenHttpMethodFilter itself. Essentially, multipart resolution needs to happen in a filter here because we have another filter accessing request parameters; doing multipart resolution in the DispatcherServlet is too late for this scenario since it happens after the filter chain.

Juergen

@spring-projects-issues
Copy link
Collaborator Author

Oliver Drotbohm commented

Hey Jürgen,

I've been playing around with your suggestion a little but that doesn't seem to workout. HandlerMethodInvoker.resolveRequestParam(..) checks, whether the native request is a MultipartRequest (line 420). As the HiddenHttpMethodFilter wraps the MultipartServletRequest into its own decorator, this evaluates to false and the lookup is rather made via parameters than on the file.

I wonder if altering the MultipartServletRequest to include the keys of the file map into the parameter lookup would fix this?

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

We detect a native MultipartRequest even when decorated now - which should work fine with HiddenHttpMethodFilter. I'll also add a comment to HiddenHttpMethodFilter's javadoc, clarifying that a MultipartFilter (if any) needs to run first.

I haven't tested this in integration yet. Would be great if you could give it a try :-)

Juergen

@spring-projects-issues
Copy link
Collaborator Author

Jakobi commented

Hi!

I put the Spring MultipartFilter before the HiddenHttpMethodFilter in my web.xml filter chain. But the upload field of my model attribute is always set to null when I'm using the PUT method. With POST method everything works fine.

here the interessting part of my web.xml:

<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param><init-param><param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param></filter>


	<filter>
		<filter-name>multipartFilter</filter-name>
		<filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
		<init-param>
			<param-name>multipartResolverBeanName</param-name>
			<param-value>multipartResolver</param-value>
		</init-param>
	</filter>


	<filter>
		<filter-name>httpMethodFilter</filter-name>
		<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
	</filter>

	<filter>
		<filter-name>UrlRewriteFilter</filter-name>
		<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
	</filter>

	<filter>
		<filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
		<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
	</filter>

	<filter-mapping>
		<filter-name>multipartFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	<filter-mapping>
		<filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	<filter-mapping>
		<filter-name>springSecurityFilterChain</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	<filter-mapping>
		<filter-name>CharacterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	<filter-mapping>
	<filter-name>httpMethodFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

	<filter-mapping>
		<filter-name>UrlRewriteFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

Any suggestions?

@spring-projects-issues
Copy link
Collaborator Author

Jakobi commented

I justed debugged my app: The MultipartFilter is definitely applied before the HiddenHttpMethodFilter. Additionally I get the following debug messages:

org.springframework.web.multipart.commons.CommonsMultipartResolver - Found multipart file [upload] of size 3446 bytes with original filename [images.jpg], stored in memory
org.springframework.web.servlet.DispatcherServlet - DispatcherServlet with name 'myapp' processing PUT request for [/myapp/app/form/]

But in my Controller upload is NULL...

@spring-projects-issues
Copy link
Collaborator Author

Jakobi commented

My problem seems to be a binding issue..so it's not a problem of HiddenHttpMethodFilter and CommonsMultipartResolver.

Thanks anyway...

@spring-projects-issues
Copy link
Collaborator Author

Vitaly Polonetsky commented

The HiddenHttpMethodFilter is still causing problems with binding:
ServletRequestDataBinder.bind() checks whether the request is of MultipartRequest type (line 106) and it fails because the MultipartRequest is wrapped into DefaultMultipartHttpServletRequest.

@spring-projects-issues
Copy link
Collaborator Author

Vitaly Polonetsky commented

... small correction:
the MultipartRequest is wrapped into HttpMethodRequestWrapper !

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Jan 19, 2011

Vitaly Polonetsky commented

My comments are related to #12451 (should link between the two jiras)

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Jan 20, 2011

Juergen Hoeller commented

Well spotted, the solution for this original issue in Spring 3.0.2 addressed the problem for WebRequestDataBinder (as used by @MVC data binding) only. We'll use #12451 for tracking an equivalent solution for ServletRequestDataBinder.

Juergen

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants