nginx changes HEAD requests into GET requests
🔥 Problem
In gitlab#381504 (comment 1297755108), we found out that the nginx http
config file template has a location
block for ^/api/v\d
.
The issue is that this configuration will change HEAD
requests into GET
requests:
sequenceDiagram
outside->>nginx: HEAD /api/v4/<whatever>
nginx->>workhorse: GET /api/v4/<whatever>
workhorse->>rails: GET /api/v4/<whatever>
rails->>workhorse: response
workhorse->>nginx: response
nginx->>outside: response
Some API endpoints return files that are located in object storage.
Now, the file itself is not returned. That would be too heavy. Instead, rails will return a redirect to a signed url pointing to the file in object storage.
When using AWS S3 as the object storage provider, the signed url is strictly for the http verb that is passed as a parameter. This means that if we generate a signed url for GET
, outside clients can't HEAD
that url (only GET
).
The Maven package registry for example has some clients known to use HEAD
request to quickly check if a given file is already cached locally ($ gradle
).
If nginx switches the request to GET
, rails will generate a signed url for GET
and when those clients will try to HEAD
that url, well,
Again, this only happens using the AWS S3 as the object storage backend.
🚒 Solution
From our trials in gitlab#381504 (comment 1297755108), it seems that proxy_cache_convert_head off;
will stop nginx from converting HEAD
into GET
requests.