I am implementing a router to process all web requests.
OPTIONS requests come in and I am responding with:
header('Access-Control-Allow-Origin: http://localhost:4000');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');
header('Access-Control-Allow-Headers: authorization');
header('Access-Control-Allow-Credentials: true');
header('Vary: Origin');
And also I am sending all those for the GET/POST/PUT/DELETE requests.
Is sending those headers for those "real" requests unnecessary?
The Fetch standard is the (somewhat dry) source of truth for the CORS protocol; you can find answers to all your questions about CORS in there; see, in particular,
Some CORS response headers are only used in preflight responses:
Access-Control-Allow-MethodsAccess-Control-Allow-HeadersAccess-Control-Max-AgeAccess-Control-Allow-Local-Network(which is part of Local Network Access, a recent extension to the CORS protocol)Other CORS response headers are used in both the preflight response and the actual response:
Access-Control-Allow-OriginAccess-Control-Allow-CredentialsNote that, if one or both of those headers (
Access-Control-Allow-OriginandAccess-Control-Allow-Credentials) are actually needed in the preflight response, they're also needed in the actual response.Finally, one CORS response header is only used in the actual response:
Access-Control-Expose-Headers.The case of the
Varyheader is interesting. Since, in theory, responses toOPTIONSrequests are not cacheable (outside of browsers' preflight cache), theVaryheader should have no place in such responses. However, some caching intermediaries do allow their users to cache responses toOPTIONSrequests, and omitting theVaryheader from those responses may lead to Web cache poisoning.This difficulty is a good indication that you shouldn't be implementing CORS by manually setting response headers. Instead, rely on a good CORS middleware library that can abstract all this complexity for you.