从 React 在 Express.js 服务器上运行 fetch() 时出现 Cors 错误
我有一个 Node.js Express.js REST API 服务器,使用在 localhost:4000
上运行的 cors
中间件。在 localhost:3000 上运行的 React 应用程序使用 fetch 向 Express 服务器发送 GET 请求并期望 JSON 响应。
但是,由于 CORS 错误,React 无法执行fetch
。
从源“http://localhost:3000”获取“http://localhost:4000/metrics”的访问已被 CORS 策略阻止:不存在“Access-Control-Allow-Origin”标头所请求的资源。如果不透明响应满足您的需求,请将请求模式设置为“no-cors”以在禁用 CORS 的情况下获取资源。
尽管在 API 服务器上使用了 cors
中间件,为什么仍然出现 CORS 错误?
api_server.js:
import { selectMetrics } from './db'
import express from 'express'
import cors from 'cors'
const PORT = 4000
const app = express()
const corsOptions = {
origin: '*',
credentials: true, //access-control-allow-credentials:true
optionSuccessStatus: 200,
}
app.use(cors(corsOptions))
app.set('json spaces', 2)
app.get('/metrics', async (req, res) => {
const metrics = await selectMetrics()
return res.json(metrics)
})
app.listen(PORT, () => console.log(`API server listening on port ${PORT}`))
从 React 应用程序内部获取:
async () => {
const apiUrl = "http://localhost:4000/metrics";
const response = await fetch(apiUrl);
if (!response.ok) {
throw new Error("Error fetching from /metrics");
}
console.log("/metrics response:", response);
}
常规:
Request URL: http://localhost:4000/metrics
Request Method: GET
Status Code: 200
Referrer Policy: strict-origin-when-cross-origin
响应标头:
Content-Length: 30008
Content-Type: application/json; charset=utf-8
Date: Thu, 24 Feb 2022 05:12:01 GMT
ETag: W/"7538-9fQpPD2E0HULEM9eRjgd2o2OHGo"
X-Powered-By: Express
请求标头:
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Host: localhost:4000
If-None-Match: W/"7538-9fQpPD2E0HULEM9eRjgd2o2OHGo"
Origin: http://localhost:3000
Referer: http://localhost:3000/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Sec-GPC: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
还尝试了以下操作,但仍然收到 CORS 错误:
每次尝试后 Express 服务器都会重新启动
const app = express()
app.use(cors())
const app = express()
const corsOptions = {
origin: '*',
optionSuccessStatus: 200,
}
app.use(cors(corsOptions))
const app = express()
app.use(cors())
app.options('*', cors())
const app = express()
app.use(function (req, res, next) {
res.header('Access-Control-Allow-Origin', 'http://localhost:4000')
res.header('Access-Control-Allow-Credentials', true)
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS')
res.header(
'Access-Control-Allow-Headers',
'Origin,X-Requested-With,Content-Type,Accept,content-type,application/json',
)
next()
})
运行 curl -v -H "Origin: http://localhost:3000" 的结果“http://localhost:4000/metrics”
:
标头:
* Trying 127.0.0.1:4000...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 4000 (#0)
> GET /metrics HTTP/1.1
> Host: localhost:4000
> User-Agent: curl/7.68.0
> Accept: */*
> Origin: http://localhost:3000
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Content-Type: application/json; charset=utf-8
< Content-Length: 30008
< ETag: W/"7538-9fQpPD2E0HULEM9eRjgd2o2OHGo"
< Date: Thu, 24 Feb 2022 05:44:21 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
<
收到预期的 JSON 响应
I have a Node.js Express.js REST API server using the cors
middleware running on localhost:4000
. A React app running on localhost:3000
uses fetch
to send a GET request to the Express server and expects a JSON response.
However, React is unable to perform the fetch
due to a CORS error.
Access to fetch at 'http://localhost:4000/metrics' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Why is it still getting a CORS error despite using the cors
middleware on the API server?
api_server.js:
import { selectMetrics } from './db'
import express from 'express'
import cors from 'cors'
const PORT = 4000
const app = express()
const corsOptions = {
origin: '*',
credentials: true, //access-control-allow-credentials:true
optionSuccessStatus: 200,
}
app.use(cors(corsOptions))
app.set('json spaces', 2)
app.get('/metrics', async (req, res) => {
const metrics = await selectMetrics()
return res.json(metrics)
})
app.listen(PORT, () => console.log(`API server listening on port ${PORT}`))
Fetch from inside the React app:
async () => {
const apiUrl = "http://localhost:4000/metrics";
const response = await fetch(apiUrl);
if (!response.ok) {
throw new Error("Error fetching from /metrics");
}
console.log("/metrics response:", response);
}
General:
Request URL: http://localhost:4000/metrics
Request Method: GET
Status Code: 200
Referrer Policy: strict-origin-when-cross-origin
Response Headers:
Content-Length: 30008
Content-Type: application/json; charset=utf-8
Date: Thu, 24 Feb 2022 05:12:01 GMT
ETag: W/"7538-9fQpPD2E0HULEM9eRjgd2o2OHGo"
X-Powered-By: Express
Request Headers:
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Host: localhost:4000
If-None-Match: W/"7538-9fQpPD2E0HULEM9eRjgd2o2OHGo"
Origin: http://localhost:3000
Referer: http://localhost:3000/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Sec-GPC: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
Also tried the following, but still getting CORS error:
Express server restarted after each try
const app = express()
app.use(cors())
const app = express()
const corsOptions = {
origin: '*',
optionSuccessStatus: 200,
}
app.use(cors(corsOptions))
const app = express()
app.use(cors())
app.options('*', cors())
const app = express()
app.use(function (req, res, next) {
res.header('Access-Control-Allow-Origin', 'http://localhost:4000')
res.header('Access-Control-Allow-Credentials', true)
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS')
res.header(
'Access-Control-Allow-Headers',
'Origin,X-Requested-With,Content-Type,Accept,content-type,application/json',
)
next()
})
Result of running curl -v -H "Origin: http://localhost:3000" "http://localhost:4000/metrics"
:
Headers:
* Trying 127.0.0.1:4000...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 4000 (#0)
> GET /metrics HTTP/1.1
> Host: localhost:4000
> User-Agent: curl/7.68.0
> Accept: */*
> Origin: http://localhost:3000
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Content-Type: application/json; charset=utf-8
< Content-Length: 30008
< ETag: W/"7538-9fQpPD2E0HULEM9eRjgd2o2OHGo"
< Date: Thu, 24 Feb 2022 05:44:21 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
<
Expected JSON response is received
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论