restful.js icon indicating copy to clipboard operation
restful.js copied to clipboard

FormData in POST is treated as JSON

Open bep opened this issue 9 years ago • 13 comments

It should be multipart/form-data with content-type and boundaries set by the browser.

Doing a fetch POST with the same form object works:

fetch('/api', {
            method: 'post',
            body: multiformData
        });

See #46

bep avatar Jan 31 '16 17:01 bep

Hi,

Have you tried to set the correct Content-Type header? If you don't, restul.js will assume it is JSON and will set it to application/json;charset=UTF-8 (see https://github.com/marmelab/restful.js/blob/master/src/model/endpoint.js#L25).

RobinBressan avatar Jan 31 '16 20:01 RobinBressan

Yes, if I set the correct content type header the server complains about missing boundaries. I have spent some hours reading about and debugging this, and in this case the trick is to let the browser handle everything (setting Content-Type and correct boundaries between the parts).

So, for restful.js I guess a special check for FormData would do it.

bep avatar Jan 31 '16 20:01 bep

You can use a requestInterceptor to deal with the config object forwarded to fetch. This way you should be able to remove the Content-Type header.

RobinBressan avatar Jan 31 '16 21:01 RobinBressan

The requestInterceptor seems to be tiggered too late in the game.

res.addRequestInterceptor((config) => {
            const {
                data, headers, method, params, url
            } = config;

            delete headers["Content-Type"];
            return {
                headers
            };
        });

The correct content type doesn't get set by the browser.

bep avatar Jan 31 '16 22:01 bep

Any solution for this?

cristianfierro avatar Apr 13 '16 15:04 cristianfierro

waiting the solution too

sohibul avatar May 11 '16 06:05 sohibul

I've had a similar problem but I do not experience the same issues @bep has. In my case the following was the case. When sending in a standard JS object as body (like I think everyone is doing by default) it gets JSON.stringify()'d by the browser when constructing the request and it looks like restfull.js is treating it as JSON, but in fact the browser does this. I've fixed this issue by formatting the data from the form like the browser expects it (like GET variables only in the body of the request) with a function in the requestInterceptor like so:

res.addRequestInterceptor((params) => {
  const {data, headers} = params;
  let str = '';
  if (data){
    Object.keys(data).forEach((key) => {
      str += ( str.length ? '&' : '' ) + key + '=' + data[key];
    });
    headers['Content-Type'] = 'multipart/form-data';
  }

  return {
    headers,
    data: str
  };
});

And experienced no other issues thus far. Hope it helps in your cases.

PM5544

PM5544 avatar May 11 '16 07:05 PM5544

@PM5544 so, you pass the data as json object?

sohibul avatar May 11 '16 08:05 sohibul

@sohibul To restfull.js yes and then it gets reformatted by the interceptor to the url-parameter format the backend expects when receiving multipart/form-data.

PM5544 avatar May 11 '16 08:05 PM5544

@PM5544 the main point of this issue is to make sure it is handled natively and effectively as a multiform formdata stream by the browser.

It should be a simple conditional fix to this library.

bep avatar May 11 '16 08:05 bep

@bep yes i understand your point. the reason of my reply was to give others with similar issues a way to work around it until a long term solution was formed, if @RobinBressan sees the need to.

PM5544 avatar May 11 '16 08:05 PM5544

@PM5544 do you have tried to send file object? I need multipart/form-data for upload file

sohibul avatar May 11 '16 09:05 sohibul

@sohibul nope I have not, but I assume it's better left up to the browser to directly connect to an upload service on the backend by using a standard form with an input with type="file".

PM5544 avatar May 11 '16 11:05 PM5544