CORS middleware mirroring PostgREST's server-cors-allowed-origins
(PostgREST src/PostgREST/Cors.hs).
CORS headers are emitted only when the request carries an Origin header; a
request without Origin is a same-origin request and gets no CORS headers
(PostgREST's corsPolicy returns Nothing when no Origin is present).
Origin matching follows the WAI cors middleware semantics PostgREST relies
on:
- Allowlist configured (
server-cors-allowed-originsis a non-empty, comma-separated list): a request whoseOriginis in the list gets that origin echoed inAccess-Control-Allow-Origintogether withAccess-Control-Allow-Credentials: true. AnOriginnot in the list gets noAccess-Control-Allow-Originheader. - Empty/unset (
""or nil): every origin is allowed, soAccess-Control-Allow-Origin: *is returned (no credentials, per the WAI wildcard rule).
For a CORS preflight (OPTIONS carrying Access-Control-Request-Method) the
response additionally advertises the allowed methods, headers, and a 24h
max-age — the fixed set PostgREST configures, widened by the WAI middleware's
union with the CORS "simple" methods and headers.
Access-Control-Allow-Headers is emitted only when the preflight actually
carried Access-Control-Request-Headers: wai-cors' hdrRequestHeader
returns no header at all for the Nothing case (see put_allow_headers/1).
This plug sets no Vary header of its own. It would suppress the v16 default
on exactly the requests that carry an Origin — put_resp_header/3 replaces,
and Bier.Plugs.Vary's funnel skips a response that already has a Vary.
Instead the funnel reads the Access-Control-Allow-Origin this plug wrote and
appends Origin to the default when the value is an echo rather than the
wildcard, so a CORS response carries the union
Vary: Accept, Prefer, Range, Origin. That is a deliberate divergence from
PostgREST, which builds its policy with corsVaryOrigin = False (Cors.hs)
and therefore names no Vary at all on a response whose
Access-Control-Allow-Origin depends on the request — see #98 and the
README's "Deliberate divergences from PostgREST".
Summary
Functions
True when the request is a CORS preflight: an OPTIONS carrying
Access-Control-Request-Method.
Functions
@spec preflight?(Plug.Conn.t()) :: boolean()
True when the request is a CORS preflight: an OPTIONS carrying
Access-Control-Request-Method.
Public so Bier.Plugs.Vary can leave preflight responses alone without
restating the predicate — upstream answers a preflight inside the wai-cors
middleware, before the funnel that appends Vary runs at all.