使用create-react-app和webpack发出CORS API请求 - 没有明确表示

时间:2018-04-24 18:35:29

标签: reactjs webpack cors fetch axios

我试图在我的浏览器中禁用CORS的情况下进行API调用。该应用程序是使用react-create-app创建的。它使用webpack和webpackDevServer for dev。我在这里找到的所有答案都说将以下代码放入我的webpack.config文件

devServer: {
      headers: {
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
        "Access-Control-Allow-Headers": "X-Requested-With, content-type, Authorization"
      }
  }

但是,我已经在很多不同的地方尝试过它并且它不起作用。

我继续得到错误 Failed to load resource: the server responded with a status of 500 ()Failed to load ... Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 500.

我还尝试将我的呼叫从axios呼叫更改为提取呼叫

return fetch(process.env.REACT_APP_API_URL + "/prod/user", {
    mode: 'no-cors',
    credentials: 'include',
    method: "GET",
    headers: {
        "x-api-key": process.env.REACT_APP_API_KEY
    }
})
.then(response => {
   return response.json()
})
.then(resp => dispatch(receiveUsers(resp.data)))
.catch(error => {console.log(error)})

这让我更接近但控制台现在正在返回

Response {type: "opaque", url: "", redirected: false, status: 0, ok: false, …}

如何解决此CORS问题?在此先感谢您的帮助!

Response/Request Headers

3 个答案:

答案 0 :(得分:2)

无法添加评论,所以我会把它作为答案。

如果您尝试访问由其他节点应用或其他主机提供的API。您可以配置webpack-dev-server以将该请求代理到真实服务器。

查看Create React App Doc: Proxying API Requests in Development了解详情。

答案 1 :(得分:0)

您看到对预检OPTIONS请求的500响应这一事实让我觉得,Web服务器根本不允许OPTIONS请求方法。

许多网络服务器默认只允许使用HEAD,GET和POST,因此这是我要检查的第一件事。

如果这没有帮助,请确保上述webpack.config代码针对所有请求(即OPTIONS和GET / POST)运行。

如果这没有帮助,请向OPTIONS和GET请求发布一整套请求和响应标头,让我们看看我们从哪里开始。

答案 2 :(得分:0)

最好的选择是使用代理,尤其是在使用外部API或多个API的情况下。 只需安装proxy-middleware并创建文件src/setupProxy.js,然后在文件内部,可以向其中添加类似的代码:

const proxy = require('proxy-middleware');

module.exports = app => {
  // setup proxies
  // 1st api
  app.use("/etherscan", "http://api.etherscan.io/api");
  // 2nd api
  app.use("/cryptocompare", "https://min-api.cryptocompare.com/data");

  // also it's better to use .env variables
  const {REACT_APP_API_ETHERSCAN_PROXY, REACT_APP_API_ETHERSCAN_BASE_URL} = process.env;
  app.use(REACT_APP_API_ETHERSCAN_PROXY, REACT_APP_API_ETHERSCAN_BASE_URL);      
};

对于您的API,如果可以从.env变量中获取基本URL,则也更好,例如:

const {REACT_APP_API_ETHERSCAN_PROXY, REACT_APP_API_ETHERSCAN_BASE_URL} = process.env;
const baseURL = REACT_APP_API_ETHERSCAN_PROXY || REACT_APP_API_ETHERSCAN_BASE_URL;

其他建议:您可以看看axios来创建具有默认属性的API实例,例如:

,而不是为每个API调用保持传递process.env.REACT_APP_API_URL和标头的方式
const {
  REACT_APP_API_ETHERSCAN_PROXY, 
  REACT_APP_API_ETHERSCAN_BASE_URL,
  REACT_APP_API_TIMEOUT,
  REACT_APP_API_ETHERSCAN_KEY
} = process.env;

export const etherscanAPI = axios.create({
  "baseURL": REACT_APP_API_ETHERSCAN_PROXY || REACT_APP_API_ETHERSCAN_BASE_URL,
  "timeout": parseInt(REACT_APP_API_TIMEOUT),
  "headers": {
    "X-Requested-With": "XMLHttpRequest"
  },
  "params": {
    "apiKey": REACT_APP_API_ETHERSCAN_KEY
  }
});

然后etherscanAPI.get("/whatever")