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