How to use it with Apollo Server?
FluorescentHallucinogen opened this issue · 13 comments
Is it possible to use it with Apollo Server? More precisely with apollo-server-express?
If yes, could you please add the sample code to README.md
?
It's definitely possible. I just briefly looked into the apollo-server-express code. You can create the validation rule similar to the example give in the README for the use with express-graphql.
(Not tested):
import { graphqlExpress } from 'apollo-server-express';
const myGraphQLSchema = // ... define or import your schema here!
const PORT = 3000;
const app = express();
// bodyParser is needed just for POST.
app.use('/graphql', bodyParser.json(), graphqlExpress((req, res) => {
// Extract variables from req object here to pass to validation rule
return {
schema: myGraphQLSchema,
validationRules: [
// Add queryComplexity configuration here
]
}
}));
If you have a full working version, a PR to the README would be appreciated.
@ivome
The new Apollo Server 2.0 has changed the API and now ApolloServer
constructor accept a config as a parameter, when you can place validationRules
but they only take ValidationContext
as a callback function argument, so there's no req.variables
access.
Can we somehow use getVariableUsages(node: NodeWithSelectionSet): ReadonlyArray<VariableUsage>;
method on context to get this?
@19majkel94 Unfortunately this does not work as far as I can tell. This only returns the definitions of the variable nodes, not the actual values. The problem is that the variable values are not part of the ValidationContext in graphql-js.
I can only think of two options:
- Add the variables to the ValidationContext in graphql-js, not sure how big of a project that would be and if it's even desired.
- Change apollo-server so that it supports the dynamic creation of configuration options based on the request.
I haven't looked at the source code of ApolloServer 2 in detail, but nr 2 is probably the best option as this also opens up the possibility to write other dynamic validation rules (restrict parts of the schema for certain IP blocks / user agents etc.)
Or any other ideas?
Change apollo-server so that it supports the dynamic creation of configuration options based on the request. I haven't looked at the source code of ApolloServer 2 in detail...
I've looked at it and they just pass the array of validators to graphql-js
, so the only option is to create a wrapper to inject the additional "context" using closure.
I will open an issue on apollo-server repo for that 😉
I just published version v0.3.0 of this library which adds a helper function getComplexity
to calculate the complexity outside of the validation phase. This could be used pretty much anywhere where the query and variables are available:
https://github.com/slicknode/graphql-query-complexity#calculate-query-complexity
How to use validation for graphql-upload multipart request?
curl localhost:12250/graphql -F operations='{ "query": "mutation ($file: Upload!) { uploadImage(file: $file) }", "variables": { "file": null } }' -F map='{ "0": ["variables.file"] }' -F 0=@file.txt {"errors":[{"message":"Argument \"file\" of required type \"Upload!\" was provided the variable \"$file\" which was not provided a runtime value.","locations":[{"line":1,"column":47}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED","exception":{"stacktrace":["GraphQLError: Argument \"file\" of required type \"Upload!\" was provided the variable \"$file\" which was not provided a runtime value."," at Object.getArgumentValues (node_modules/graphql/execution/values.js:181:15)"," at node_modules/graphql-query-complexity/src/QueryComplexity.ts:198:24"," at Array.reduce (<anonymous>)"," at QueryComplexity.nodeComplexity (node_modules/graphql-query-complexity/src/QueryComplexity.ts:182:56)"," at QueryComplexity.onOperationDefinitionEnter (node_modules/graphql-query-complexity/src/QueryComplexity.ts:144:33)"," at Object.enter (node_modules/graphql/language/visitor.js:332:29)"," at Object.enter (node_modules/graphql/language/visitor.js:383:25)"," at visit (node_modules/graphql/language/visitor.js:250:26)"," at Object.validate (node_modules/graphql/validation/validate.js:63:22)"," at validate (node_modules/apollo-server-core/src/requestPipeline.ts:423:22)"]}}}]}
@ivome
With getComplexity
I was able to integrate this library with Apollo Server 💪
Here is a working example:
https://github.com/19majkel94/type-graphql/blob/4501867fffe3e6f5b3e71af0b71651efcd48d9c3/examples/query-complexity/index.ts#L16-L64
For anyone who comes across this, looking to define cost complexity using the fieldExtensionsEstimator
, but defining their schema using apollo typeDefs
and resolvers
I've created an example at digicatapult/graphql-complexity-experiment based on the example given by @MichalLytek.
Unfortunately my example relies what I believe is unsupported/undocumented behaviour in graphql-tools
. I've created an issue to hopefully add support for this (ardatan/graphql-tools#1279)
I'm going to close this here as this can be solved outside of this library like mentioned above: https://github.com/MichalLytek/type-graphql/blob/4501867fffe3e6f5b3e71af0b71651efcd48d9c3/examples/query-complexity/index.ts#L16-L64
If someone wants to create an npm package with an apollo server plugin, I'm happy to accept a PR with a link in the README.
Small refactor of @MichalLytek's file that made it into a plugin https://gist.github.com/reconbot/37ccd8b8fcdfb78ff6a16a7055edf103
And since you asked https://www.npmjs.com/package/graphql-query-complexity-apollo-plugin
First of all, I'm sorry to continue a closed question here
But I'm really in pain
I'm using Nest combined with Gql (Apollo) + complexity
But it seems that the document is not comprehensive, https://docs.nestjs.com/graphql/complexity
I looked up how graphql-query-complexity is used
I don't know how to get a schema and I'm not familiar with gql and how it works and I just want to use this feature, right
// Nest
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
cors: corsOptions,
path: gqlPath,
playground: !isPrd,
plugins: [{
// How to get a schema => https://github.com/MichalLytek/type-graphql/blob/4501867fffe3e6f5b3e71af0b71651efcd48d9c3/examples/query-complexity/index.ts#L30
}],
cache: 'bounded', // 解决生产报错 Persisted queries are enabled and are using an unbounded cache. Your server is vulnerable to denial of service attacks via memory exhaustion. Set `cache: "bounded"` or `persistedQueries: false` in your ApolloServer constructor, or see https://go.apollo.dev/s/cache-backends for other alternatives.
autoSchemaFile: path.resolve(__dirname, 'schema/index.gql'), // true 在内存中
context(ctx) {
return ctx;
},
}),
After much effort I finally found a working example:nestjs/graphql#373