Content-Type header is overridden to text/plain in no-cors mode
torgeirhansen opened this issue · comments
I'm submitting a bug report
- Library Version:
1.8.2 and also current master-branch.
Please tell us about your environment:
-
Operating System:
Win 10 -
Node Version:
11.15.0 -
NPM Version:
6.9.2 -
JSPM OR Webpack AND Version
Testet with webpack 4.27.0 and 4.28.4 -
Browser:
Chrome 75.0.3770.100
Edge 44.17763.1.0
Firefox 67.0.4 -
Language:
TypeScript
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.
- ** Reproduction **
Just by modifying one of the existing tests to include "mode: 'no-cors'" it's easy to reproduce:
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(); }); });
- What is the motivation / use case for changing the behavior?
This isn't the first time I've hit this bug, so my motivation is to get this fixed ;)
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.
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.
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?
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)
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".
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.