pg_graphql icon indicating copy to clipboard operation
pg_graphql copied to clipboard

provide request metadata

Open chaoky opened this issue 2 years ago • 10 comments

Summary

set the "request.headers" setting to the graphql request headers

Rationale

this functionality is already offered by supabase postgrest and it's very useful for i18n

Examples

create function "public"."_body"("public"."notifications")
returns setof "public"."translations" rows 1
language sql as
$$
select * from "public"."translations"
where id = $1.body_id and
language = current_setting('request.headers', true)::json->>'accept-language'
limit 1
$$;

Alternatives

in hasura, the metadata is injected into computed fields as an argument

chaoky avatar Jul 31 '23 21:07 chaoky

This should already be the case. Are you seeing something different?

On supabase the /graphql/v1/ endpoint goes through PostgREST RPC so those headers are still available. Thats also how the role management works

olirice avatar Jul 31 '23 22:07 olirice

in a fresh supabase local instance

create table "public"."notifications" (
    "id" bigint generated by default as identity not null
);

create function "public"."_test"("public"."notifications")
returns json
language sql as
$$
select current_setting('request.headers', true)::json
$$;

with this query

{
  notificationsCollection {
    edges {
      node {
        test
      }
    }
  }
}

besides Authorization, all of the other headers seem static

{
  "x-forwarded-port": "8000",
  "x-real-ip": "172.21.0.11",
  "host": "supabase_rest_dashboard:3000",
  "x-forwarded-host": "supabase_kong_dashboard",
  "content-type": "application/json",
  "accept": "*/*",
  "sec-fetch-mode": "cors",
  "apikey": "...",
  "accept-language": "*",
  "x-forwarded-prefix": "/graphql/v1",
  "x-forwarded-proto": "http",
  "x-forwarded-path": "/graphql/v1",
  "user-agent": "undici",
  "authorization": "Bearer ...",
  "content-length": "150",
  "accept-encoding": "gzip, deflate",
  "x-forwarded-for": "172.21.0.11",
  "connection": "keep-alive",
  "content-profile": "graphql_public"
}

chaoky avatar Aug 01 '23 00:08 chaoky

Reproduced by adding a customer header "Fooooo" via GraphiQL and returning the response

Screenshot 2023-08-01 at 6 09 23 AM

@steve-chavez is there a way to forward custom headers so they're visible in he db or are they stripped for security?

olirice avatar Aug 01 '23 11:08 olirice

Hm, no header is stripped. All headers (including custom) are passed.

Can you guys try with a plain curl call? Not sure how that UI works for sending headers.

steve-chavez avatar Aug 01 '23 20:08 steve-chavez

I tried with curl with the same result. If PostgREST is not stripping custom headers then it could be some other proxy or gateway along the route.

imor avatar Aug 02 '23 07:08 imor

@imor Hm, how about trying with a header like Prefer: return=representation? This is one that PostgREST needs and should pass unmodified by any proxy.

Also can you share the curl snippet?

steve-chavez avatar Aug 02 '23 17:08 steve-chavez

besides Authorization, all of the other headers seem static "accept-language": "*",

Also, I do see the accept-language in the request.headers output ^.

steve-chavez avatar Aug 02 '23 17:08 steve-chavez

I sent the request using GraphiQL and then from the browser dev tools copied it as a curl command using the "Copy as cURL" context menu option. Here's the command line (edited to omit jwt):

curl "https://api.supabase.io/platform/projects/wcteuwpjlocwxcjvgtkp/api/graphql" -H "authority: api.supabase.io" -H "accept: application/json, multipart/mixed" -H "accept-language: en-US,en;q=0.8" -H "authorization: Bearer <omitted>" -H "content-type: application/json" -H "origin: https://supabase.com" -H "prefer: return=representation" -H "referer: https://supabase.com/" -H "sec-ch-ua: \"Not/A)Brand\";v=\"99\", \"Brave\";v=\"115\", \"Chromium\";v=\"115\"" -H "sec-ch-ua-mobile: ?0" -H "sec-ch-ua-platform: \"Windows\"" -H "sec-fetch-dest: empty" -H "sec-fetch-mode: cors" -H "sec-fetch-site: cross-site" -H "sec-gpc: 1" -H "user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36" -H "x-graphql-authorization: Bearer <omitted>" --data-raw "{\"query\":\"{  usersCollection {    edges {      node {        test1      }    }  }}\"}"

And these are the headers I get back (formatted for readability):

{
  "baggage": "sentry-environment=production,sentry-release=d5bbed201eb20cc0a1af86619f58cea24cee017d,sentry-public_key=d5e18af8274946988586aab9276cd108,sentry-trace_id=cf9372e30f4e4002b4eb9d6b8bbb3185,sentry-sample_rate=0.002",
  "cf-ipcountry": "FR",
  "cf-visitor": "{\"scheme\":\"https\"}",
  "x-forwarded-port": "443",
  "x-real-ip": "172.71.134.144",
  "host": "localhost:3000",
  "x-consumer-username": "service_role-key",
  "cf-worker": "supabase.co",
  "x-forwarded-host": "wcteuwpjlocwxcjvgtkp.supabase.co",
  "sentry-trace": "cf9372e30f4e4002b4eb9d6b8bbb3185-b06142310af2d6b7-0",
  "accept": "*/*",
  "cf-ray": "7f0d03d771d3f18c-CDG",
  "x-forwarded-prefix": "/graphql/v1",
  "x-consumer-id": "777f6130-904b-5657-ba5f-1e56d7f28356",
  "x-credential-identifier": "764f2ba4-c7e4-5675-8f8d-83fa1c813e09",
  "x-forwarded-proto": "https",
  "x-forwarded-path": "/graphql/v1",
  "user-agent": "node-fetch/1.0 (+https://github.com/bitinn/node-fetch)",
  "authorization": "Bearer <omitted>",
  "content-length": "84",
  "cf-ew-via": "15",
  "accept-encoding": "gzip",
  "x-forwarded-for": "167.88.159.69, 172.71.134.144",
  "connection": "keep-alive",
  "cf-connecting-ip": "167.88.159.69",
  "content-profile": "graphql_public",
  "cdn-loop": "cloudflare; subreqs=1"
}

The prefer: return=representation header is missing.

imor avatar Aug 03 '23 08:08 imor

It's really strange because we have had many discussions around using request.headers for custom logic and it has been working normally. For example, see https://github.com/orgs/supabase/discussions/4419#discussioncomment-4321279

So there must be something up with the graphql endpoint, maybe Kong is stripping the headers.

steve-chavez avatar Aug 03 '23 16:08 steve-chavez

image PostgREST on latest version using Supabase-js passes thru custom headers. See the header custom:"hi there"

GaryAustin1 avatar Aug 03 '23 17:08 GaryAustin1