Needed control over CORS `Access-Control-Allow-Headers` and `Access-Control-Expose-Headers`
Environment
- PostgreSQL version: 16.3
- PostgREST version: 12.0.2
- Operating system: Ubuntu 22.04 LTS
Description of issue
I am trying to add a custom header (x-app-id) to postgrest requests. My intention is to use the value of this header in RLS policies. I noticed PostGREST has no way to add this header to the list of allowed headers: Access-Control-Allow-Headers
Would you consider supporting controlling the allowed headers via a configuration parameter similar to server-cors-allowed-origins ?
It would be something like:
server-cors-allowed-headers="Authorization, Content-Type, Accept, Accept-Language, Content-Language, X-App"
or to just configure the extra headers:
server-cors-allowed-headers="X-App"
Thank you, Ra
For PostgREST to return Access-Control-Allow-Headers you'll need to add the header Access-Control-Request-Headers in the CORS pre-flight request. It will include the header that you specify there in the list of allowed headers by default. For example:
curl -X OPTIONS "http://localhost:3000/todos" \
-H "Access-Control-Request-Method: GET" \
-H "Access-Control-Request-Headers: X-App-Id" \
-H "Origin: http://www.example.com" -i
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Date: Wed, 22 May 2024 18:12:48 GMT
Server: postgrest/12.1 (b6c6f2b)
X-Request:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS, HEAD
Access-Control-Allow-Headers: Authorization, X-App-Id, Accept, Accept-Language, Content-Language
Access-Control-Max-Age: 86400
AFAIK the browser adds Access-Control-Request-Headers to the pre-flight, when specifying headers in a fetch(), for instance.
As mentioned, Access-Control-Allow-Headers mirrors what was sent in via Access-Control-Request-Headers. Simply mentioning the header in fetch request did it.
@laurenceisla Is there a way to control Access-Control-Expose-Headers?
@laurenceisla Is there a way to control
Access-Control-Expose-Headers?
Not for now. The expose-headers are hard-coded here:
https://github.com/PostgREST/postgrest/blob/b261abd5f543c1bdda4bc422ec1f13d542809cd3/src/PostgREST/Cors.hs#L36-L38
I'll update the title of this issue to include this header.
@laurenceisla Looks like setting response.headers merges with existing values. 🎉
It was introduced in this MR: https://github.com/PostgREST/postgrest/pull/986
response_headers := jsonb_build_array(
jsonb_build_object(
'X-Meta-Info',
meta_info::TEXT
),
jsonb_build_object(
'Access-Control-Expose-Headers',
'X-Meta-Info'
)
);
EXECUTE 'SET LOCAL "response.headers" = ' || quote_literal(response_headers);
Browser receives this as:
Access-Control-Allow-Origin: https://example.com
Access-Control-Expose-Headers: X-Meta-Info,Content-Encoding, Content-Location, Content-Range, Content-Type, Date, Location, Server, Transfer-Encoding, Range-Unit
Environment
- Supabase
- PostgreSQL version: 15.1.1.78
- PostgREST version: 12.2.2
@laurenceisla Looks like setting
response.headersmerges with existing values. 🎉
Cool, that's a nice workaround! Info on setting/reading headers can be found in the Transaction settings section in the docs.