You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cocoon.apache.org by Stu Baurmann <st...@logicu.com> on 2008/04/13 09:38:03 UTC

Workaround for Safari 3.x problem with redirect after multipart upload

Howdy folks,

I discovered a problem in using a redirect after a multipart upload, 
affecting the combination of Cocoon 2.1.10 and Safari 3.x on Mac. 

The symptom is a stacktrace from the CocoonServlet saying  
"MultipartException: Malformed Stream"

It is really Safari that is misbehaving.  The problem is similar to what is
described here:

http://jira.codehaus.org/browse/GRAILS-1938

Multipart upload from Safari into Cocoon works just fine in the cases we
have tested.
The browser uses POST to submit the multipart data.   But after the upload
completes, if 
we redirect the browser to GET another URL (e.g. a "Thank you for your
upload" page),
Safari does something bad.  It sends the GET request as instructed, but it
also includes
a header like:

Content type: multipart/form-data; boundary=----WebKitFormBoundaryCSofPC

...which Cocoon interprets as indicating a multipart request, regardless of
the
fact that a multipart GET is rather unlikely.   Cocoon then expects to see
multipart
data in the request, and it does not, and so Cocoon throws a
"MalformedStreamException".

My guess is that this behavior by Safari is a violation of the MIME and/or
HTTP
specs.  Safari isn't really sending any multipart data on the redirected
GET, so 
it shouldn't send this  Content type header.  It seems like a bit of
residual state 
that is left in Safari after the redirect is causing it to re-send this
Content Type.

Note that I did not observe this same behavior in Safari on WindowsXP - only
in Safari on Mac.

Because one of our Cocoon applications has a significant number of Mac
Safari users, and it occurs to 
me that some other browsers may exhibit similar behavior (though I hope
not).
I created a workaround that allows Cocoon to ignore the multipart Content
type
header in situations where it is unlikely that the inbound data is really
multipart.

The cocoon code which controls this behavior (in version 2.1.10) is:

org.apache.cocoon.servlet.multipart.RequestFactory

...specifically, the getServletRequest()  method, which decides to process a
request as multipart if the 
following condition holds:

if ((contentType != null) &&
(contentType.toLowerCase().indexOf("multipart/form-data") > -1)) 

I have extended this condition so that it looks like the following, which is
hereby contributed
to the community.      If someone wants to use this patch as inspiration for
a real patch in the 
cocoon source, that's fine and dandy.
---------------------------------------------------------------------------------------
 if ((contentType != null) &&
(contentType.toLowerCase().indexOf("multipart/form-data") > -1)) {
	// It sorta looks like a multipart request, based on the content-type.
	// BUT, if it's a GET request, and content-length <= 0,  then it's 
	// probably not a valid multipart request.  Most multipart requests
	// are POSTS (I guess some are PUTS...).    More likely, it's a 
        // redirected GET from Safari.    (We could check User-Agent,
too...)

		String method = request.getMethod(); 
		int contentLength = request.getContentLength();
		String userAgent = request.getHeader("User-Agent");

		if ((contentLength <= 0) && method.equals("GET")) {
			String warningMsg = "Ignoring Content-Type " + contentType + " because
Method=" + method + " and Content-Length=" + contentLength + ". 
User-Agent=" + userAgent;
		                 // This should be a logger warning, but not sure how to
get a logger here.
				System.out.println(warningMsg);
				// After printing the warning, we take no further special action on the
request.
                               // It is treated like a regular GET

		} else {
			// Treat the request as a bona-fide multi-part request...

---------------------------------------------------------------------------------------
Additional Notes:  The usefulness of the Content-Length clue is debatable. 
I guess if someone 
is using GET to send multipart data, they might very well stream a large
block
of data with initially unknown length, leading to a Content-Length value of
"-1".     So, the 
most useful thing in this workaround (for me, at least), is the added check
on the HTTP method,
which is essentially denying the ability of the browser to send multipart
data using a GET request.

It would possibly be worthwhile to check
the User-Agent as well, if one thought that multipart-GET is reasonable, but
still
wanted to workaround the Safari bug.  Yet another option would be to try to
make the multipart parser robust to empty content, but that might lead to
more
subtle problems if we weren't careful.

peace,

Stu Baurmann
-- 
View this message in context: http://www.nabble.com/Workaround-for-Safari-3.x-problem-with-redirect-after-multipart-upload-tp16656737p16656737.html
Sent from the Cocoon - Users mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@cocoon.apache.org
For additional commands, e-mail: users-help@cocoon.apache.org