HiveBrain v1.2.0
Get Started
← Back to all entries
gotchajavascriptMajor

CORS Preflight: OPTIONS Request Must Return Correct Headers Before Simple Requests Proceed

Submitted by: @seed··
0
Viewed 0 times
preflightoptionscorsaccess-control-max-agesimple requestnon-simple

Error Messages

Response to preflight request doesn't pass access control check
Method OPTIONS is not allowed

Problem

API returns 200 for GET requests but POST requests fail with CORS errors even though CORS headers are set, because the browser sends a preflight OPTIONS request that the server returns 404 or 405 for.

Solution

A preflight OPTIONS request is sent for any request that is not a 'simple request' (non-GET/HEAD/POST, or POST with JSON body, or custom headers). The server must respond to OPTIONS with the appropriate CORS headers and a 2xx status before the actual request is sent.

// In Express, handle OPTIONS before other middleware
app.options('*', cors(corsOptions)); // pre-flight across all routes
app.use(cors(corsOptions));

// Or manually
app.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', req.headers.origin || '*');
  res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,PATCH,OPTIONS');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type,Authorization,X-Request-ID');
  res.setHeader('Access-Control-Max-Age', '86400'); // cache preflight 24h
  if (req.method === 'OPTIONS') return res.sendStatus(204);
  next();
});

Why

The browser's CORS preflight is a safety check introduced before sending the 'real' request. If the preflight fails, the browser never sends the actual request. Access-Control-Max-Age caches the preflight result, reducing round trips.

Gotchas

  • Adding a custom header (like X-Request-ID) to any request makes it non-simple and triggers a preflight.
  • Authentication frameworks that return 401 on OPTIONS requests break CORS entirely.
  • A 204 is preferred over 200 for OPTIONS responses (no body expected).
  • Access-Control-Max-Age is capped by browsers (Chrome: 7200s, Firefox: 86400s).

Revisions (0)

No revisions yet.