logaretm / villus

🏎 A tiny and fast GraphQL client for Vue.js

Home Page:https://villus.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to set the headers for the batch plugin

DaLukasDev opened this issue · comments

Hi!
First of all, amazing GraphQL client!

There is however one thing I can't seem to figure out.
I was wondering how I should set the headers for the batch plugin.
Without the batch plugin I made an auth plugin as stated in the docs and this works fine until I add the batch plugin to the mix.
I need to set the credentials to include as well as set an X-XSRF-TOKEN header.
if I add the batch plugin the requests all return a 419 No reason phase as the X-XSRF-TOKEN header doesn't get set.

How should I do that?

It should work fine but you need to make sure the batch plugin is applied last. The order of plugins is important here.

I don't have enough information here, can you post some code samples?

I'm working with Laravel sanctums session cookies.
I made an authplugin which set the token as follows:

const authPlugin = definePlugin(({ opContext }) => {
  const xsrf = RegExp('XSRF-TOKEN[^;]+').exec(document.cookie);
  opContext.headers['X-XSRF-TOKEN'] = decodeURIComponent(
    xsrf ? xsrf.toString().replace(/^[^=]+./, '') : ''
  );
  opContext.credentials = 'include';
});

My client I created looks like this:

export const client = createClient({
  url: import.meta.env.VITE_GRAPH_URL,
  cachePolicy: 'network-only',
  use: [authPlugin, ...defaultPlugins()],
});

This works just fine but when i'm using the batch plugin like this:

export const client = createClient({
  url: import.meta.env.VITE_GRAPH_URL,
  cachePolicy: 'network-only',
  use: [authPlugin, batch()],
});

My API returns a 419 no reason phase.

I did however find out that in the request headers with the 1st setup a Cookie: XSRF-TOKEN gets send while with the batch plugin this doesn't happen.

Request headers:
Without batch:

    POST /graphql/ HTTP/2
    Host: xxx.lokal.host
    User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:103.0) Gecko/20100101 Firefox/103.0
    Accept: */*
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate, br
    Referer: https://xxx.lokal.host/
    content-type: application/json
    X-XSRF-TOKEN: xxxx
    Content-Length: 161
    Origin: https://xxx.lokal.host
    Connection: keep-alive
    Cookie: XSRF-TOKEN=xxxxx
    Sec-Fetch-Dest: empty
    Sec-Fetch-Mode: cors
    Sec-Fetch-Site: same-site
    Pragma: no-cache
    Cache-Control: no-cache
    TE: trailers

With batch:

    POST /graphql/ HTTP/2
    Host :xxx.lokal.host
    User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:103.0) Gecko/20100101 Firefox/103.0
    Accept: */*
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate, br
    Referer: https://xxx.lokal.host/
    content-type: application/json
    X-XSRF-TOKEN: xxxx
    Content-Length: 239
    Origin: https://xxx.lokal.host
    Connection: keep-alive
    Sec-Fetch-Dest: empty
    Sec-Fetch-Mode: cors
    Sec-Fetch-Site: same-site
    Pragma: no-cache
    Cache-Control: no-cache
    TE: trailers

From what I can see in your example responses. The X-XSRF-TOKEN seems to be there in both cases unless you mistakenly copied a different response.

I have a similar setup with a Rails server and it's working as expected. Is your server capable of handling batched queries?

If it is possible to set up a simple Laravel repo to test this issue that would be great, otherwise it will be guesswork on my part.

It should be according to Lighthouse-PHP. I'll set up a simple laravel repo tomorrow to see if it is a problem in my current configuration.
Could it be possible the opContext.credentials = 'include' isn't sticking for some reason? As there is a cookie object without the batch and with batch enabled this dissapears? I think Sanctum uses this as well to authenticate. If I remove it in my authplugin then I get the same behavior as with the batch plugin. In the batch plugin source I see you only spread the opContext.headers in the fetch object and the opContext.credentials do not get set. This is a hard requirement for Laravel/Sanctum

I can confirm that with adding the credentials: opContext.credentials it is fixed. I opened a PR for you to review.

Thanks for #167 this resolves this issue indeed and I have added a test in 281aedd.

This is now released in 1.2.5