Inspect and control upstream response headers in Nginx

Log selected upstream headers, hide or replace them deliberately, and account for response status, processing phase, and header inheritance.

Best practices
Illustration of server operations and log analysis

Use $upstream_http_* variables to inspect selected upstream response headers. Use proxy_hide_header to suppress a header on the client response, and add_header to append one. Appending is not the same as replacing an upstream value.

Record selected headers

Inside http, define a format and use its name in the applicable logging context:

log_format upstream_debug '$remote_addr "$uri" status=$status '
                          'up_content_type="$upstream_http_content_type" '
                          'up_cache_control="$upstream_http_cache_control" '
                          'up_time="$upstream_response_time"';
access_log /var/log/nginx/upstream.log upstream_debug;

Header names become lowercase variable suffixes with hyphens replaced by underscores: X-Request-Id becomes $upstream_http_x_request_id. These variables are not a full raw capture of every header from every retry; use dedicated tracing when that is the requirement.

Compare GET response headers without downloading the body to the terminal:

curl -sS -D - -o /dev/null https://example.com/path
curl -sS -D - -o /dev/null http://127.0.0.1:8080/path

Match Host, authentication, and other relevant request conditions when comparing. curl -I sends HEAD, which an application can handle differently.

Hide, allow, or replace a header

location / {
    proxy_pass http://127.0.0.1:8080;
    proxy_hide_header X-Powered-By;
    proxy_hide_header X-App-Version;
    add_header X-App-Version "public-v1" always;
}

The hide-plus-add pair replaces the downstream representation of X-App-Version. Using only add_header could produce duplicate fields.

Nginx normally suppresses certain upstream headers, including Date, Server, and X-Accel-*. proxy_pass_header permits a field otherwise hidden, for example proxy_pass_header Date; when deliberately needed. Hiding the upstream Server does not remove Nginx's own server-identification header.

Do not treat X-Accel-Redirect as an ordinary debug field. Nginx may process it as an internal redirect. proxy_pass_header controls forwarding; proxy_ignore_headers controls processing of supported special fields. Exposing internal redirect paths is usually unnecessary.

Check status and inheritance

Without always, add_header applies only to documented status codes, including 304. Add always when the header should also appear on error responses. Empty variable values are not a way to guarantee a visible header.

By the default inheritance rule, defining any add_header at a child level prevents inheriting the parent's set. Restate required headers there when using that model. Nginx 1.29.3 and later also support add_header_inherit, including merge; check your version before using it.

DataKit log collection can retain selected header fields for cache or version investigations. Avoid collecting tokens and session cookies merely to debug an unrelated header.

FAQ

Why does the client still see the old value?

Check the matched location, duplicate fields, successful reload, and browser/CDN caching. A 304 is not automatically excluded by add_header's default status list.

Does Nginx forward Set-Cookie?

Normally yes. Cookie rewriting uses directives such as proxy_cookie_domain and proxy_cookie_path; preserve multiple cookie fields correctly rather than folding them into one generic header.

Can an upstream header control a request-side decision?

Only after that header exists. A map can be evaluated lazily in a suitable response-phase use, but a rewrite-phase if cannot inspect a response that has not arrived. For cache storage, use response-aware controls such as proxy_no_cache as documented, rather than assuming any variable works in any phase.

References: proxy response-header controls, add_header and inheritance.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting