Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[graphiql] Sending extensions in request #3372

Open
dondonz opened this issue Jul 26, 2023 · 6 comments
Open

[graphiql] Sending extensions in request #3372

dondonz opened this issue Jul 26, 2023 · 6 comments

Comments

@dondonz
Copy link

dondonz commented Jul 26, 2023

Hello, it can be useful to send extensions in a GraphQL request and I'd like to know if you're interested in supporting this feature.

At work, I have a use case where I want to send metadata via the extensions key in a GraphQL request. This metadata is then used to toggle behaviour in the GraphQL service, which is very useful for developers wanting to quickly iterate and test ideas in staging.

I saw a previous discussion about request extensions from 2017. Given that GraphiQL has changed significantly since then, I thought it could be easier to implement this now.

Would you consider this as a feature? I am happy to help out.

@acao
Copy link
Member

acao commented Jul 26, 2023

@dondonz yes, for sure! considering it's part of the spec, I would say we should support it as a requirement. Technically it is supported in that the fetcher prop supports any promise resolved exec request you like, but would you suggest additional features somehow? createGraphiQlFetcher () we've added to make creating a fetcher implementation easier, and additional headers can be supplied, but should we give users the ability to extens the request payload with this abstraction as well? and do we need to allow more keys in the response payload outside data as well? how do you see this working?

@dondonz
Copy link
Author

dondonz commented Jul 27, 2023

Thanks @acao for considering this feature!

I would like to add an extra tab for extensions in the UI, next to the tabs for variables and HTTP headers. In terms of the code, my plan was to essentially mirror what is already there for query variables, and insert the values into the extensions key of the request payload. Hopefully I can do that with a small change, as you say the fetcher technically supports it.

I think only adding the extensions key will be enough to be useful and also remain compliant with the GraphQL over HTTP spec.

The extensions key is a map without any restrictions, so I think that would be the best place to add any extra metadata, instead of enabling additional non-spec top level keys.

Additionally, I think we should restrict ourselves to the top level request keys defined in the spec, otherwise the GraphQL engine in the backing service may not recognise or read the extra top level keys. For example, I help out with GraphQL Java and the engine's representation of a request (ExecutionInput) would only include the top level keys defined in the spec.

And I'll admit, I have a bias for keeping the PR's scope small so I can get it done and merged faster!

Of course, this is your project so I am very open to ideas and advice. Thanks also for your time spent on maintaining this project!!

If you're happy to go ahead, I can give this a try and open a PR.

@acao
Copy link
Member

acao commented Jul 27, 2023

Here is a quick example for simple HTTP queries/mutations if you have static extensions at runtime

import type { Fetcher } from '@graphiql/toolkit'

import myExtensions from './extensions.json'

const fetcher: Fetcher = async (graphQLParams, { headers }) => {
  const data = await fetch(
    'https://myurl',
    {
      method: 'POST',
      headers: {
        ... headers,
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ 
         ...graphQLParams, 
        extensions: myExtensions
        }),
      credentials: 'same-origin',
    },
  );
  return data.json().catch(() => data.text());
};

<GraphiQL fetcher={fetcher} />

You can also create the fetcher dynamically with user input in say, a react component, and just wrap it in useMemo() or useCallback() depending on the use case

if you want to open a PR, then you could add this key as a config option when calling createGraphiQLFetcher() in @graphiql/toolkit

the fetcher prop is one of the original power features of this project, from long before I became a maintainer in 2018! It can also accept subscriptions and async iterables.

I'm quite busy with interviews lately but I should be able to answer more questions next week!

@dondonz
Copy link
Author

dondonz commented Jul 28, 2023

Fabulous thank you @acao ! And no worries you have given so much context and help already, take your time with work stuff first.

@acao
Copy link
Member

acao commented Jul 28, 2023

glad to help @dondonz ! thank you, and let me know when/if atlassian is hiring, these early stage Berlin startups are exhausting 😂

@dondonz
Copy link
Author

dondonz commented Aug 1, 2023

@acao yeah there are always roles open, and we're big on GraphQL! I'll message you on LinkedIn (or let me know if another way is better)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants