How to Convert HEAD to GET Requests in NGINX for Backend Compatibility


2 views

Many legacy applications weren't designed with proper HEAD request support, returning "405 Method Not Allowed" errors. While the HTTP spec states that HEAD responses should match GET responses (without the body), some frameworks don't implement this correctly.

We can leverage NGINX's rewrite capabilities to transform HEAD requests into GET requests before they reach our backend:

location / {
    if ($request_method = HEAD) {
        set $request_method GET;
        proxy_pass http://ourupstream;
        proxy_set_header X-Original-Method HEAD;
        proxy_ignore_client_abort on;
    }
    
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://ourupstream;
}

To properly return only headers for HEAD requests:

map $upstream_http_content_length $content_length {
    default $upstream_http_content_length;
    ""      "";
}

server {
    # ... existing config ...
    
    location / {
        if ($request_method = HEAD) {
            set $request_method GET;
            proxy_pass http://ourupstream;
            proxy_set_header X-Original-Method HEAD;
            proxy_ignore_client_abort on;
        }
        
        proxy_hide_header 'Content-Length';
        add_header 'Content-Length' $content_length;
        proxy_pass http://ourupstream;
    }
}

For more complex scenarios with caching:

proxy_cache_key "$scheme$request_method$host$request_uri";
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;

location / {
    if ($request_method = HEAD) {
        set $request_method GET;
        proxy_cache_key "$scheme$host$request_uri";
        proxy_pass http://ourupstream;
    }
    
    proxy_pass http://ourupstream;
}

Verify with curl:

curl -I http://yourdomain.com/path
curl -X HEAD http://yourdomain.com/path

Both commands should return identical headers without errors.


Many legacy applications struggle with proper HTTP HEAD request handling, often returning "405 Method Not Allowed" errors. This becomes particularly problematic when:

  • Using monitoring tools that rely on HEAD requests
  • Implementing REST APIs that should support HEAD
  • Enabling CDN health checks

Instead of modifying the backend application, we can leverage NGINX's proxy capabilities to transparently convert HEAD to GET requests:

server {
    listen 80;
    server_name example.com;

    location / {
        if ($request_method = HEAD) {
            set $request_method GET;
            proxy_pass http://backend;
            proxy_ignore_client_abort on;
            proxy_set_header X-Original-Method HEAD;
        }
        
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

For production environments, consider these enhancements:

map $request_method $transformed_method {
    HEAD    GET;
    default $request_method;
}

server {
    ...
    
    location / {
        proxy_method $transformed_method;
        proxy_pass http://backend;
        
        # Discard body for HEAD requests
        proxy_set_header Accept-Encoding "";
        proxy_buffering on;
        proxy_cache_valid 200 1s;
        
        # Preserve original method in header
        proxy_set_header X-Original-Method $request_method;
    }
}

Verify with curl:

curl -I http://yourserver.com/resource
curl -X HEAD http://yourserver.com/resource

Check logs for the X-Original-Method header to confirm the transformation worked.

  • Enable proxy_buffering to discard response bodies efficiently
  • Consider adding proxy_cache for HEAD requests to reduce backend load
  • Monitor upstream traffic to verify the solution works as intended