Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

POST requests that work with Axios throw CORS error with Redaxios #84

Open
Nantris opened this issue May 13, 2022 · 9 comments
Open

POST requests that work with Axios throw CORS error with Redaxios #84

Nantris opened this issue May 13, 2022 · 9 comments

Comments

@Nantris
Copy link

Nantris commented May 13, 2022

First, thank you for this awesome project! What a huge transfer size savings Redaxios is over Axios.

We have some code like below that works fine with Axios but fails with Redaxios:

 const response = await axios({
  method: 'POST',
  url: getApiUrl(),
  data: {
    ...formData,
  },
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
  },
});

We get:

Access to fetch at 'https://example.com/' from origin 'http://localhost:1212' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

It seems possibly related to this question/answer

@Nantris Nantris changed the title Working Axios code throws CORS errors on POST requests in Redaxios POST requests that work with Axios throw CORS error with Redaxios May 13, 2022
@Nantris
Copy link
Author

Nantris commented May 18, 2022

@developit any thoughts on this? Is Redaxios supposed to support application/x-www-form-urlencoded content-type?

@developit
Copy link
Owner

developit commented May 20, 2022

Are you able to show the CORS preflight request and response? It seems like the cors error is masking a failure here relating to the request body encoding.

In your example code, what is the formData value? Is it a plain object, or a FormData instance?

My guess right now is that Axios automatically switches to form-encoding object body values if an x-www-form-encoded content-type is set.

One way to check this would be to see if the following works:

const response = await axios({
  method: 'POST',
  url: getApiUrl(),
  data: new URLSearchParams(formData),
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
  },
});

@Nantris
Copy link
Author

Nantris commented May 21, 2022

Thanks very much for your reply @developit!

In your example code, what is the formData value? Is it a plain object, or a FormData instance?

It is. I tried now with your suggestion but unfortunately it fails in a different way. I no longer see a CORS error, but instead the API endpoint doesn't respond as expected - it returns an HTTP 200 OK status code, but the actual API code fails to process the passed data properly, and returns a failure message.

The Axios payload looks like below - and the failing Redaxios payload (without URLSearchParams) looks the same:

{"endpoint":"ourEndpoint","name":"test","email":"[email protected]","applicationVersion":"x.x.x","issue":"test only"}

The Redaxios payload (with URLSearchParams) looks like this:

endpoint=ourEndpoint&name=test&email=test%40test.com&applicationVersion=x.x.x&issue=test+only

The request headers (minus the User-Agent) for Axios look like this:

:authority: api.example.com
:method: POST
:path: /
:scheme: https
accept: application/json, text/plain, */*
accept-encoding: gzip, deflate, br
accept-language: en-US
cache-control: no-cache
content-length: 134
content-type: application/x-www-form-urlencoded
origin: http://localhost:1111
pragma: no-cache
referer: http://localhost:1111/
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: cross-site

For Redaxios (without URLSearchParams) look like this:

content-type: application/json
Referer: http://localhost:1111/

and with URLSearchParams:

:authority: api.example.com
:method: POST
:path: /
:scheme: https
accept: */*
accept-encoding: gzip, deflate, br
accept-language: en-US
cache-control: no-cache
content-length: 114
content-type: application/x-www-form-urlencoded
origin: http://localhost:1111
pragma: no-cache
referer: http://localhost:1111/
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: cross-site

Any clues there? I see differences in the accept header, and also the casing of the referer header, though I doubt that one matters.

@Nantris
Copy link
Author

Nantris commented May 21, 2022

Ah I think I've found a fix, and it's quite simple! It looks like Axios maybe applies JSON.stringify to the object passed as data.

https://programmerlib.com/how-to-send-application-x-www-form-urlencoded-format-data-with-axios-in-vue/

Indeed, wrapping our code to look like this works:

  data: JSON.stringify({
    ...formData,
  }),

Is this logic something you'd be open to integrating into Redaxios to match Axios so we wouldn't need to modify all of our request code?


I suspect the URLSearchParams should probably work too, based on that resource and my other reading - but in my testing, passing an object to the URLSearchParams constructor doesn't result in the data actually being added as an entry. It will only work in my testing (in Firefox 100) if I use URLSearchParams.append(). Not sure what the issue might be there.

@Nantris
Copy link
Author

Nantris commented Jun 15, 2022

Friendly bump. @developit what do you think? Could this be integrated directly into redaxios?

@Nantris
Copy link
Author

Nantris commented Jun 28, 2022

Friendly bump @developit, whenever you have a chance. I think this would be a valuable addition to Redaxios.

@Nantris
Copy link
Author

Nantris commented Oct 25, 2022

Friendly bump.

@developit
Copy link
Owner

Hey, sorry for the inactivity on this. I haven't had time to make the change because it requires a fair amount of byte-shaving to offset (the string "application/x-www-form-encoded" is very long). I'm hoping I can come up with a clever solution (eg: browser sending the header by using FormData to encode?), but haven't found one yet.

The affected lines are these ones:

redaxios/src/index.js

Lines 174 to 175 in ad40de9

data = JSON.stringify(data);
customHeaders['content-type'] = 'application/json';

@Nantris
Copy link
Author

Nantris commented Jan 10, 2023

Thanks for the update @developit!

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

No branches or pull requests

2 participants