The surprise multipart/form-data
Building up and sending an Ajax request is so much easier than it ever used to be. No longer must we hassle ourselves with
XMLHttpRequest, never mind the horror of ActiveX’s
ActiveXObject("Microsoft.XMLHTTP"). The Fetch API is here (and it is polyfilled for older browsers). Then there’s the
But you can still get things wrong. I can definitely get things wrong.
So I wanted to write about what I got wrong to remind myself for the future. My mistakes involved the Fetch API,
FormData and a simple Express server in Node.js.
I couldn’t POST any data
It was simple, I wanted to POST some data to my server. I had Express set up, I’d installed body-parser (normally something I forget to do until this kind of problem comes along), I had a route that was ready to receive my data and do something with it.
It looked a little like this:
OK, it was more complicated than that, but that’s all we need to demonstrate this.
The front end was going to be even easier.
The plan was simple: run the server, run the front end code, see “bar” printed in the console, celebrate.
I searched up and down the
request object, looking for that simple piece of data that I had sent. I checked in all the places I thought it might be
request.query, Express has all of those you know. I checked in plenty of places I didn’t think it would be. Finally I did what any sensible developer would do. I asked the internet.
The internet is a wonderful support network
I love that out there is a resource where I can ask questions and people respond and help me. The internet came up trumps in this case, I asked and many people chimed in with ways to fix the issue.
The first solution was to set the content type to JSON and just send JSON to the server.
This worked, but I was confused. I had this really easy
FormData object to work with, but the solution was to throw it away and use
JSON.stringify? It didn’t seem right. It worked but I wanted to persist and make it work the way I had intended.
It works in Rails
It turns out that body-parser doesn’t understand
multipart/form-data encoded forms (though as Edd pointed out, Rails does). And
FormData, when added to a Fetch API request (or an
XMLHttpRequest as it happens, I checked), will set the content type to
multipart/form-data. It actually says that right here in the first paragraph of the MDN documentation. In bold.
I like to say that “people don’t read things on the internet”. I don’t read things on the internet.
In my defence, I would have thought that body-parser might parse the body of the request. Once again skimming over the documentation was my downfall. Check out line 2 of the body-parser readme.
In fact, the body-parser readme doesn’t just say that it won’t handle
multipart/form-data bodies, it even goes as far as suggesting other modules to use for those requests.
I ended up using formidable via the express-formidable middleware. Our example server now looks like this:
FormData objects set the content type of a Fetch API (or
XMLHttpRequest) request to
body-parser doesn’t support parsing the body of a
multipart/form-data request. But there are many options that do.
The internet is a very helpful place. Thank you to Edd and others who suggested what I might be doing wrong.
READ THE DOCUMENTATION. Then probably read it again just to make sure.
There are no surprises
There are actually very few surprises in development, particularly when using modern browser APIs and well supported frameworks and reading the documentation. I learned quite a bit from this one small episode as you can see above. The next thing I need to do is write some documentation for someone else. Eventually, they’ll read it and be thankful as I was.
To keep up with posts on this blog, you can subscribe via RSS or follow me on DEV.