PostgREST / postgrest

REST API for any Postgres database
https://postgrest.org
MIT License
23.48k stars 1.03k forks source link

Needed control over CORS `Access-Control-Allow-Headers` and `Access-Control-Expose-Headers` #3551

Open fusionbeam opened 6 months ago

fusionbeam commented 6 months ago

Environment

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

laurenceisla commented 6 months ago

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.

fahimalizain commented 4 months ago

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 commented 4 months ago

@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.

fahimalizain commented 4 months ago

@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

laurenceisla commented 4 months ago

@laurenceisla Looks like setting response.headers merges 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.