Skip to content

NGINX : How to capture headers and use them in subsequent responses

  • How to capture headers returned by the proxied upstream server in NGINX ?
  • How to intercept redirects and follow location while hiding the upstream URL in NGINX ?
  • How to add headers to the HTTP response in NGINX ?

Official documentation

This article is based on the official documentation and the following modules:

Cheat sheet

Requests

  • proxy_set_header : Sets headers in Proxied HTTP Request
  • proxy_hide_header : Removes headers in Proxied HTTP Request
  • $http_< header_in_snake_case > : Header value from a HTTP Request

Responses

  • add_header : Sets headers in HTTP Response
  • $upstream_http_< header_in_snake_case > : Header value from a Proxied HTTP Response

A quick overview of the request/response flow

Given the following diagram, we defined 2 zones :

  • The frontend zone : This is where NGINX receives requests from clients
  • The proxied zone : This is where NGINX acts as a HTTP client towards the upstream app server

The mapping between NGINX directives and this diagram are the following :

  • When a client performs a HTTP request, a specific Location is matched.
  • proxy_pass performs both sending and receiving data from the upstream server. It manages both arrows (Proxied HTTP Request and Proxied HTTP Response)

Capturing headers returned by the proxied upstream server

NGINX performs some kind of dynamic variable definition based on the HTTP headers. This allows us to get headers from the upstream server (in Proxied HTTP Response in the diagram) with the following : $upstream_http_< name_of_the_header_in_snake_case >

Example : Proxying a S3 bucket from a third party cloud provider

How to Intercepting redirects, following location while hiding the upstream URL

nginx
location / {
    #: Disable buffering, so we are only hiding the upstream URL
    proxy_buffering off;

    proxy_set_header Host $host;
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-Proto https;
    proxy_pass http://upstream_app_server;

    proxy_intercept_errors on;
    error_page 302 = @proxy_redirects_302;
}

location @proxy_redirects_302 {
    #: The following line performs exactly what we want : capturing the header
    #: from the `Proxied HTTP Response`
    set $saved_redirect_location '$upstream_http_location';
    
    #: We need this line in order to resolve URLs provided by the upstream server
    resolver 8.8.8.8;
    
    #: We are connecting to a dynamic upstream location
    proxy_pass $saved_redirect_location;
}

The updated diagram is then :

Adding back headers

Let's say you want to add headers, such as Content-Disposition to trigger a download from the browser. Adding headers is done with the add_header directive and influences the HTTP Response :

nginx
location @proxy_redirects_302 {
    #: The following line performs exactly what we want : capturing the header
    #: from the `Proxied HTTP Response`
    set $saved_redirect_location '$upstream_http_location';

    #: Capture `Content-Disposition` header from upstream to add it back to the final response
    set $saved_content_disposition '$upstream_http_content_disposition';
    
    #: We need this line in order to resolve URLs provided by the upstream server
    resolver 8.8.8.8;
    
    #: We are connecting to a dynamic upstream location
    proxy_pass $saved_redirect_location;

    #: Adding header to `HTTP Response`
    add_header Content-Disposition $saved_content_disposition;
}

Discover more content ?

Do you want to learn more and faster with dense and tailored technical resources ?

Advanced Stack