Noh | エンジニア向け情報共有コミュニティ
Signup / Login

Apollo Client や URQL でリクエストヘッダーやレスポンスヘッダーを操作する

graphql
javascript
typescript
react

投稿日: 2024/06/25

GraphQLのクライエントパッケージとしては Apollo Client や URQL が有名です。

リクエストヘッダーに値をセットしたり、レスポンスヘッダーから値を取得するコードを書いたので記事にしておきます。

今回は例としてCSRFトークンをセットしたり、取り出したりします。

書いてるコードはTypescriptなのでJavascriptで書く人はうまく読み替えてください。

登場するRouterコンポーネントはReactRouterを使ったものですが、別になんでもいいです。

また、説明中に出てくるsessionStorageはブラウザにデータを保存するものです。サーバーサイドで扱うセッションやCookieではないです。
https://developer.mozilla.org/ja/docs/Web/API/Window/sessionStorage

Apollo Client の例

import { ApolloClient, InMemoryCache, ApolloProvider, HttpLink, ApolloLink, } from "@apollo/client"; import Router from "./Router"; const App: React.FC = () => { const httpLink = new HttpLink({ uri: "/graphql" }); const middlewareLink = new ApolloLink((operation, forward) => { operation.setContext(({ headers = {} }) => ({ headers: { ...headers, "X-CSRF-Token": sessionStorage.getItem("csrfToken") || document.querySelector<HTMLMetaElement>('meta[name="csrf-token"]') ?.content || null, }, })); return forward(operation); }); const afterwareLink = new ApolloLink((operation, forward) => { return forward(operation).map((response) => { const context = operation.getContext(); const headers = context.response.headers; if (headers && headers.get("csrf-token")) { sessionStorage.setItem("csrfToken", headers.get("csrf-token")); } return response; }); }); const client = new ApolloClient({ link: ApolloLink.from([middlewareLink, afterwareLink, httpLink]), cache: new InMemoryCache(), }); return ( <ApolloProvider client={client}> <Router /> </ApolloProvider> ); }; export default App;

middlewareLinkの方がリクエストヘッダーにCSRFトークンをセットしています。

sessionStorageにトークンが入っていればそれを使い、なければHTMLのhead内metaタグ内に入ってるトークンを使うようにしてます。

afterwareLinkの方がレスポンスヘッダーからCSRFトークンを取り出しています。

レスポンスヘッダーにトークンが存在すればsessionStorageに保存してます。

URQL

import { createClient, Provider } from "urql"; import Router from "./Router"; const App: React.FC = () => { const client = createClient({ url: "/graphql", fetchOptions: () => { const csrfToken = sessionStorage.getItem("csrfToken") || document.querySelector<HTMLMetaElement>('meta[name="csrf-token"]') ?.content || ""; return { headers: { "X-CSRF-Token": csrfToken, }, }; }, fetch: (...args) => fetch(...args).then((response) => { const csrfToken = response.headers.get("csrf-token"); if (csrfToken) { sessionStorage.setItem("csrfToken", csrfToken); } return response; }), }); return ( <Provider value={client}> <Router /> </Provider> ); }; export default App;

fetchOptionsオプションを使ってリクエストヘッダーに値をセットできます。

公式ドキュメントにあるようにheaders: { ... }のハッシュを返す処理を書けばよいので、ハッシュの中にCSRFトークンを入れてます。

fetchオプションを使ってレスポンスヘッダーから値を取得できます。

Apollo clientの時と同様に、レスポンスヘッダー内にトークンがあればsessionStorageに保存しています。

参考

https://formidable.com/open-source/urql/docs/basics/react-preact/#setting-up-the-client
yosi

Noh を作ってるエンジニア。

目次