I have a subgraph microservice that handles sessions. We store our sessions via cookies that the subgraph creates, and should set it via the set-cookie header. Only issue is my gateway does not seem to be forwarding the set-cookie header from the subgraph to the client.
Here is the code for my gateway
const { ApolloServer } = require('apollo-server');
const { ApolloGateway, RemoteGraphQLDataSource } = require('@apollo/gateway');
const { readFileSync } = require('fs');
const supergraphSdl = readFileSync('./gateway/supergraph.graphql').toString();
class CookieDataSource extends RemoteGraphQLDataSource {
didReceiveResponse({ response, request, context }) {
const cookie = response.http.headers.get('set-cookie');
console.log("Cookie:", cookie)
return response;
}
}
const gateway = new ApolloGateway({
supergraphSdl,
buildService({url}) {
return new CookieDataSource({url});
}
});
const server = new ApolloServer({
gateway,
cors: {
origin: ["http://localhost:3000", "https://studio.apollographql.com"],
credentials: true
},
csrfPrevention: true,
});
server.listen().then(({ url }) => {
console.log(`🚀 Gateway ready at ${url}`);
}).catch(err => {console.error(err)});
version info “@apollo/gateway”: “^2.1.2”, “apollo-server”: “^3.10.2”,
I can confirm that the subgraph is sending back a set-cookie header, however, it is not being passed through to the client.
Thank you!
I ended up resolving the issue by creating both a gateway datasource that added context value. Then, pass the header from the subgraph context value to the response header.
import { GatewayGraphQLResponse, GatewayGraphQLRequestContext } from '@apollo/server-gateway-interface';
import { RemoteGraphQLDataSource } from '@apollo/gateway';
import { ApolloServerPlugin, GraphQLRequestContext, GraphQLRequestListener } from '@apollo/server';
interface ServerContext {
passthrough_cookies?: string
}
export class CookieProcessorDataSource extends RemoteGraphQLDataSource {
didReceiveResponse({response, context}: Required<Pick<GatewayGraphQLRequestContext<Record<string, any>>, 'request' | 'response' | 'context'>>): GatewayGraphQLResponse | Promise<GatewayGraphQLResponse> {
context.passthrough_cookies = response.http?.headers.get('set-cookie');
return response;
}
}
export class CookieServerListener implements GraphQLRequestListener<ServerContext> {
public willSendResponse({contextValue, response}: GraphQLRequestContext<ServerContext>): Promise<void> {
if (contextValue.passthrough_cookies !== undefined) {
response.http.headers.set('set-cookie', contextValue.passthrough_cookies);
}
return Promise.resolve()
}
}
export class CookieServerPlugin implements ApolloServerPlugin<ServerContext> {
async requestDidStart() {
return new CookieServerListener();
}
}