Skip to content
This repository has been archived by the owner on Feb 6, 2018. It is now read-only.

Setting 'content-type' header properly with boundary #110

Closed
ghost opened this issue Apr 19, 2017 · 3 comments
Closed

Setting 'content-type' header properly with boundary #110

ghost opened this issue Apr 19, 2017 · 3 comments

Comments

@ghost
Copy link

ghost commented Apr 19, 2017

In a Feathers server I had set up a service for uploading images following the official guide on file uploads, using multer as middleware and all.
The code is exactly the same as that tutorial, https://docs.feathersjs.com/guides/advanced/file-uploading.html, because it works when I use Postman to test it.
In the client I use react-dropzone to get a file due for uploading, and found out that the reason why multer doesn't process the image is because the content-type header isn't being set accordingly. It needs to be in a format of: multipart/form-data --==...

Now, this cannot be achieved by hooks.

  1. Trying to set 'content-type': 'multipart/form-data' results in the server receiving: 'content-type': 'application/json, multipart/form-data',.
  2. Trying to set the boundary like this with the above: boundary=----WebKitFormBoundaryDKc3PiteTDBUUMlm results in the server content-type header as 'application/json, multipart/form-data; boundary=----WebKitFormBoundaryDKc3PiteTDBUUMlm' which you'd expect to work, but it turns out it doesn't, multer doesn't run. It appears to be a parameter that isn't supposed to be manually put in.

It should be noted that Postman does this automatically, when you try to override the request header there with a simple 'content-type':'multipart/form-data' the boundary parameter will not be supplied, thus an error. So in Postman I did not supply any headers, and the Feathers upload service simply works, I can see the proper header being received as well.

Upon research I found that if you're using forms in React, you can use the encType property to set the content type properly, and it will trigger. But I wasn't using a form, I was doing a service .create(...) call.
superagent has something like this: http://visionmedia.github.io/superagent/#setting-the-content-type, but how does one achive this with Feathers?

System configuration

Module versions (especially the part that's not working):
In the server:
dauria@1.1.5
feathers@2.1.1
feathers-configuration@0.3.3
feathers-errors@2.5.0
feathers-hooks@1.8.1
feathers-memory@1.1.0
feathers-rest@1.7.2
multer@1.3.0

Client side:
feathers-client@1.9.0
feathers-rest@1.7.1
feathers-hooks@1.8.1
superagent@2.3.0

NodeJS version:
6.9.1
Operating System:
Windows 10
Browser Version:
Latest Chrome
Module Loader:
For the client:
webpack@1.14.0
webpack-dev-middleware@1.9.0
webpack-dev-server@1.16.2

@daffl
Copy link
Member

daffl commented Apr 19, 2017

You can set headers by adding a headers property in params. In you case calling

client.service('upload').create(data, {
  headers: {
    'content-type': 'multipart/form-data'
  }
});

@marshallswain
Copy link
Member

I missed this in the docs, earlier, but looks like it's in place on this page: https://docs.feathersjs.com/api/rest.html#client

@ghost
Copy link
Author

ghost commented Apr 20, 2017

I might have said hooks, but whether you do it in the create call or a before hook is the same.
I don't know how I missed this earlier when I was looking for prior issues, but @ekryski puts it well. #102 (comment)
The guide on file uploading works well because it uses a native form element, IIRC.

In superagent, you can either do .set('enctype', 'multipart/form-data') or construct a FormData (which the library itself does.) ladjs/superagent#746 Nevertheless there is a way to do it in superagent, so I guess I will specifically opt out of the upload service create call in favor of doing a direct request like that.

https://www.w3.org/TR/html401/interact/forms.html#h-17.13.4 also defines behavior of the multipart/form-data content type. User agent being the browser, when using a native form element with enctype='multipart/form-data', it is the browser that does the work of constructing the payload and updating the content-type header with a boundary. This is also what Postman does, and superagent deals with this by simulating using FormData.

I do think this can be closed because there is a separate open issue regarding this already. Will update this with a relevant solution if I come up with one, though.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants