ApolloGraphQL useQuery 不遵守我的 context/headers 设置
ApolloGraphQL useQuery not respecting my context/headers setting
当我创建我的 ApolloGraph 客户端时,我使用如下代码将 header 设置为“xxx”:
new ApolloClient({
link: new HttpLink({
uri: 'http://localhost:5000/graphql',
credentials: 'same-origin',
headers: {
authorization:
'bearer xxx',
},
}),
然后,我用 ApolloGrapql Provider 包装我的 React 组件,这样我就可以在我的组件中使用 useQuery。
我想通过useQuery传递一个新的授权header,所以我用这样的代码调用它:
const authorization = user && user.jwtToken.length > 0 ? 'bearer ' + user.jwtToken : ' ';
console.log(authorization);
const { loading, error, data } = useQuery(q, {
context: {
headers: { authorization }
}
});
我的 console.log 显示我有一个有效的身份验证令牌,但是当我使用 chrome 开发工具查看什么是 POST 时,这就是授权 header真正被发送的是它显示 xxx 忽略了我放入 useQuery 上下文的内容。
关于如何让我的 header 发送以反映我在 useQuery 中的内容有什么想法吗?
你应该有一个身份验证机制,比如登录、注销、检查令牌等功能 (auth.js) 然后你可以将你的组件包装在高阶组件中,包装一个 Apollo 客户端。
下面是我使用 Strapi 后端的工作代码。
import { InMemoryCache } from "apollo-cache-inmemory";
import { ApolloClient } from "apollo-client";
import { ApolloLink } from "apollo-link";
import { HttpLink } from "apollo-link-http";
import { setContext } from "@apollo/link-context";
import React from "react";
import auth from "../auth/auth";
const httpLink = new HttpLink({
uri: process.env.REACT_APP_API_URL,
cors: false,
});
const authLink = setContext((_, { headers }) => {
const token = auth.getToken() || null;
return token
? {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : "",
},
}
: null;
});
export const client = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache(),
});
const AppProvider = ({ children }) => {
return <ApolloProvider client={client}>{children}</ApolloProvider>;
};
auth.js getting/setting 凭据:
import { isEmpty } from "lodash";
const TOKEN_KEY = "jwtToken";
const USER_INFO = "userInfo";
const parse = JSON.parse;
const stringify = JSON.stringify;
const auth = {
clear(key) {
if (localStorage && localStorage.getItem(key)) {
return localStorage.removeItem(key);
}
if (sessionStorage && sessionStorage.getItem(key)) {
return sessionStorage.removeItem(key);
}
return null;
},
clearAppStorage() {
if (localStorage) {
localStorage.clear();
}
if (sessionStorage) {
sessionStorage.clear();
}
},
clearToken(tokenKey = TOKEN_KEY) {
return auth.clear(tokenKey);
},
clearUserInfo(userInfo = USER_INFO) {
return auth.clear(userInfo);
},
get(key) {
if (localStorage && localStorage.getItem(key)) {
return parse(localStorage.getItem(key)) || null;
}
if (sessionStorage && sessionStorage.getItem(key)) {
return parse(sessionStorage.getItem(key)) || null;
}
return null;
},
getToken(tokenKey = TOKEN_KEY) {
return auth.get(tokenKey);
},
getUserInfo(userInfo = USER_INFO) {
return auth.get(userInfo);
},
set(value, key, isLocalStorage) {
if (isEmpty(value)) {
return null;
}
if (isLocalStorage && localStorage) {
return localStorage.setItem(key, stringify(value));
}
if (sessionStorage) {
return sessionStorage.setItem(key, stringify(value));
}
return null;
},
setToken(value = "", isLocalStorage = false, tokenKey = TOKEN_KEY) {
return auth.set(value, tokenKey, isLocalStorage);
},
setUserInfo(value = "", isLocalStorage = false, userInfo = USER_INFO) {
return auth.set(value, userInfo, isLocalStorage);
},
};
export default auth;
当我创建我的 ApolloGraph 客户端时,我使用如下代码将 header 设置为“xxx”:
new ApolloClient({
link: new HttpLink({
uri: 'http://localhost:5000/graphql',
credentials: 'same-origin',
headers: {
authorization:
'bearer xxx',
},
}),
然后,我用 ApolloGrapql Provider 包装我的 React 组件,这样我就可以在我的组件中使用 useQuery。
我想通过useQuery传递一个新的授权header,所以我用这样的代码调用它:
const authorization = user && user.jwtToken.length > 0 ? 'bearer ' + user.jwtToken : ' ';
console.log(authorization);
const { loading, error, data } = useQuery(q, {
context: {
headers: { authorization }
}
});
我的 console.log 显示我有一个有效的身份验证令牌,但是当我使用 chrome 开发工具查看什么是 POST 时,这就是授权 header真正被发送的是它显示 xxx 忽略了我放入 useQuery 上下文的内容。
关于如何让我的 header 发送以反映我在 useQuery 中的内容有什么想法吗?
你应该有一个身份验证机制,比如登录、注销、检查令牌等功能 (auth.js) 然后你可以将你的组件包装在高阶组件中,包装一个 Apollo 客户端。
下面是我使用 Strapi 后端的工作代码。
import { InMemoryCache } from "apollo-cache-inmemory";
import { ApolloClient } from "apollo-client";
import { ApolloLink } from "apollo-link";
import { HttpLink } from "apollo-link-http";
import { setContext } from "@apollo/link-context";
import React from "react";
import auth from "../auth/auth";
const httpLink = new HttpLink({
uri: process.env.REACT_APP_API_URL,
cors: false,
});
const authLink = setContext((_, { headers }) => {
const token = auth.getToken() || null;
return token
? {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : "",
},
}
: null;
});
export const client = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache(),
});
const AppProvider = ({ children }) => {
return <ApolloProvider client={client}>{children}</ApolloProvider>;
};
auth.js getting/setting 凭据:
import { isEmpty } from "lodash";
const TOKEN_KEY = "jwtToken";
const USER_INFO = "userInfo";
const parse = JSON.parse;
const stringify = JSON.stringify;
const auth = {
clear(key) {
if (localStorage && localStorage.getItem(key)) {
return localStorage.removeItem(key);
}
if (sessionStorage && sessionStorage.getItem(key)) {
return sessionStorage.removeItem(key);
}
return null;
},
clearAppStorage() {
if (localStorage) {
localStorage.clear();
}
if (sessionStorage) {
sessionStorage.clear();
}
},
clearToken(tokenKey = TOKEN_KEY) {
return auth.clear(tokenKey);
},
clearUserInfo(userInfo = USER_INFO) {
return auth.clear(userInfo);
},
get(key) {
if (localStorage && localStorage.getItem(key)) {
return parse(localStorage.getItem(key)) || null;
}
if (sessionStorage && sessionStorage.getItem(key)) {
return parse(sessionStorage.getItem(key)) || null;
}
return null;
},
getToken(tokenKey = TOKEN_KEY) {
return auth.get(tokenKey);
},
getUserInfo(userInfo = USER_INFO) {
return auth.get(userInfo);
},
set(value, key, isLocalStorage) {
if (isEmpty(value)) {
return null;
}
if (isLocalStorage && localStorage) {
return localStorage.setItem(key, stringify(value));
}
if (sessionStorage) {
return sessionStorage.setItem(key, stringify(value));
}
return null;
},
setToken(value = "", isLocalStorage = false, tokenKey = TOKEN_KEY) {
return auth.set(value, tokenKey, isLocalStorage);
},
setUserInfo(value = "", isLocalStorage = false, userInfo = USER_INFO) {
return auth.set(value, userInfo, isLocalStorage);
},
};
export default auth;