apollographql / apollo-client-nextjs

Apollo Client support for the Next.js App Router
https://www.npmjs.com/package/@apollo/experimental-nextjs-app-support
MIT License
358 stars 25 forks source link

Adding headers to client side queries. #279

Closed jacob-af closed 1 month ago

jacob-af commented 1 month ago

Apologies if this has been addressed, I feel like i've look high and low.

I cannot find a way to attach headers to queries made with useQuery on the client side. I have tried both adding:

function makeClient() {
  const httpLink = new HttpLink({
    uri: process.env.NEXT_PUBLIC_GQL_API_URL,
    fetchOptions: { cache: "no-store" },
    headers: {
      Authorization: authTokens() ? `Bearer ${authTokens()}` : ""
    }
  });

  return new NextSSRApolloClient({
    cache: new NextSSRInMemoryCache(),
    link:
      typeof window === "undefined"
        ? ApolloLink.from([
            new SSRMultipartLink({
              stripDefer: true
            }),
            httpLink
          ])
        : httpLink
  });
}

when declaring the client and also tried:

const { data, error } = useQuery(QUERY_THAT_NEEDS_AUTHTOKEN, 
  {context: {
       headers: {
              Authorization: authTokens() ? `Bearer ${authTokens()}` : ""
        }
}});

on an individual query level.

The former doesn't seem to work client side, but attaching headers in the makeClient function server side work with the regular ApolloClient and InMemoryCache
The latter approach works with Mutations, but not Queries.
If I remove the need for an Auth header on the backend, the query works as expected. Is there a trick with Links?

What can I say, I'm losing my head for a lack of headers.

jacob-af commented 1 month ago

This works, based off the things I found deep in a thread on a still open issue.

"use client";

import { HttpLink, ApolloLink } from "@apollo/client";
import { setContext } from "@apollo/client/link/context";
import {
  ApolloNextAppProvider,
  NextSSRApolloClient,
  SSRMultipartLink,
  NextSSRInMemoryCache
} from "@apollo/experimental-nextjs-app-support/ssr";

import { authTokens } from "@/app/Apollo/authTokens";

const authLink = setContext(async (_, { headers }) => {
  if (!authTokens()) return { headers: { ...headers } };
  const token = authTokens();

  return {
    headers: {
      ...headers,
      Authorization: token ? `Bearer ${token}` : ""
    }
  };
});

function makeClient() {
  const httpLink = new HttpLink({
    uri: process.env.NEXT_PUBLIC_GQL_API_URL,
    fetchOptions: { cache: "no-store" }
  });
  return new NextSSRApolloClient({
    cache: new NextSSRInMemoryCache(),
    link:
      typeof window === "undefined"
        ? ApolloLink.from([
            new SSRMultipartLink({
              stripDefer: true
            }),
            authLink.concat(httpLink)
          ])
        : authLink.concat(httpLink)
  });
}

export function ApolloWrapper({ children }: React.PropsWithChildren) {
  return (
    <ApolloNextAppProvider makeClient={makeClient}>
      {children}
    </ApolloNextAppProvider>
  );
}
github-actions[bot] commented 1 month ago

Do you have any feedback for the maintainers? Please tell us by taking a one-minute survey. Your responses will help us understand Apollo Client usage and allow us to serve you better.