因此,我弄清楚了如何设置中间件来处理我的身份验证令牌,以及在需要时获取新令牌。问题是,在解决承诺后,在没有设置适当的标头的情况下转发该操作,导致存在另一个可能未经身份验证的调用的情况。我觉得这里的技巧很简单,但是我似乎无法弄清楚。有没有办法将承诺中的结果返回到包含的函数中?关于这一点,我还没有找到太多的运气,但是也许还有另一种方法。这是设置我的中间件和Apollo客户端的代码:
const authLink = new ApolloLink((operation, forward) => {
operation.setContext(({ headers = {} }) => {
const token = localStorage.getItem('token');
const tokenExp = token ? decodeJWT(token).exp : null;
const currentTime = Date.now() / 1000;
if(token && tokenExp >= currentTime) {
// Check if token is expired. If so, get a new one and THEN
// move forward
headers = { ...headers,authorization: token ? `Bearer ${token}` : "", };
return { headers };
} else {
// TODO: This would be replaced with the token service that actually
// takes an expired token and sends back a valid one
return fetch('http://localhost:4000/topics', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: `mutation LOGIN_USER(
$email: String
$password: String!
) {
login(email: $email, password: $password) {
id
token
}
}
`,
variables: {
email: "test@test.com",
password: "test"
}
}),
}).then(response => {
return response.json()
})
.then(({ data: { login: { token } }}) => {
// Put updated token in storage
localStorage.setItem('token', token);
headers = { ...headers,authorization: token ? `Bearer ${token}` : "", };
return { headers };
});
}
});
return forward(operation);
});
/**
* Setup the URLs for each service
*/
const httpTopicsServiceLink = createHttpLink({
uri: 'http://localhost:4000/topics',
});
/**
* Create the client instance for each GraphQL server URL
*/
export const TopicsClient = new ApolloClient({
link:authLink.concat(httpTopicsServiceLink),
cache: new InMemoryCache(),
});
答案 0 :(得分:0)
您可以返回自己的Promise,该Promise将使用标题或获取请求中的另一个Promise进行解析:
const authLink = new ApolloLink(async (operation, forward) => {
return await operation.setContext(({ headers = {} }) => {
const token = localStorage.getItem('token');
const tokenExp = token ? decodeJWT(token).exp : null;
const currentTime = Date.now() / 1000;
return new Promise((resolve, reject) => {
if(token && tokenExp >= currentTime) {
// Check if token is expired. If so, get a new one and THEN
// move forward
headers = { ...headers,authorization: token ? `Bearer ${token}` : "", };
resolve({ headers });
} else {
// TODO: This would be replaced with the token service that actually
// takes an expired token and sends back a valid one
resolve(fetch('http://localhost:4000/topics', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: `mutation LOGIN_USER(
$email: String
$password: String!
) {
login(email: $email, password: $password) {
id
token
}
}
`,
variables: {
email: "test@test.com",
password: "test"
}
}),
}).then(response => {
return response.json()
})
.then(({ data: { login: { token } }}) => {
// Put updated token in storage
localStorage.setItem('token', token);
headers = { ...headers,authorization: token ? `Bearer ${token}` : "", };
return { headers };
}));
}
});
}).then(res => {
return forward(operation);
});
});
无法测试,所以我可能错过了一些东西,但这应该确保请求在转发之前完成。