Axios: cannot get cross-site POST to work

Created on 11 Jan 2016  ·  70Comments  ·  Source: axios/axios

Hello,

Thanks for the great work.
Although that were some releases targeting cross-site requests, I still can't get it to work. I dug through the previous posts and tried adding:

  • crossDomain: true
  • xDomain: true
    *xDomainRequest: true

to the config. And none of them worked. (If this feature is actually available, updating the readme would help.)

Please advise ASAP. Thank you.

Most helpful comment

How is such a HUGE issue, not addressed?

All 70 comments

In addition, i'm also setting withCredentials to true in the config.

I just ran into this issue as well and it only seems to happen for me on Mac. I spent a good 3 days and nights trying to debug my network and decided on a whim to try this using a vanilla XHR request and realized the problem wasn't my network, but axios.

I too am doing cross-site requests with credentials set to true. Looking at the network request, you get an ERR_EMPTY_RESPONSE and it's like the request failed before it even left the browser.

This is my config:

const myApi = axios.create({
  baseURL: 'http://someUrl/someEndpoint',
  timeout: 10000,
  withCredentials: true,
  transformRequest: [(data) => JSON.stringify(data.data)],
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json',
  }
});'

If I get a chance I will try to look into this further.

Oh good I'm not crazy. :) Please look into this if possible.

Turns out my issue was unrelated to Axios. Cisco Anyconnect was blocking options requests from my machine... because reasons?

Cross domain requests don't require any extra config. It will fall back to using XDomainRequest for older IE. https://github.com/mzabriskie/axios/blob/master/lib/adapters/xhr.js#L22

Can you provide more details? What browser, OS, version of axios, any error messages.

I can't speak for Jenny but something in particular this library does causes requests to be block by Cisco Anyconnect default security which means it's possible other security settings do this too. I'm trying to track this down but no luck so far.

This can be reproduced by making a cross site request on a mac installed with cisco Anyconnect and possibly other VPN clients.

My environment is:

  • Axios 0.8.1
  • El Capitan
  • Chrome
  • Error msg: "No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access."

Note that the same request works with curl.

Thanks for looking into this!

With CORS a preflight request is made to the server to see if the request is allowed. You will need to have your server respond to requests that haveOPTIONS as request method by setting the header Acces-Control-Allow-Origin: * which will allow requests from any origin. Alternatively you can allow for just certain origins Acces-Control-Allow-Origin: http://example.com.

Yes, I understand that. But the server is not mine. I'm using a Baas (backend-as-a-service). And they have already added my domain to the allowed list. I have checked that other people using said Baas have not had such problems.

I'm just going off the error message that you provided, but based on that it doesn't sound like you baas has things working for you. It wouldn't fail using curl because the cross origin security is only a limitation within the browser.

Can you open the network tab in your browser and share what you get as the response to the OPTIONS request? Hopefully seeing the response data and headers will help debug this issue.

Thanks

Here are the headers:

image

Here's the response headers from GitHub when I use axios to get my user profile from their API:

screen shot 2016-01-19 at 11 36 54 am

You can see that GitHub adds the Access-Control-Allow-Origin: *. The response from your Baas is missing any Access-Control type headers.

I see I see hmm. Sorry for the super late reply. Let me look into this a bit more. Thank you very much.

I'm not sure if what I'm seeing is related or not. Basically, I can send an auth request to our remote server and get back a cookie, but then subsequent calls to the server _don't_ send the cookies along with them, resulting in an error.

Here are the headers from the POST call to login:
login

And now a followup GET call:
verify

The IP address listed under origin is my own, so that shouldn't be an issue. If this is the wrong place for this, I am happy to make a new issue, or attach to the appropriate existing one.

As a new wrinkle; I've tested a follow-up GET call using just straight XHR, and the cookie is sent along just fine. Doing the same call through Axios, however, results in the same issue I mentioned above.

Ugh. Please disregard - I wasn't sending things as expected through Axios :)

Im also facing the same issue.
OPTIONS Call goes thru, but POST calls gets stuck into cors.
http://stackoverflow.com/questions/36907693/axios-cors-issue-with-github-oauth-not-getting-access-token

How is such a HUGE issue, not addressed?

+1

+1

+1

+1

+1

+1

+1

@dsacramone what is the issue that you are seeing? It seems that most of the issues being reported are problems with server or false alarms. If there is a reproducible error that I can look at I am happy to work on a fix.

