http-server --cors: serve local files with Access-Control-Allow-Origin
- tool
- CORS
- command
- http-server
- flag
- --cors[=HEADERS]
- default
- off (no CORS headers; cross-origin fetch() from a page on another port or host is blocked)
npx http-server ./dist --cors makes the Node.js static file server add Access-Control-Allow-Origin: * and a fixed Access-Control-Allow-Headers list to every response, so a web app on another origin (for example a dev server on localhost:3000) can fetch() the files. --cors=Authorization,X-Api-Version appends extra request headers to that list. Without the option http-server sends no CORS headers and the browser blocks cross-origin reads with No 'Access-Control-Allow-Origin' header.
Headers with and without --cors
Three local servers on the same folder: no option, --cors, and --cors with extra headers. A cross-origin GET and a preflight are sent to each:
npm init -y >/dev/null && npm install --silent --no-audit --no-fund http-server@14.1.1 >/dev/null 2>&1
mkdir site && echo '{"ok":true}' > site/data.json
timeout 15 node node_modules/http-server/bin/http-server site -p 5416 -a 127.0.0.1 -s &
timeout 15 node node_modules/http-server/bin/http-server site -p 5417 -a 127.0.0.1 -s --cors &
timeout 15 node node_modules/http-server/bin/http-server site -p 5419 -a 127.0.0.1 -s --cors=Authorization,X-Api-Version &
sleep 4
for port in 5416 5417 5419; do
echo "--- port $port, GET:"
curl -s -D - -o /dev/null -H "Origin: http://localhost:3000" http://127.0.0.1:$port/data.json | tr -d '\r' | grep -iE "^HTTP|^access-control"
done
echo "--- port 5419, preflight for PUT with Authorization:"
curl -s -D - -o /dev/null -X OPTIONS -H "Origin: http://localhost:3000" -H "Access-Control-Request-Method: PUT" \
-H "Access-Control-Request-Headers: Authorization" http://127.0.0.1:5419/data.json | tr -d '\r' | grep -iE "^HTTP|^access-control"
waitOutput
--- port 5416, GET: HTTP/1.1 200 OK --- port 5417, GET: HTTP/1.1 200 OK Access-Control-Allow-Origin: * Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Range --- port 5419, GET: HTTP/1.1 200 OK Access-Control-Allow-Origin: * Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Range, Authorization, X-Api-Version --- port 5419, preflight for PUT with Authorization: HTTP/1.1 204 No Content Access-Control-Allow-Origin: * Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Range, Authorization, X-Api-Version
Without the option there are no Access-Control-* headers at all. With it the origin is always *, whatever the request's Origin was, and preflight requests get 204 No Content.
What --cors sends and what it does not
| Header | Value with --cors | Consequence in the browser |
|---|---|---|
| Access-Control-Allow-Origin | * | Any origin may read responses that are fetched without credentials |
| Access-Control-Allow-Headers | Origin, X-Requested-With, Content-Type, Accept, Range (+ the list after =) | Requests with other headers, such as Authorization, fail the preflight |
| Access-Control-Allow-Methods | not sent | Only CORS-safelisted methods (GET, HEAD, POST) pass a preflight |
| Access-Control-Allow-Credentials | not sent | fetch with credentials: 'include' is blocked |
| Access-Control-Max-Age | not sent | Browsers cache the preflight only briefly |
The missing Allow-Methods rarely matters for a static server, which answers only GET and HEAD anyway (PUT gets 405). The header list matters more: a request that sends Authorization is rejected with Request header field is not allowed by Access-Control-Allow-Headers unless the header is added with --cors=Authorization.
Pitfalls
- Wildcard and credentials. Because the origin is
*, cookies and HTTP authentication cannot be used cross-origin; see wildcard origin with credentials. Use a server that reflects the origin, such aslive-server --cors, when you need them. - Caching. http-server sends
cache-control: max-age=3600by default. When you toggle--corsand reload, the browser may reuse a cached response without the headers; add-c-1to disable caching while testing. - Production.
--corsis meant for local development and test fixtures. Public APIs should list allowed origins explicitly instead of*when responses are not meant for everyone.
To check headers the way a browser does, use test CORS with curl or the explanation of the preflight request.
FAQ
Why do I still get a CORS error with http-server --cors?
Check which request fails. --cors allows any origin but only a fixed list of request headers and sends no Access-Control-Allow-Methods. A request with Authorization or a custom header needs --cors=Authorization, and PUT or DELETE are not allowed at all.
Does http-server --cors allow cookies?
No. It sends Access-Control-Allow-Origin: * and no Access-Control-Allow-Credentials, so fetch with credentials: 'include' is blocked. Wildcard origins and credentials cannot be combined anyway.
Do I need --cors when the page and the files come from the same http-server?
No. CORS only applies to cross-origin requests. A page on http://127.0.0.1:8080 that fetches /data.json from the same host and port needs no CORS headers.