The documentation shows how to add a authorization header:
Supply req.options.headers.authorization in a middleware.
How can we add a custom header my-custom-header with value header:header-value to all queries?
Yep - you can do it the same way. Have you tried it? req.options.headers["my-custom-header"] = "header:header-value"
Can the header value dynamically assigned upon .query call?
So far I haven't found a way to add additional parameters to .query which could be read in middleware, is there?
@fikriauliya it's not currently possible to pass additional parameters to query that are passed to the middleware layer. Could you describe your use-case?
I have multiple GraphQL endpoints. As suggested https://github.com/apollographql/apollo-client/issues/84#issuecomment-207656752, instead of creating multiple Apollo client, I created a proxy server to dispatch a GraphQL query to the corresponding server.
The way the proxy determine where to dispatch to is by HTTP header
(e.g. service: tracker => goes to tracker server, service: transaction, etc).
And this HTTP Header should be dynamically injected during apolloClient.query via one of its parameter.
apolloClient.query({ variable, query, service: 'tracker'}) --> Apollo middleware converts service: tracker to HTTP Header --> graphql.domain.com checks the header --> tracker.domain.com
I think the goal of doing the proxying on the server should be that the client is not aware of which server it is talking to. Perhaps you can use the root field names of the query? I feel like hard coding which graphql service you are talking to in each component might make things very hard to change down the road.
Perhaps you can use the root field names of the query?
Thought about the same as well @stubailo . But I think there are two problems with that approach:
1) The root field name may be shared among multiple services. e.g.:
me {
recommendation { } => goes to recommendation service
}
and
me {
profile { } => goes to profile service
}
2) The proxy server may do more by decoding the GraphQL query and match on recommendation and profile fields instead. But I am afraid of the overhead (compared to simply match on HTTP Header which could be done in Nginx without any GraphQL server)
Rethinking again, my approach above couldn't handle single query which need to retrieve from multiple servers:
me {
recommendation { } => goes to recommendation service
profile { } => goes to profile service
}
Now I am thinking to use approach (2) above: Instead of having simple Nginx proxy server, put GraphQL proxy server on top of Nginx, decode the JSON query, and dispatch based on JSON query.
Or do you have better alternatives?
Came across this, also. Basically looking to aggregate many data sources under a single graphql api. Eg. some rest, but also some graphql endpoints
ala api gateway'ish. Coming to similar conclusion of having resolvers that dispatch to different network interfaces/connectors.
so
App layer (views/internal server app specific concerns)->graphql API gateway-> [1..n] endpoints (rest, another graphql api, traditional data stores, geodata, whatev)
Completely off base?
set header value dynamically is messy
but if you add customer headers in your client, don't forget to add those fields in your 'Access-Control-Allow-Headers' on your server side, because browser CORS preflight ( request that uses the HTTP OPTIONS)
SERVER:
server.use('/graphql', (req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With, myCustomHeader1, myCustomHeader2,');
if (req.method === 'OPTIONS') {
res.sendStatus(200);
} else {
next();
}
});
CLIENT:
(..)
networkInterface.use([{
applyMiddleware(req, next) {
if (!req.options.headers) {
req.options.headers = {}; // Create the header object if needed.
}
req.options.headers.authorization = session.token ? `Bearer ${session.token}` : null;
if (session.token) {
req.options.headers.myCustomHeader1 = something...;
req.options.headers.myCustomHeader2 = something...;
}
next();
},
}]);
(..)