Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting '400 Bad Request' when using multipart/form-data as Content-Type in XHR

I have an AJAX request that sends out some data. The data respects the multipart/form-data specification.

The problem I'm facing is that the browser sets the Content-Type header to text/plain and it should be multipart/form-data.

I've tried doing this: request.setRequestHeader("Content-Type", "multipart/form-data"); but this gives out an 400 Bad Request error.

If I do request.setRequestHeader("Content-Typexxxx", "multipart/form-data"); there is no error, the "Content-Typexxxx" header is set but it obviously is no help to me.

I guess there is a list of valid Content-Type headers one can set and "multipart/form-data" isn't among them, but I cannot find a sollution to my predicament.

Sample of the data actually being sent:

Content-Type: multipart/form-data; boundary=l3iPy71otz

--l3iPy71otz
Content-Disposition: form-data; name="titluPublic"

Variation_1
--l3iPy71otz
Content-Disposition: form-data; name="nr_versiune"


--l3iPy71otz--

Thanks!

like image 965
Sorin Buturugeanu Avatar asked Jan 23 '11 12:01

Sorin Buturugeanu


1 Answers

You didn't set the boundary in your request header, as in:

request.setRequestHeader("Content-Type", "multipart/form-data; boundary=l3iPy71otz");

For more information, see RFC 2045:

5 Content-Type Header Field
[…]
Parameters are modifiers of the media subtype, and as such do not fundamentally affect the nature of the content. The set of meaningful parameters depends on the media type and subtype. Most parameters are associated with a single specific subtype. However, a given top-level media type may define parameters which are applicable to any subtype of that type. Parameters may be required by their defining content type or subtype or they may be optional. MIME implementations must ignore any parameters whose names they do not recognize.

For example, the "charset" parameter is applicable to any subtype of "text", while the "boundary" parameter is required for any subtype of the "multipart" media type.

Update: Another problem I found on the net appears when a charset is added to the Content-type in the request header, but not in the message boundaries in the body (this is also true for your test case). It doesn't seem a likely solution, but perhaps it helps.

In your case, explicitly add a charset to both the request header and in the message boundaries:

data.params += "--" + data.uniqid + "; charset=UTF-8" + data.crlf;
…
request.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + data.uniqid + "; charset=UTF-8");

Update 2: After trying this myself locally, I noticed the leading boundary wasn't recognized as such, but interpreted as the last parameter contents (on my more forgiving server). Perhaps that was causing Apache to throw a 400 Bad Request error.

After some trial and error, I noticed that that was caused because the server expected the charset to be in every boundary, even the last one. To prevent confusion, I decided to explicitly set the charset in the request header before the boundary parameter, so that the boundary would be the last parameter in the Content-type request header. After this, everything seemed to work fine.

data.params = "Content-Type: multipart/form-data; boundary=" + data.uniqid;
…
data.params += "--" + data.uniqid + data.crlf;
…
data.params += "--" + data.uniqid + "--";
…
request.setRequestHeader("Content-Type", "multipart/form-data; charset=UTF-8; boundary=" + data.uniqid);
like image 70
Marcel Korpel Avatar answered Nov 02 '22 15:11

Marcel Korpel