@@ -31,20 +31,16 @@ function getServerCookie(
3131) {
3232 const cookie = headers ?. cookie ;
3333 if ( cookie == null ) {
34- // eslint-disable-next-line no-console
35- console . warn ( "cookie not found in headers" , headers ) ;
3634 return null ;
3735 }
3836 const decoded = qs . decode ( cookie , "; " ) ;
3937 const token = decoded [ name ] ;
4038 if ( token == null ) {
41- // eslint-disable-next-line no-console
42- console . warn ( `${ name } not found in cookie` , decoded ) ;
4339 return null ;
4440 }
4541 if ( Array . isArray ( token ) ) {
4642 // eslint-disable-next-line no-console
47- console . warn ( `multiple ${ name } in cookies` , decoded ) ;
43+ console . warn ( `multiple ${ name } in cookies` , token ) ;
4844 return token [ 0 ] ;
4945 }
5046 return token ;
@@ -55,28 +51,46 @@ export function createApolloClient(
5551 ctx ?: GetServerSidePropsContext < ParsedUrlQuery , PreviewData >
5652) {
5753 const isServer = typeof window === "undefined" ;
54+
55+ const uri = buildGraphQLUrl ( hostUrl , env . ENABLE_FETCH_HACK ) ;
5856 const csrfToken = isServer
5957 ? getServerCookie ( ctx ?. req ?. headers , "csrftoken" )
6058 : getCookie ( "csrftoken" ) ;
6159
62- const sessionCookie = isServer
63- ? getServerCookie ( ctx ?. req ?. headers , "sessionid" )
64- : getCookie ( "sessionid" ) ;
65-
66- const uri = buildGraphQLUrl ( hostUrl , env . ENABLE_FETCH_HACK ) ;
67-
68- // TODO on client side we might not need this (only on SSR)
69- const enchancedFetch = ( url : RequestInfo | URL , init ?: RequestInit ) => {
60+ const enchancedFetch = async ( url : RequestInfo | URL , init ?: RequestInit ) => {
7061 const headers = new Headers ( {
7162 ...( init ?. headers != null ? init . headers : { } ) ,
63+ // TODO missing csrf token is a non recoverable error
7264 ...( csrfToken != null ? { "X-Csrftoken" : csrfToken } : { } ) ,
73- // NOTE server requests don't include cookies by default
74- // TODO include session cookie here also when we use SSR for user specific requests
75- ...( csrfToken != null ? { Cookie : `csrftoken=${ csrfToken } ` } : { } ) ,
7665 } ) ;
7766
78- if ( sessionCookie != null ) {
79- headers . append ( "Cookie" , `sessionid=${ sessionCookie } ` ) ;
67+ // NOTE server requests don't include cookies by default
68+ // TODO do we want to copy request headers from client or no?
69+ if ( isServer ) {
70+ if ( csrfToken == null ) {
71+ throw new Error ( "csrftoken not found in cookies" ) ;
72+ }
73+ headers . append ( "Set-Cookie" , `csrftoken=${ csrfToken } ` ) ;
74+ headers . append ( "Cookie" , `csrftoken=${ csrfToken } ` ) ;
75+ // Django fails with 403 if there is no referer (only on Kubernetes)
76+ const requestUrl = ctx ?. req ?. url ?? "" ;
77+ const hostname =
78+ ctx ?. req ?. headers ?. [ "x-forwarded-host" ] ??
79+ ctx ?. req ?. headers ?. host ??
80+ "" ;
81+ // NOTE not exactly correct
82+ // For our case this is sufficent because we are always behind a proxy,
83+ // but technically there is a case where we are not behind a gateway and not localhost
84+ // so the proto would be https and no x-forwarded-proto set
85+ // TODO we have .json blobs in the referer (translations), does it matter?
86+ const proto = ctx ?. req ?. headers ?. [ "x-forwarded-proto" ] ?? "http" ;
87+ headers . append ( "Referer" , `${ proto } ://${ hostname } ${ requestUrl } ` ) ;
88+
89+ const sessionCookie = getServerCookie ( ctx ?. req ?. headers , "sessionid" ) ;
90+ if ( sessionCookie != null ) {
91+ headers . append ( "Cookie" , `sessionid=${ sessionCookie } ` ) ;
92+ headers . append ( "Set-Cookie" , `sessionid=${ sessionCookie } ` ) ;
93+ }
8094 }
8195
8296 return fetch ( url , {
@@ -89,7 +103,7 @@ export function createApolloClient(
89103 uri,
90104 // TODO this might be useless
91105 credentials : "include" ,
92- // @ts -expect-error: TODO undici ( node fetch) is a mess
106+ // @ts -expect-error: node- fetch is a subset of fetch API
93107 fetch : enchancedFetch ,
94108 } ) ;
95109
0 commit comments