aurelia / http-client

A simple, restful, message-based wrapper around XMLHttpRequest.
MIT License
62 stars 59 forks source link

Content-Type header is overridden to text/plain in no-cors mode #186

Closed torgeirhansen closed 5 years ago

torgeirhansen commented 5 years ago

I'm submitting a bug report

Please tell us about your environment:

Current behavior: Sending a post with a json body and no-cors mode fails (I need to talk to a public api that does not support OPTIONS). The failure is that the Content-Type header is overwritten to "text/plain;charset=UTF-8".

Expected/desired behavior: I expect the Content-Type to be application/json. (I've tried both setting it manualy, and relying on the "body: json({...})" convention.

it('makes proper requests with json() inputs with no-cors', (done) => {
  fetch.and.returnValue(emptyResponse(200));
  client
    .fetch('http://example.com/some/cool/path', {
      method: 'post',
      body: json({ test: 'object' }),
      mode: 'no-cors'
    })
    .then(result => {
      expect(result.ok).toBe(true);
    })
    .catch(result => {
      expect(result).not.toBe(result);
    })
    .then(() => {
      expect(fetch).toHaveBeenCalled();
      let [request] = fetch.calls.first().args;
      expect(request.headers.has('content-type')).toBe(true);
      expect(request.headers.get('content-type')).toMatch(/application\/json/);
      done();
    });
});

The problem seems to be in buildRequest(): https://github.com/aurelia/fetch-client/blob/9e16ac6875c622261a0014dc593b23c313ae16f4/src/http-client.ts#L177

That method returns a request that has zero headers, even if the requestInit object has headers.

Then it runs this: https://github.com/aurelia/fetch-client/blob/9e16ac6875c622261a0014dc593b23c313ae16f4/src/http-client.ts#L183

.. but that does not seem to actually do -anything-.

Looking at MDN: https://developer.mozilla.org/en-US/docs/Web/API/Request/headers it states that "The headers read-only property of the Request interface contains the Headers object associated with the request."

So I'm guessing that L183 itself is a dud and thus the real bug.

bigopon commented 5 years ago

The line at https://github.com/aurelia/fetch-client/blob/9e16ac6875c622261a0014dc593b23c313ae16f4/src/http-client.ts#L177 uses requestInit, which is a merge of custom headers so it should be there, I'm not sure why you are experiencing this issue.

bigopon commented 5 years ago

line 183 seems to only works if the body sent is a json string, can you check to see if you accidentally sent something else?

torgeirhansen commented 5 years ago

I see while debugging in Chrome that #183 is triggered, but it does not change the state of the object. And since this also fails in other browsers and when running the modified test using npm run test I'm assuming (which obviously can be wrong) that the headers object cannot be used in the manner attempted by the code

If it wasn't clear none of the headers passed in via the init object, so content type is only one of the problems.. (so possibly my bad for putting emphasis on content type which is the thing I really need)

torgeirhansen commented 5 years ago

I've created a simple test you can try yourself.

Create a new aurelia project w/typescript, npm install aurelia-fetch-client and drop in app.html and app.ts from here: https://aureliafetchfail.blob.core.windows.net/files/app.html https://aureliafetchfail.blob.core.windows.net/files/app.ts

It contains four tests, two with no-cors (with and without custom header) and two without setting the mode (with and without custom header).

It shows that when using mode: no-cors; all headers are simply discarded, and content-type is set to "text/plain;charset=UTF-8" instead of the expected "application/json".

torgeirhansen commented 5 years ago

I don't fully get it, but this seems to be related to the request-no-cors guard on the Headers class (https://fetch.spec.whatwg.org/#example-headers-class).

So I'm guessing this can be closed, I'll just use something XMLHttpRequest based instead of the fetch api.