Skip to content

/flags/cors/live-server-cors

live-server --cors: reflect the request Origin and allow credentials in development

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash)updated
tool
CORS
command
live-server
flag
--cors
default
off (no CORS headers; live-server only serves files and the live-reload script)

npx live-server ./public --cors turns on CORS in the live-reload development server. Unlike http-server --cors and serve -C, which send the wildcard *, live-server echoes the request's Origin into Access-Control-Allow-Origin and adds Access-Control-Allow-Credentials: true. That is the combination browsers require for requests that carry cookies, so a front end on another port can call the files with credentials: 'include'. Preflight requests get the allowed methods and the requested headers back.

Response headers with --cors

A cross-origin GET and a preflight for PUT with an Authorization header:

bash
npm init -y >/dev/null && npm install --silent --no-audit --no-fund live-server@1.2.2 >/dev/null 2>&1
mkdir site && echo '{"ok":true}' > site/data.json
timeout 12 node node_modules/live-server/live-server.js site --port=5421 --host=127.0.0.1 --no-browser --quiet --cors &
sleep 4
echo "--- GET:"
curl -s -D - -o /dev/null -H "Origin: http://localhost:3000" http://127.0.0.1:5421/data.json | tr -d '\r' | grep -iE "^HTTP|^access-control|^vary"
echo "--- preflight:"
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:5421/data.json | tr -d '\r' | grep -iE "^HTTP|^access-control"
wait

Output

--- GET:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://localhost:3000
Vary: Origin
Access-Control-Allow-Credentials: true
--- preflight:
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE
Access-Control-Allow-Headers: Authorization

The allowed origin is exactly http://localhost:3000, the value the request sent. The preflight answer is 204 No Content with a method list and the requested Authorization header mirrored in Access-Control-Allow-Headers.

Three dev servers compared

Headerlive-server --corshttp-server --corsserve -C
Access-Control-Allow-OriginThe request Origin**
Access-Control-Allow-Credentialstruenot senttrue (ignored with *)
Access-Control-Allow-Methods (preflight)GET,HEAD,PUT,PATCH,POST,DELETEnot sentnot sent
Access-Control-Allow-Headers (preflight)The requested headersFixed list*
Preflight status204204200

Use live-server when the page under development sends cookies or HTTP authentication to the files; the other two are enough for anonymous reads of JSON, images or fonts.

Pitfalls

  • Cookies still need SameSite. CORS allows the browser to read the response, but a cookie is only sent cross-site if it has SameSite=None; Secure; between localhost ports the cookie rules for same-site apply. See Set-Cookie SameSite.
  • Do not copy the pattern to production. Reflecting every origin with credentials allowed lets any site read authenticated data. Real servers should compare the origin with a list and send Vary: Origin.
  • Static files only. live-server serves files. A PUT passes the preflight, but the server does not implement it, so the real request comes back with an error status: the app sees a failed request, not a CORS error.
  • Project status. live-server 1.2.2 is the current release; for new projects, dev servers built into Vite or webpack have their own CORS settings.

FAQ

Is reflecting the Origin header safe?

For a local development server it is convenient. On a real API, echoing any Origin together with Access-Control-Allow-Credentials: true lets every website read authenticated responses, which defeats the purpose of CORS. Production servers should check the origin against an allow list.

Why does live-server answer with my exact origin instead of *?

Browsers reject Access-Control-Allow-Origin: * for requests that send cookies. Echoing the exact origin is the only way to allow credentialed requests, so live-server copies the Origin header it receives.

Does live-server --cors add Vary: Origin?

Check your version's response headers. When a server reflects the origin, Vary: Origin tells caches that the response differs per origin; without it a shared cache could serve one origin's header to another.

Sources