getting this too

XMLHttpRequest cannot load https://en.wikipedia.org/w/api.php?action=opensearch&format=json&search=fish. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.

also getting it using fetch to note. i think its chrome have recently made their request setting policy more strict, i think it will need some sort of header (not sure what tho).

here's some example (both served over https)

Example 1 - Works fine

axios.get('https://randomuser.me/api/')
  .then(function (response) {
    console.log(response.data);
  })
  .catch(function (error) {
    console.log(error);
  });

Exampel 2 - Not working - showing error ?

axios.get('https://en.wikipedia.org/w/api.php?action=opensearch&format=json&search=fish')
  .then(function (response) {
    console.log(response.data);
  })
  .catch(function (error) {
    console.log(error);
  });

here's the error response

[object Error] {
  config: [object Object] {
    data: undefined,
    headers: [object Object] { ... },
    maxContentLength: -1,
    method: "get",
    timeout: 0,
    transformRequest: [object Object] { ... },
    transformResponse: [object Object] { ... },
    url: "https://en.wikipedia.org/w/api.php?action=opensearch&format=json&search=fish",
    validateStatus: function validateStatus(status) {
      return status >= 200 && status < 300;
    },
    xsrfCookieName: "XSRF-TOKEN",
    xsrfHeaderName: "X-XSRF-TOKEN"
  },
  response: undefined
}

something that might be relevant is in the transformResponse ? i'm wondering what PROTECTION_PREFIX bit means?

[object Object] {
  0: function transformResponse(data) {
      /*eslint no-param-reassign:0*/
      if (typeof data === 'string') {
        data = data.replace(PROTECTION_PREFIX, '');
        try {
          data = JSON.parse(data);
        } catch (e) { /* Ignore */ }
      }
      return data;
    }
}

even trying

mode: 'no-cors'
in fetch still gives this error

i'm sure the answers pretty simple and just needs some sort of header, just not sure what tho, will keep playing around.

the wikipedia api might just be a wonky example,same error on others?

I delete this code,can work: axios.defaults.withCredentials = true

I got the wikipedia api to work fine with jsonp

var jsonp = require('jsonp');

// search for 'frog'
jsonp('https://en.wikipedia.org/w/api.php?action=opensearch&search=frog&format=json', null, function (err, data) {
  if (err) {
    console.error(err.message);
  } else {
    console.log(data);
  }
});

No extra configs required.

Getting the same error with axios. Here's my React component:

import React, { Component } from 'react'
import axios from 'axios'

export default class User extends Component {
  constructor(props){
    super(props)

    // axios.defaults.withCredentials = true

    const config = {
    method: 'get',
    url: 'https://api.airbnb.com/v2/users/2917444?client_id=3092nxybyb0otqw18e8nh5nty&_format=v1_legacy_show',
    headers: {'X-Requested-With': 'XMLHttpRequest'},
    responseType: 'json',
    withCredentials: true,
  }

    axios.request(config)
      .then(response => { console.log('response: ', response) });

  }

  render() {
    return (
      <div>User</div>
    )
  }
}

_Note: I can hit the API perfectly fine with Node request._

I'm running into the same error that @Sinistralis is. On the latest version of chrome in Mac OSX I'm getting net::ERR_EMPTY_RESPONSE on CORS requests that are made properly (my server handles all the CORS headers including OPTIONS just fine). It's strange because on iOS10 safari, the exact same code works with no problems. Will try to investigate a little more on my own to see how this might be resolved.

On an older mac (10.11) with the latest version of chrome, I cannot reproduce this error with the exact same code. This is very odd indeed. You may be able to reproduce by visiting this very simple app: http://lights.suyashkumar.com and inspecting the console (code is here. On some machines there will be no error and it'll redirect you to login. On others it won't redirect and will leave you on the main page.

