Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

README.md

Async timeout

The graphql.servlet.async.timeout property enables you to define a request level timeout to be enforced. This can help in preventing DDoS attacks. This is only available when running the application in servlet mode. The value is the timeout in milliseconds that should be enforced. If the GraphQL request has not finished within that timeout a GraphQL error will be returned:

{
  "errors": [
    {
      "message": "Execution canceled because timeout of 500 millis was reached",
      "locations": []
    }
  ],
  "data": null
}

It will also write a log message to clarify which query was being executed when the timeout occurs:

2021-05-14 09:19:53.314  WARN 359165 --- [nio-9000-exec-3] g.k.servlet.HttpRequestInvokerImpl       : GraphQL execution canceled because timeout of 500 millis was reached. The following query was being executed when this happened:
query {
  hello
}

In this example the timeout has been configured at 500 milliseconds in application.yml.

graphql.servlet.async.timeout: 500

GraphQL execution cancellation

The Query class shows two examples of queries that will take 3000 milliseconds to finish, which is longer than the timeout.

When you run this application you can open GraphiQL at http://localhost:9000/graphiql. You can then run either:

query {
    hello
}

or

query {
    world
}

Either one will stop processing after 500ms because of the configured timeout.

The main difference between the two methods in the Query class however is the ability to also cancel the execution of the GraphQL request. Ideally the GraphQL execution is cancelled as well, because otherwise that request is still taking up resources and Thread(s) even though the HTTP request has stopped. An attacker could repeatedly call that particular GraphQL query which now returns fast, and that would spawn a new Thread with long running execution within the application itself. That could ultimately lead to an application that crashes because it runs out of memory for example.

To make the GraphQL requests themselves cancellable you only have to remember to always return a CompletableFuture instead of the value directly. The Query.getHello() method is a simple example of a cancellable GraphQL request. While Query.getWorld() just returns the String value after a certain amount of time and cannot be canceled. In that case when the GraphQL request finally finishes it will log a warning:

Cannot write GraphQL response, because the HTTP response is already committed. It most likely timed out.