Limiting/disabling batching in apollo-server

Hi! I want to disable query batching to prevent possible DoS attacks on my GQL server running on apollo-server-express.

I already use complexity analysis but it seems that it works per query not per batch (as well as other validations) and I did not find any public API for limiting batch queries.

Is there any way to implement batch query limiting or disable it at all?

1 Like

There isn’t currently a way to disable or limit (e.g., max batch count) this batching functionality. That sounds like a very reasonable feature request for apollo-server!

Feel free to include a suggested design as it could be good conversation that might unblock the ability for someone (even you!) to make a pull-request for it!

Thanks for mentioning this!

2 Likes

I confess I am an Express newbie, but you might be able to achieve what you’re looking for by:

  1. Swapping from apollo-server to apollo-server-express (Edit: I failed to see that you’re already using apollo-server-express! You can skip this :grinning_face_with_smiling_eyes:)
  2. Configuring custom middleware for your server’s GraphQL endpoint path (such as /graphql):
var batchOperationChecker = function (req, res, next) {
  // Check if we have a batch of two or more operations
  if (Array.isArray(req.body) && req.body.length > 1) {
    res.status(400).send({
      errors: [{
        message: "Batched operations not allowed!"
      }]
    });
  } else {
    next();
  }
}
app.use(express.json());
app.use('/graphql', batchOperationChecker);

The logic above is coarse and flat-out rejects any batch. You could tweak this to check for a certain threshold of operation count or a level of operation complexity. You probably also want to check for a batch in a more reliable way than just checking for an array as the request body, but I’m not positive at the moment of all the hallmarks of a batched operation request.

Also, make sure to call app.use for this custom middleware before you call server.applyMiddleware.

1 Like

You can definitely do it at the layer before Apollo Server as @StephenBarlow creatively and thoughtfully took the time to exemplify above!

A native implementation could extend this to work for all integrations, but this is a great work around and will work even if we do implement it natively! (And it’s also a great example of how to do many circuit-breaker -like activities before Apollo Server even touches the request!)

Found this thread during my feature request process- relevant feature request here.