Solved my error. For me, it was an issue with assigning a header in config.headers with a null value on application start (it pulls a value out of local storage, and initially, nothing is there). Assigning the value to be an empty string when the value is null solves the problem. I wonder if this is something that can or should be handled within axios (not sure if there's value in passing null headers to xhr if it breaks _sometimes_).

For others with a similar issue, I found that some VPN clients can also block OPTIONS requests (see here)

The misleading CORS error is still in axios. The fetch polyfill supports mode: 'no-cors' to fix this issue.

We need to do these kinds of requests to make requests against machines in other environments we operate, as well as on the same machine on different ports!

@dreki Please provide the description of the issue you mentioned.

You can't do a thing on the client-side, when the server simply does not accept requests from your origin. If you could, we'd have a huge security leak here (and with "we" I mean the whole internet)...

I think axios acts and reacts totally conformy here.

The important Response header is Access-Control-Allow-Origin which basically sets the valid origins, that are allowed to call this server-side service. If your client is not calling from any of these configured origins, the request will be declined with a console error like this:

XMLHttpRequest cannot load http://localhost:8080/v1/api/search?q=candles. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9999' is therefore not allowed access.

You're not on the guest list.

Fixed my problem.
Was trying to access my express api on localhost:3000 from my vue app on localhost:8080, but was getting an error back.
Turns out you need to add http:// to make it work.
So use http://localhost:3000 instead of localhost:3000 when doing dev testing.

I had the same problem with wikmedia api. looking into their CORS page (https://www.mediawiki.org/wiki/Manual:$wgCrossSiteAJAXdomains) I added origin=* to the request and it fixed the issue.

axios.get('https://en.wikipedia.org/w/api.php?action=opensearch&format=json&origin=*&search=Albert') .then(function(res) { console.log(res); }) .catch(function(err) { console.log('Error: =>' + err); })

Even though I got the scary cors error message, my request was hitting the server.

XMLHttpRequest cannot load "...url here...". No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.

Axios team, can you please fix???

@mellogarrett This is not an axios related problem. Read this: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

Important cite:

"For security reasons, browsers restrict cross-origin HTTP requests initiated from within scripts. For example, XMLHttpRequest and Fetch follow the same-origin policy. So, a web application using XMLHttpRequest or Fetch could only make HTTP requests to its own domain. To improve web applications, developers asked browser vendors to allow cross-domain requests."

Many of those having this issue probably don't have the server responding to the OPTIONS request. Make sure you have handlers (with CORS headers) for both OPTIONS and POST requests. The client (axios) will first ping OPTIONS and then do the POST.

I've got the same error on Firefox, but not on Chromium. Then I remembered NoScript was there (in Firefox) preventing the request to the remote server. In case you have NoScript (or a similar plugin) installed, check that first.
In my case the issue was not related to Axios. Thanks for the great work.

For anyone else googling a fix to this issue, I had all the same symptoms but traced the problem to a php.ini setting on the server.

My preflight OPTIONS request was successful and followed by a proper POST request but I was still getting No 'Access-Control-Allow-Origin' header is present on the requested resource... similar to @mellogarrett . This seemed totally weird so I used a Chrome plugin to temporarily disable CORS protection. After that, I could see the problem was actually a PHP error:

Deprecated: Automatically populating $HTTP_RAW_POST_DATA is deprecated and will be removed in a future version. To avoid this warning set 'always_populate_raw_post_data' to '-1' in php.ini and use the php://input stream instead. in Unknown on line 0

This post has more info on the problem, but in short, if you're using PHP 5.6 you should uncomment always_populate_raw_post_data in your php.ini and set to -1. Hope this saves somebody else a few hours of troubleshooting 🤓

Hey @daltonamitchell It seems like I am having the same issue (conditions suggest that it is the same problem). But I am wondering: How did you figure out the raw post data-error was the problem? When using the chrome plugin you mentioned the CORS request goes through and everything works fine. But even though headers are set correctly I can not get it to work without the plugin. So maybe the deprecation message is just not displayed but the issue might still be there...? Can you give some advice how to check for that?

@RT-TL the plugin is only used to see the response content without CORS blocking it. In my case, for test purposes I was just returning a string like Hello World so once I disabled CORS I saw something like

Deprecated: Automatically populating $HTTP_RAW_POST_DATA is deprecated and will be removed in a future version. To avoid this warning set 'always_populate_raw_post_data' to '-1' in php.ini and use the php://input stream instead. in Unknown on line 0
Hello World

Make sure you have PHP warnings enabled by adding error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE) or error_reporting(E_ALL) to the top of your controller method. If you still don't see anything I'd just try returning some simple JSON response to check that they look as expected.

Is anyone still experiencing this issue? I'm running into the same:

const instance = axios.create({
    baseURL: 'http://localhost/',
    responseType: 'json',
    headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
        'Authorization': 'test',
        'X-Test': 'testing'
    }
})
axios.get('v2/portal/bar/foo?')

