Le lien Apollo propose un gestionnaire d'erreurs onError
Problème: Actuellement, nous souhaitons actualiser les jetons oauth lorsqu'ils expirent lors d'un appel apollo et que nous ne pouvons pas exécuter une demande de récupération asynchrone à l'intérieur de onError
correctement.
Code:
initApolloClient.js
import { ApolloClient } from 'apollo-client';
import { onError } from 'apollo-link-error';
import { ApolloLink, fromPromise } from 'apollo-link';
//Define Http link
const httpLink = new createHttpLink({
uri: '/my-graphql-endpoint',
credentials: 'include'
});
//Add on error handler for apollo link
return new ApolloClient({
link: ApolloLink.from([
onError(({ graphQLErrors, networkError, operation, forward }) => {
if (graphQLErrors) {
//User access token has expired
if(graphQLErrors[0].message==="Unauthorized") {
//We assume we have both tokens needed to run the async request
if(refreshToken && clientToken) {
//let's refresh token through async request
return fromPromise(
authAPI.requestRefreshToken(refreshToken,clientToken)
.then((refreshResponse) => {
let headers = {
//readd old headers
...operation.getContext().headers,
//switch out old access token for new one
authorization: `Bearer ${refreshResponse.access_token}`,
};
operation.setContext({
headers
});
//Retry last failed request
return forward(operation);
})
.catch(function (error) {
//No refresh or client token available, we force user to login
return error;
})
)
}
}
}
}
}
}),
Ce qui se produit est:
onError
de ApolloLink
est exécutée.onError
de ApolloLink
est à nouveau exécutée ??undefined
Entre l'étape 5 et 6, apollo ne réexécute pas la requête graphQL initiale qui a échoué et donc le résultat est undefined
.
Erreurs de la console:
Uncaught (in promise) Error: Network error: Error writing result to store for query:
query UserProfile($id: ID!) {
UserProfile(id: $id) {
id
email
first_name
last_name
}
__typename
}
}
La solution devrait nous permettre de:
Je rafraîchis le jeton de cette façon (cela met à jour votre code):
import { ApolloClient } from 'apollo-client';
import { onError } from 'apollo-link-error';
import { ApolloLink, Observable } from 'apollo-link'; // <-- Add Observable
// Define Http link
const httpLink = new createHttpLink({
uri: '/my-graphql-endpoint',
credentials: 'include'
});
// Add on error handler for apollo link
return new ApolloClient({
link: ApolloLink.from([
onError(({ graphQLErrors, networkError, operation, forward }) => {
if (graphQLErrors) {
// User access token has expired
if(graphQLErrors[0].message === "Unauthorized") {
// We assume we have both tokens needed to run the async request
if(refreshToken && clientToken) {
// Let's refresh token through async request
return new Observable(observer => {
authAPI.requestRefreshToken(refreshToken, clientToken)
.then(refreshResponse => {
operation.setContext(({ headers = {} }) => ({
headers: {
// Re-add old headers
...headers,
// Switch out old access token for new one
authorization: `Bearer ${refreshResponse.access_token}` || null,
}
}))
})
.then(() => {
const subscriber = {
next: observer.next.bind(observer),
error: observer.error.bind(observer),
complete: observer.complete.bind(observer)
}
// Retry last failed request
forward(operation).subscribe(subscriber)
})
.catch(error => {
// No refresh or client token available, we force user to login
observer.error(error)
})
})
}
}
}
})
])
})