Bug 49711 - HttpServletRequest#getParts() does not work in a Filter
Summary: HttpServletRequest#getParts() does not work in a Filter
Status: RESOLVED FIXED
Alias: None
Product: Tomcat 7
Classification: Unclassified
Component: Servlet & JSP API (show other bugs)
Version: 7.0.0
Hardware: PC Windows XP
: P2 enhancement (vote)
Target Milestone: ---
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-08-05 16:39 UTC by balusc
Modified: 2014-01-19 22:25 UTC (History)
2 users (show)



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description balusc 2010-08-05 16:39:53 UTC
In order to have the ability to process multipart/form-data transparently with help of the new Servlet 3.0 HttpServletRequest#getParts(), a Filter is the most suitable place for this. 

This works fine in Glassfish v3. However, in Tomcat the getParts() returns null and it works only inside a servlet with @MultipartConfig annotation.

This is too strict. This makes it hard if not impossible to process multipart/form-data requests transparently with help of a Filter (i.e. creating a new parametermap and replacing the original one in HttpServletRequest).

It is true that the Servlet 3.0 spec tells nothing about the use of this method inside a Filter, but this is in my opinion an oversight. There is no other way to obtain the parts than parsing the stream yourself with good 'ol Apache Commons FileUpload.

Since it works fine in Glassfish v3, I'd suggest to make Tomcat 7 that lenient as well.
Comment 1 Mark Thomas 2010-08-05 16:51:57 UTC
I've just read the spec and my reading of the spec is that this is expected to work. A quick look at the code suggests it should work. If you want to dig into this yourself, start at line 2499 of o.a.catalina.connector.Request
Comment 2 balusc 2010-08-05 17:11:24 UTC
Correction: it didn't return null, it returned an empty collection.

I will dig in the source.
Comment 3 balusc 2010-08-05 17:57:50 UTC
Well, the getWrapper().getMultipartConfigElement() at line 2493 always returns null and thus an empty collection will be returned. Only when I call getParts() inside a Servlet with @MultipartConfig, it works. But the intent is to call getParts() inside a Filter. The getWrapper() always returns the target JSP/Servlet associated with the request which in my case does not necessarily have the @MultipartConfig annotation (or cannot have one because it's a 3rd party one out of your control, e.g. FacesServlet).
Comment 4 Mark Thomas 2010-08-22 19:03:13 UTC
If the Servlet doesn't have the @MultipartConfig annotation then getParts() should not work. Tomcat is therefore specification compliant in this regard.

I'm not adverse to adding a (probably per context) configuration attribute to relax this requirement. Therefore, I am changing this to an enhancement request.
Comment 5 balusc 2010-08-22 19:10:21 UTC
Thank you. This is imo an oversight in the Servlet 3.0 specification. I will report it sooner or later.
Comment 6 Christopher Schultz 2010-11-08 10:15:52 UTC
If @MultipartConfig in a servlet is the sole way to trigger multipart handling during a request, then a Filter must be able to check the target servlet to determine if Request.getParts will work (which I don't believe is possible). I agree with balusc's assertion that this is an oversight in the specification.

My only question is what the overall behavior should be. If a Filter calls Request.getParts and the content-type of the request is multipart/form-data, should Tomcat simply parse it as a multipart request regardless of the presence (or absence) of an @MultipartConfig annotation on the servlet?

I would argue that Tomcat /should/ go ahead and do this. I would also argue that this ought to be the /default configuration/ as well.

There are some web applications where a Filter is expected to be the content generator. All Apache Struts 2 applications are like this: the front controller is implemented as a Filter instead of as a Servlet (don't ask me why this is the case). Ignoring the fact that S2 provides multipart parsing itself, S2 applications would not be able to use the 3.0 specification for loading multipart data because the request will never reach a servlet (or, at best, the request would have to be mapped to both a Filter which does the real work, and to a dummy servlet that simply has the @MultipartConfig annotation just to achieve the goal).
Comment 7 balusc 2010-11-15 19:40:59 UTC
FYI: this issue is currently reported on servlet-spec-public: https://servlet-spec-public.dev.java.net/issues/show_bug.cgi?id=14
Comment 8 Christopher Schultz 2011-01-20 16:20:54 UTC
Working on a patch.
Comment 9 Christopher Schultz 2011-01-21 12:48:10 UTC
Fixed. Will be available in 7.0.7 onwards.

See documentation for <Connector> for how to enable this.
Comment 10 Christopher Schultz 2011-01-21 13:29:26 UTC
Patch needs tweaking. Configuration belongs in the Context, not in the Connector.
Comment 11 Christopher Schultz 2011-01-21 13:40:26 UTC
Fixed (again). Will be in 7.0.7 onwards.
Comment 12 nsnospam3 2011-06-27 13:06:00 UTC
Fixed in 7.0.7, but back in 7.0.16?? 
Please tell me if I'm wrong, but the code from BalusC works with Glassfish v3.1 it dosn't with Tomcat 7.0.16. HttpServletRequest#getParts() in the filter returns an empty collection.
Do anybody know more about it?
Comment 13 Mark Thomas 2011-06-27 13:09:34 UTC
See allowCasualMultipartParsing on the Context and ask on the users list if you have any further questions.
Comment 14 noel 2014-01-19 20:10:20 UTC
This problem also exists in Tomcat 7.0.47.
Comment 15 Konstantin Kolinko 2014-01-19 22:25:32 UTC
(In reply to noel from comment #14)
> This problem also exists in Tomcat 7.0.47.

The burden of proof is yours. You provided no proof.

Please discuss this on the users mailing list so that others confirm
that there is an issue, before reopening or submitting other issue.

Note that

1. The testsuite contains testcases for this feature,

org.apache.catalina.core.TestStandardContext#testBug49711()
org.apache.catalina.connector.TestRequest#testBug54984()

So it does work, if configured properly.

2. You must read documentation on "allowCasualMultipartParsing" option, as mentioned above. It is off by default.

http://tomcat.apache.org/tomcat-7.0-doc/config/context.html

Re-closing as FIXED.