Response headers

HTTP/1.1 401 Unauthorized
Server: nginx/1.11.10
Date: Fri, 24 Mar 2017 07:12:13 GMT
Content-Type: application/json; charset=UTF-8
Content-Length: 0
Connection: keep-alive
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, PUT, DELETE, GET, OPTIONS
Access-Control-Allow-Headers: *

Request headers

OPTIONS /v2/portal/bar/foo? HTTP/1.1
Host: localhost
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: http://localhost:3000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36
Access-Control-Request-Headers: authorization,content-type,x-test
Accept: */*
Referer: http://localhost:3000/dashboard/report
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: en-US,en;q=0.8,fr;q=0.6,nl;q=0.4,zh-TW;q=0.2,zh;q=0.2,zh-CN;q=0.2

I can't figure out why none of my headers are being send correctly.

Same issue here, OPTIONS request is made, but POST request is not.

TLDR: fetch works, axios doesn't unless I use JSON.stingify

So I have also seen the variant of this error where OPTIONS returns 200 with the headers set for cross origin requests, but no POST is made. I use this extension and it starts working as expected. But I am pretty sure there is some sort of issue here. Take a look at my request:

My server is replying with Access-Control-Allow-Origin: *
Here's all the examples with code and screenshots:

Axios:

axios.post('http://localhost:3001/card', { test: 'test' })

axios_cors


fetch:

    return fetch('http://localhost:3001/card', {
      method: 'POST',
      body: { test: 'test' },
    })

fetch_no_stringify

with JSON.stringify

    return fetch('http://localhost:3001/card', {
      method: 'POST',
      body: JSON.stringify({ test: 'test' }),
    })

fetch_cors

I was able to make axios work by JSON.stringify-ing my data like so:

    return axios.post('http://localhost:3001/card', JSON.stringify({ test: 'test' }));

axios_json_stringify

I was facing the same problem as @kwhitaker explained, axios was not sending my cookie properly resulting in responses with less information (I suppose due to the security concerns). In the other hand regular XHR request worked fine. Then as @zlyi suggested I just added the line axios.defaults.withCredentials = true; and everything started worked as expected.

Tried everything and still having the issue. :(

Tried everything and still having the issue. :(

have managed the issue by adding the following to .htaccsess :

<IfModule mod_headers.c> 
Header add Access-Control-Allow-Headers "origin, x-requested-with, content-type" 
Header add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS" 
</IfModule>

I was able to address this by using a proxy. Add the proxy to the package.json

{
    "proxy": "http://some-url/some-endpoint"
}

Then request:

axios.get('/user?ID=12345')
  .then(function (response) {
    console.log(response)
  })
  .catch(function (error) {
    console.log(error)
  })

This is a server-side issue, need to have 'Acces-Control-Allow-Origin': '*' in your response header. If you are using Express, can use npm-cors for a more robust/elegant implementation.

+1 @ProfNandaa
i've created an export in my local server

# cors.js file
module.exports = (req, res, next) => {
  res.setHeader("Access-Control-Allow-Origin", "*");
  res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
}

so then i assign:
```
const cors = require('cors');
router.use(cors);
````
now move on... thanks

The error will happen when the server does not accept OPTION request.

For those commenting saying "Add OPTION request handling to your server", that does not work. I'm running a local environment that has OPTION request handling enabled.

I experienced this issue identically as a user above, where Axios.post(url, obj) returned the CORS 403 forbidden error, but updating that to Axios.post(url, JSON.stringify(obj)) worked correctly.

I'm working on just a simple tutorial project and have had trouble accessing various apis. The only solution I've found to work is the one mentioned by thiagodebastos above.

I simply substituted jsonp for get and I was able to access the data.

I had this problem and koa-cors was a simple solution! (npm-cors for Express users according to ProfNandaa)

For those still having problems with this: Axios will work fine with CORs, with OPTIONS requests, with JSON sent as the body of the request without being JSON.encoded, and with cookies sent and persisted properly, so long as Axios and the server responding to the requests are configured properly.

It took some frustrating trial and error but we have cross domain requests working fine with Axios.

Some points:

For the request to work, ensure

  • The server responds to OPTIONS requests, as if the response is anything other than 200 with all the correct headers set, "preflighted" requests will fail.

  • The request is made with the correct headers, and the server responds with all headers necessary.

  • If cookies/authorisation headers or TLS client certificates are required, send allowCredentials to true for the Axios request. This can be done as a default (axios.defaults.withCredentials = true) or per request.

Example successful request headers

Access-Control-Request-Headers: Content-Type
Access-Control-Request-Method: GET

Example successful response headers

Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS
Access-Control-Allow-Origin: http://your-origin-url.com

We gradually added response headers and found that we had various, difficult to diagnose errors and unexpected behaviour with different combinations

Without Access-Control-Allow-Credentials: true cookies weren't being sent or persisted, which makes sense after reading the MDN page for that header

Reading through this documentation helps.

Anyone having the issue, ...Allow-Headers: Content-Type is important.

Access-Control-Allow-Origin: '*'
Access-Control-Allow-Methods: ...
Access-Control-Allow-Headers: Content-Type, Accept

Im using this chrome extension named 'Allow-Control-Allow-Origin: *'
hope it could help ur problem.
2017-07-19 14 06 37

For anyone who does not understand why Axios CANNOT fix this error:

This is not an Axios problem. It is an issue with the browser. JS in the browser will reject requests to servers that do not have the proper headers set. If you're using this with something like React on the client then do not be confused, this is not a React or Axios problem, it is simply the browser respecting CORS standard.

JakeElder gives a good description of what you need to do on the server-side of your API here: https://github.com/mzabriskie/axios/issues/191#issuecomment-311069164

If you have no control over the server you're trying to access then you should create a proxy server to fetch the content for you and return it with the correct headers.

Not sure why this was implemented. It sure is annoying when you just want to make a request to a server to get some info but can't because the server doesn't have a specific header set. Seems extremely restrictive. Oh well ...

@robins-eldo Again, I do not believe you are correct.

My original comment:

For those commenting saying "Add OPTION request handling to your server", that does not work. I'm running a local environment that has OPTION request handling enabled.

I experienced this issue identically as a user above, where Axios.post(url, obj) returned the CORS 403 forbidden error, but updating that to Axios.post(url, JSON.stringify(obj)) worked correctly.

If it was in fact a server problem, and not an Axios problem, stringifying an object would've had no affect, as the OPTIONS request would've failed either way.

@alexanderbanks

Not sure about the OPTION HTTP method but my specific problem was that I have a React client trying to POST to an internal API I wrote (the internal API being the server here). I kept getting this error: Failed to load resource: Origin http://localhost:7149 is not allowed by Access-Control-Allow-Origin. XMLHttpRequest cannot load http://localhost:8902/user-login due to access control checks.

I thought it may be an Axios problem so I tried Unirest instead and kept getting the same error. So I figured it must be something else. Not sure if this is a browser problem or React, but as soon as I added the following to my API server (which is a Nodejs + Express API), everything started working with both Axios and Unirest on the client side:

app.use(function(req, res, next) { res.header("Access-Control-Allow-Origin", "*"); next(); });

Perhaps my understanding of what is actually happening behind the scenes here is somewhat limited, however, this bit of code on the server solved the problem for me.

Make sure your server is not restricting origin access too much and if you feel like getting around no-cors then try this:

    return axios(url, {
      method: 'POST',
      mode: 'no-cors',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
      withCredentials: true,
      credentials: 'same-origin',
    }).then(response => {
    })

I think there is some people here confused about how CORS work. However, the original problem was not about CORS,or at least that should be the important problem. I mean, when you have CORS properly configured but even though the Post does not work, then that is a problem to report, not how to configure a server properly

API acting weird. All cors GET request was working with "credentials : true".
For POST requests, same origin request is working without stringify data object while for CORS POST request also start working when i stringify data object.

Didn't get exactly the reason but problem solved for me.

I'm sorry but I'm locking this thread as it seems we're doing circles around the same topic. If you have a specific issue that hasn't been covered in another issue (general CORS issues due to misconfiguration, POST requests being sent as JSON instead of form-urlencoded, etc.) please open a new one with specific details.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

achingbrain picture achingbrain  ·  3Comments

altruisticsoftware picture altruisticsoftware  ·  3Comments

c0debreaker picture c0debreaker  ·  3Comments

reggi picture reggi  ·  3Comments

9tor picture 9tor  ·  3Comments