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

Access to query variables in validationRules #1777

Closed
MichalLytek opened this issue Oct 7, 2018 · 14 comments
Closed

Access to query variables in validationRules #1777

MichalLytek opened this issue Oct 7, 2018 · 14 comments
Labels
⛲️ feature New addition or enhancement to existing solutions

Comments

@MichalLytek
Copy link

My feature request is partially related to #1627. Generally, I want to integrate with a graphql-query-complexity library that creates validationRules but it need access to the query variables values and they're not present in ValidationContext in graphql-js. Here's how it's configured using plain express-graphql middleware:

import queryComplexity from 'graphql-query-complexity';
import express from 'express';
import graphqlHTTP from 'express-graphql';
import schema from './schema';

const app = express();
app.use('/api', graphqlHTTP(async (request, response, {variables}) => ({
  schema,
  validationRules: [ queryComplexity({
    maximumComplexity: 1000,
    variables,
    onComplete: (complexity: number) => {console.log('Query Complexity:', complexity);},
  }) ]
})));

In graphql-yoga there is a callback, like in apollo-server for context:
https://github.com/prisma/graphql-yoga/blob/3362b13374190fd2390594495dc08064e5ee4815/src/types.ts#L64-L77

And I think that apollo-server should support this kind of configuration too 😉 Changing ValidationContext mechanism in graphql-js is much more complicated and the only way that the author has figured out is by making validationRules dynamic in Apollo Server:
slicknode/graphql-query-complexity#7 (comment)

@ghost ghost added the ⛲️ feature New addition or enhancement to existing solutions label Oct 7, 2018
@MichalLytek MichalLytek changed the title Access to query variables in validation Access to query variables in validationRules Oct 7, 2018
@martinhyldgaard
Copy link

It would be great if the variables could be accessible as a callback.
I had some luck using the "old way" of accessing request headers (https://www.apollographql.com/docs/apollo-server/migration-two-dot.html#request-headers), then passing variables: req.body.variables to queryComplexity. However it fell short on batched queries.

@martijnwalraven
Copy link
Contributor

Closing this because validationRules shouldn't have access to query variables, because validation isn't related to any particular operation and isn't guaranteed to run on every request (as an optimization, validation only happens once per operation and is skipped on subsequent requests).

@MichalLytek
Copy link
Author

@martijnwalraven so what do you propose instead or complexity calculation for preventing DDoS of GraphQL API?

@martijnwalraven
Copy link
Contributor

@19majkel94 Complexity calculation is a fine solution, but using the didResolveOperation hook from the request pipeline plugin API would be a better place for this because it gets called for every request and has access both to the specific operation that gets executed and the query variables.

@MichalLytek
Copy link
Author

@martijnwalraven
Thanks for the tip! Looks like it works like a charm 😄

But is there a better way to receive a operation DocumentNode rather than:

import { parse } from "graphql";
// ...
didResolveOperation({ request, operation }) {
  const operationString = request.query!.substring(
    operation.loc!.start,
    operation.loc!.end,
  );
  const query = parse(operationString);
},

@martijnwalraven
Copy link
Contributor

@19majkel94 Good to hear! Yep, you should have access to document. Note that a document may contain multiple operations however, so you may also want to take operation or operationName into account.

@martijnwalraven
Copy link
Contributor

Oh, and your current code wouldn't work with fragments, because those are not part of operation.

@MichalLytek
Copy link
Author

I can't use just document because it may contains not executed operations and thus overcalculating complexity.

So how to proper cut document into operation with fragments as DocumentNode?

@martijnwalraven
Copy link
Contributor

You should be able to use separateOperations from graphql-js for that.

@MichalLytek
Copy link
Author

Great! Thanks! 😃
I was looking under extractOperations key 😄

So here is the (I hope) final version:

const query = request.operationName
  ? separateOperations(document)[request.operationName]
  : document;

@martijnwalraven
Copy link
Contributor

That looks great!

@MichalLytek
Copy link
Author

Here is a working example of graphql-query-complexity integration with Apollo Server 💪
https://github.com/19majkel94/type-graphql/blob/4501867fffe3e6f5b3e71af0b71651efcd48d9c3/examples/query-complexity/index.ts#L16-L64

@rex-remind101
Copy link

#1777 (comment)

Closing this because validationRules shouldn't have access to query variables, because validation isn't related to any particular operation and isn't guaranteed to run on every request (as an optimization, validation only happens once per operation and is skipped on subsequent requests).

this consumed a significant amount of our time because we assumed it ran on every request, from some clients we permit certain queries and in others we do not. could the documentation be updated to include that please https://www.apollographql.com/docs/apollo-server/api/apollo-server/#validationrules ?

@glasser
Copy link
Member

glasser commented Feb 24, 2021

@rex-remind101 I'm sorry you were confused by our docs here! Yeah, the purpose of validation rules is to be a pure function of "operation + schema" so it doesn't work with other things. Those docs can be found at docs/source/api/apollo-server.md. I bet you have a better idea of what would have been clear to you than I would, so want to give a PR a try?

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 20, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
⛲️ feature New addition or enhancement to existing solutions
Projects
None yet
Development

No branches or pull requests

5 participants