-
Notifications
You must be signed in to change notification settings - Fork 235
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Execute against different schemas based on request headers #913
Comments
This question is fairly not obvious and something that Mercurius should support better. This could be managed via Fastify Constraints and plugin encapsulation. Essentially you'd register two instances of Mercurius, adding different routes with different constraints. I would recommend to enable GraphiQL on only one of those multiple plugins. I have never done this myself, so you'd possibly be on uncharted territory with bugs to fix. |
Thanks @mcollina, it was pretty straight-forward with those keywords! The only unexpected thing was requiring I haven't tested this extensively yet outside of just using the Let me know if you'd like me to create a PR to add this to the examples (and any adjustments/commentary you'd like), not sure how frequently it'd be encountered. 'use strict'
const Fastify = require('fastify')
const mercurius = require('..')
const schemaStrategy = {
name: 'schema',
storage: function () {
const handlers = {}
return {
get: (type) => { return handlers[type] || null },
set: (type, store) => { handlers[type] = store }
}
},
deriveConstraint: (req, ctx) => {
return req.headers.schema
},
validate: () => true,
mustMatchWhenDerived: true
}
const app = Fastify({ constraints: { schema: schemaStrategy } })
const schema = `
type Query {
add(x: Int, y: Int): Int
}
`
const resolvers = {
Query: {
add: async (_, obj) => {
const { x, y } = obj
return x + y
}
}
}
app.register(async childServer => {
childServer.register(mercurius, {
schema,
resolvers,
graphiql: false,
routes: false
})
childServer.route({
path: '/',
method: 'POST',
constraints: { schema: 'A' },
handler: (req, reply) => {
const query = '{ add(x: 2, y: 2) }'
return reply.graphql(query)
}
})
})
const schema2 = `
type Query {
subtract(x: Int, y: Int): Int
}
`
const resolvers2 = {
Query: {
subtract: async (_, obj) => {
const { x, y } = obj
return x - y
}
}
}
app.register(async childServer => {
childServer.register(mercurius, {
schema: schema2,
resolvers: resolvers2,
graphiql: false,
routes: false
})
childServer.route({
path: '/',
method: 'POST',
constraints: { schema: 'B' },
handler: (req, reply) => {
const query = '{ subtract(x: 10, y: 5) }'
return reply.graphql(query)
}
})
})
app.listen({ port: 3000 }) |
Out of curiosity, how many different schemas will there be? Scott |
Somewhere between 1 and ~30 different schemas will be in place, it changes on a case-by-case basis |
@curtiswilkinson - Is it for some sort of multi-tenancy system? And, are you trying to switch to Mercurius because the other GraphQL servers were slow with this setup? Scott |
@smolinari it is along these lines yes! The goal of this investigation is to see if Mercurius generally makes sense as a next step and if it allows us to shed some of our older home-grown parts (which so far appears to be the case). |
@curtiswilkinson I would be interested to read about the outcome of the work you've done in this area. Ideally this outcome is captured in the docs because I assume that other people may want to set up something similar, and having a guide showing them how to do this would be quite useful. Do you have any appetite for putting something like this together? |
Hi folks, I create a simple pr for adding this case to the examples folder and in the FAQ docs section #979. Happy to know your opinion. |
docs: document schema by http header (#913)
I have a scenario where based on a request header coming from the client, the query should be executed against a completely seperate GraphQL Schema.
req.header.schema === 'A'
-> execute againstschema A
req.header.schema === 'B'
-> execute againstschema B
I've handled this situation in a number of other GraphQL implementations, and was interested in using Mercurius if it's straight-forward.
Apologies if this is an obvious question or if it's more related to fastify (which I admittedly have very little experience with). I've done some digging and couldn't see a straight-forward way without doing something very hand-rolled.
I'd appreciate any guidance if you have any! I'd love to use Mercurius, as the benchmarking I've done has been very positive.
The text was updated successfully, but these errors were encountered: