While upgrading from Apollo v2 to v3, I'm trying to make some external API calls to an auth server. Currently, I'm using nock to intercept the requests inside of a unit test.
The GET request keeps failing when I try to attach a token in the request header because the context is undefined. Why would the context be undefined here? This worked prior to upgrading.
server.js
const {ApolloServer} = require('apollo-server-koa'),
CustomApi = require('../service/customapi'),
...;
const apolloServer = new ApolloServer({
typeDefs: [DateTypeDefinition, root.typeDef, user.typeDef, ...],
resolvers: [{Date: DateResolver}, root.resolvers, user.resolvers, ...],
validationRules: [depthLimit(10)],
plugins: [
graphqlLogger
],
dataSources: () => {
return {
customApi: new CustomApi()
};
},
context: async (req) => {
const user = await extract(req);
return {
user,
...
}
}
})
module.exports = apolloServer;
resolvers.js
syncAccount: async (parent, _, context) => {
allowed(context.user);
const reviewer = await getReviewerByEmail(context.user.email);
if (reviewer && reviewer.status === 'INVITED') {
const account = await context.dataSources.customApi.getAccount();
...
}
customapi.js
const {RESTDataSource} = require('@apollo/datasource-rest'),
config = require('config')
class CustomAPI extends RESTDataSource {
constructor() {
super();
this.baseURL = `${config.customapi.url}/path/api`;
}
willSendRequest(path, request) {
//ERROR HERE
console.log("willSendRequest - this.context: ", this.context); // prints undefined
request.headers.set('Authorization', this.context.user.token);
}
async getAccount() {
return await this.get('account');
}
...
}
package.json versions:
"@apollo/datasource-rest": "^6.2.2",
"@koa/cors": "^3.1.0",
"apollo-server": "^3.13.0",
"apollo-server-koa": "^3.13.0",
"dataloader": "^2.0.0",
"graphql": "^16.8.1",
"graphql-depth-limit": "^1.1.0",
"graphql-scalars": "^1.22.4",
"graphql-upload": "^13.0.0",
"koa": "^2.13.0",
"koa-bodyparser": "^4.3.0",
"koa-jwt": "^4.0.0",
"koa-router": "^9.4.0",
...
Instead of retrieving the context from within the RESTDataSource, I deleted the willSendRequest overridden function and instead passed in the token:
async getAccount(token) {
return await this.get('account', undefined, {
headers: {
'Authorization': token
}
});
}
EDIT:
If you are using apollo/datasource-rest version 5 or 6 now, the function has changed to use only 2 function parameters now, combine your url params with your headers:
async getAccount(token) {
return await this.get('account', {
param1: param1,
param2: param2,
headers: {
'Authorization': token
}
});
}