Skip to content
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

How to use it with Apollo Server? #7

Closed
FluorescentHallucinogen opened this issue Jul 7, 2018 · 13 comments
Closed

How to use it with Apollo Server? #7

FluorescentHallucinogen opened this issue Jul 7, 2018 · 13 comments

Comments

@FluorescentHallucinogen
Copy link

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?

@ivome
Copy link
Collaborator

ivome commented Jul 7, 2018

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.

@MichalLytek
Copy link
Contributor

@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?

@ivome
Copy link
Collaborator

ivome commented Oct 5, 2018

@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:

  1. 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.
  2. 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?

@MichalLytek
Copy link
Contributor

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 😉

@ivome
Copy link
Collaborator

ivome commented May 18, 2019

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

@EvgeniyZo
Copy link

EvgeniyZo commented Jun 17, 2019

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)"]}}}]}

@MichalLytek
Copy link
Contributor

@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

@mattdean-digicatapult
Copy link

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)

@ivome
Copy link
Collaborator

ivome commented Nov 20, 2020

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.

@ivome ivome closed this as completed Nov 20, 2020
@reconbot
Copy link

Small refactor of @MichalLytek's file that made it into a plugin https://gist.github.com/reconbot/37ccd8b8fcdfb78ff6a16a7055edf103

@reconbot
Copy link

And since you asked https://www.npmjs.com/package/graphql-query-complexity-apollo-plugin

@zq0904
Copy link

zq0904 commented Apr 12, 2023

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;
      },
    }),

@zq0904
Copy link

zq0904 commented Apr 12, 2023

After much effort I finally found a working example:nestjs/graphql#373

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants