graphqlite-bundle icon indicating copy to clipboard operation
graphqlite-bundle copied to clipboard

Support handling for HEAD/OPTIONS request method

Open andrew-demb opened this issue 11 months ago • 4 comments

Context: our server sometimes received HEAD requests from some users to /graphql and this request leads to 500 status code due to the error GraphQL\Server\Exception\CannotParseJsonBody in \GraphQL\Server\Helper::parsePsrRequest.

For now, the bundle adds a route /graphql with no limiting the request methods that it can handle.

In answer to the similar request in webonyx/graphql-php - maintainers mentioned, that it is recommended to handle OPTIONS requests on consumer side (before calling \GraphQL\Server\StandardServer::executePsrRequest)

Example request log:

method	 HEAD
protocol	HTTP/1.1
response_code	500
response_code_details	via_upstream
time	2025-02-07T10:51:09.555612977Z
user_agent	Mozilla/5.0 (Linux; U; Android 10; en-us; motorola one Build/JOP24G) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/86.0.4240.198 Mobile Safari/537.36
x_envoy_origin_path	/graphql

My proposition: return 200 status code with no body when request method is HEAD in \TheCodingMachine\GraphQLite\Bundle\Controller\GraphQLiteController::handlePsr7Request.

Refs:

  • https://github.com/webonyx/graphql-php/issues/198#issuecomment-345143284

andrew-demb avatar Feb 07 '25 12:02 andrew-demb

As an alternative don't handle such request method and return 405 (or change route to avoid handling anything except GET and POST in next major version)

andrew-demb avatar Feb 07 '25 12:02 andrew-demb

@andrew-demb in the same listener as mentioned here, we've also hardcoded a 200 response code for all responses from /graphql.

Additionally, we've configured CORS to only allow GET, OPTIONS, and POST methods on /graphql. This setup prevents HEAD requests from our own clients, although I'll need to test how it behaves if a client sends a HEAD request directly.

Lappihuan avatar Feb 09 '25 23:02 Lappihuan

@Lappihuan Our frontend hosted on the same domain, as an API.

So specifying in CORS headers allowed methods won't work for us.

To answer about "force 200 always" - I know that specification of GraphQL over HTTP enforces using 200 status code, if server successfully parsed request, but I dont think it is OK to return 200 by default for all cases

andrew-demb avatar Feb 10 '25 14:02 andrew-demb

MDN says for HEAD :

The HEAD HTTP method requests the metadata of a resource in the form of headers that the server would have sent if the GET method was used instead.

So IMO, if GET is allowed for /graphql, a 200 should be returned instead of a 405. In a perfect world, it should be handled exactly like a GET request (which means, parsing & executing the queries) without returning a body (but content-length).

About OPTIONS, it should return a 204 No Content (so without body) as the purpose is to get headers (including allowed methods).

cvergne avatar Feb 26 '25 10:02 cvergne

This issue is stale because it has been open 6 months with no activity. Remove stale label or comment or this will be closed in 5 days.

github-actions[bot] avatar Aug 26 '25 02:08 github-actions[bot]

This issue was closed because it has been stalled for 5 days with no activity.

github-actions[bot] avatar Aug 31 '25 02:08 github-actions[bot]