使用 create-react-app 和 webpack 发出 CORS API 请求 - 不明确
Posted
技术标签:
【中文标题】使用 create-react-app 和 webpack 发出 CORS API 请求 - 不明确【英文标题】:Making CORS API requests with create-react-app and webpack - no express 【发布时间】:2018-10-05 03:03:30 【问题描述】:我正在尝试在不禁用浏览器中的 CORS 的情况下进行 API 调用。该应用程序是使用 react-create-app 创建的。它使用 webpack 和 webpackDevServer 进行开发。我在这里找到的所有答案都说将以下代码放入我的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"
但是,我已经在许多不同的地方尝试过,但它不起作用。
我继续收到错误:
加载资源失败:服务器响应状态为500()
和
加载失败...对预检请求的响应未通过访问 控制检查:不存在“Access-Control-Allow-Origin”标头 请求的资源。因此,原点 'http://localhost:3000' 是 不允许访问。响应的 HTTP 状态代码为 500。
我还尝试将我的调用从 axios 调用更改为 fetch 调用
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
【问题讨论】:
好吧,CORS 是一种安全功能,理想情况下,不应避免使用它。您有权访问 API 源代码吗?如果是,您需要允许您正在开发的 URL。Origin 'http://localhost:3000' is therefore not allowed access.
这些,所以添加localhost
和localhost:3000
。如果您没有访问权限,则需要代理请求。
【参考方案1】:
还不能添加评论,所以我会把它作为答案。
如果您尝试访问由其他节点应用程序或其他主机提供的 API。您可以配置 webpack-dev-server 将该请求代理到真实服务器。
查看Create React App Doc: Proxying API Requests in Development了解更多详情。
【讨论】:
链接已更改。新的是:facebook.github.io/create-react-app/docs/… 我遇到了同样的问题,这个代理路由是迄今为止最简单的。在您的 package.json 中只需一行(例如“proxy”:“localhost:8090")即可在 DEV 模式下(npm start)路由到另一台主机以进行 API 调用。【参考方案2】:您看到对预检 OPTIONS 请求的 500 响应这一事实让我认为 Web 服务器可能根本不允许使用 OPTIONS 请求方法。
许多网络服务器默认只允许 HEAD、GET 和 POST,所以这是我要检查的第一件事。
如果这没有帮助,请确保上面的 webpack.config
代码对所有请求(即 OPTIONS 和 GET/POST)运行。
如果这没有帮助,请将一整套请求和响应标头发布到 OPTIONS 和 GET 请求,然后让我们看看从那里开始。
【讨论】:
这很有帮助,谢谢。我正在调用的 API 实际上允许 *,并且我错误地调用了 POST 和 GET。最后,我必须将 POST 的内容类型指定为“application/x-www-form-urlencoded”,并将数据字符串化以发布到 API。所以现在我可以 GET 和 POST,但我的 PUT 请求被 CORS 捕获,因为它作为 OPTIONS 发送 - 返回 200 - 但未通过预检访问控制检查。我应该能够发出 PUT 请求,但我不确定它为什么不起作用。也许这与我使用 axios 提出请求的方式有关? 更正。 PUT 总是会让浏览器抛出一个预检 OPTIONS 请求。现在的问题是,为什么当 API 允许 CORS 时浏览器会阻止 PUT 请求。PUT
请求将导致浏览器首先发送预检 OPTIONS 请求。如果您没有发送有效的 CORS 标头来响应该 OPTIONS 请求,那么浏览器甚至不会自己发出后续的 PUT 请求。您可以发布 OPTIONS 请求的请求/响应标头吗?
嘿,Rory,谢谢 - 我在原始帖子中添加了指向图片的链接。
好的,因此您需要在 OPTIONS 请求以及 PUT 请求中包含 CORS 响应标头。目前还没有发生这种情况。我怀疑您的 webpack.config 定义没有用于 OPTIONS 请求,但我不知道您的代码到底是什么。但我确实看到,现在您收到了 200 条 OPTIONS 请求的响应,所以自从您第一次发布问题以来,情况发生了变化。【参考方案3】:
最好的选择是使用代理,尤其是当您使用外部 API 或多个 API 时。
只需安装proxy-middleware
并创建文件src/setupProxy.js
并在文件中添加类似的代码:
const proxy = require('proxy-middleware');
module.exports = app =>
// setup proxies
// 1st api
app.use("/etherscan", proxy("http://api.etherscan.io/api"));
// 2nd api
app.use("/cryptocompare", proxy("https://min-api.cryptocompare.com/data"));
// Note: setupProxy is an express server so you can also override anything in the req or res before proxy them for example
app.use("/cryptocompare", (req,res,next) =>
req.headers =
...req.headers,
"my-header":"my header value"
return proxy("https://min-api.cryptocompare.com/data")(req,res,next);
);
app.use("/cryptocompare", proxy("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 调用传递 process.env.REACT_APP_API_URL 和标头,您可以在其中创建具有默认属性的 API 实例,例如:
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")
【讨论】:
如何在 setupProxy 中发送标头?以上是关于使用 create-react-app 和 webpack 发出 CORS API 请求 - 不明确的主要内容,如果未能解决你的问题,请参考以下文章
如何调试从 create-react-app 创建的应用程序使用的本地打字稿模块
如何让 create-react-app 使用 IP 连接到我的 api 服务器?
sh 用于将工作证书链接到create-react-app的脚本。允许您使用create-react-app和有效的SSL证书。