Opened 3 years ago
Last modified 3 years ago
#2477 new enhancement
proxy_redirect is missing feature for HTTP header "Link"
| Reported by: | Owned by: | ||
|---|---|---|---|
| Priority: | critical | Milestone: | |
| Component: | nginx-core | Version: | 1.18.x |
| Keywords: | Cc: | jochenwezel@… | |
| uname -a: | Linux revproxy02 5.15.0-69-generic #76-Ubuntu SMP Fri Mar 17 17:19:29 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux | ||
| nginx -V: |
nginx version: nginx/1.18.0 (Ubuntu)
built with OpenSSL 3.0.2 15 Mar 2022 TLS SNI support enabled configure arguments: --with-cc-opt='-g -O2 -ffile-prefix-map=/build/nginx-d8gVax/nginx-1.18.0=. -flto=auto -ffat-lto-objects -flto=auto -ffat-lto-objects -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -flto=auto -ffat-lto-objects -flto=auto -Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-compat --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --add-dynamic-module=/build/nginx-d8gVax/nginx-1.18.0/debian/modules/http-geoip2 --with-http_addition_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_sub_module |
||
Description (last modified by )
PLEASE NOTE: please ignore space chars in urls in following ticket (I had to "remove" all external links to be able to post this ticket, here: "Maximum number of external links per post exceeded")
Used configuration
Given is a reverse proxy configuration like
location / {
proxy_pass https :// upstream/;
proxy_redirect https :// upstream/ /;
}
As the documentation at https :// nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_redirect explains, proxy_redirect will change Location headers redirect. This is required and good and works.
HTTP Response of upstream server
My wordpress 6 system now starts to send HTTP responses like:
HTTP/1.1 200 OK Server: nginx/1.18.0 (Ubuntu) Date: Wed, 29 Mar 2023 15:31:02 GMT Content-Type: text/html; charset=UTF-8 Transfer-Encoding: chunked Connection: keep-alive Link: <https :// upstream/index.php/wp-json/>; rel="https://api.w.org/" Link: <https :// upstream/index.php/wp-json/wp/v2/pages/69>; rel="alternate"; type="application/json" Link: <https :// upstream/>; rel=shortlink Vary: Accept-Encoding Content-Encoding: gzip
HTTP protocol standard
Since I've never seen this type of 'link' header before, this was a real surprise to me. But it seems that it's a feature which exists for many years, now: https :// www.w3.org/wiki/LinkHeader
Problem description
The problem is, that the many Link headers remain unchanged and are delivered (as they are) to the client. Of course, the client machine doesn't know anything about my upstream server and can't access it to load these linked urls.
The result is, that my nginx reverse proxy response to the client contains unchanged Link headers
Link: <https :// upstream/index.php/wp-json/>; rel="https://api.w.org/" Link: <https :// upstream/index.php/wp-json/wp/v2/pages/69>; rel="alternate"; type="application/json" Link: <https :// upstream/>; rel=shortlink
Feature request
So, proxy_redirect should (by default) substitute in headers
LocationLink[array]
Optionally, the substitution of Link headers could be configured with another switch (e.g. proxy_redirect_links) to on|off|default
Change History (5)
comment:1 by , 3 years ago
| Description: | modified (diff) |
|---|
comment:2 by , 3 years ago
| Description: | modified (diff) |
|---|
comment:3 by , 3 years ago
| Description: | modified (diff) |
|---|
comment:4 by , 3 years ago
| Description: | modified (diff) |
|---|

Note that there are a lot of ways how backend servers can sent various links to the client, including response headers and the response body. In general it is not possible to change all the links, and nginx only tries to support the most common use cases - such as the
Locationheader (proxy_redirect) andSet-Cookieheaders (proxy_cookie_domain, proxy_cookie_path, proxy_cookie_flags). Instead of using nginx to rewrite links, a better approach is to configure your backend server to send the correct links.If configuring your backend server to return correct links is not an option, an immediately available solution for the
Linkheader might be to use the proxy_hide_header directive to hide such incorrect links.Alternatively, headers can be removed with
proxy_hide_headerand re-added with modifications by something like this (assuming up to 3 Link headers):map $upstream_http_link $rewritten1_link { ~^(.*)https://upstream/(.*)$ $1https://example.org/$2; default $upstream_http_link; } map $rewritten1_link $rewritten2_link { ~^(.*)https://upstream/(.*)$ $1https://example.org/$2; default $rewritten1_link; } map $rewritten2_link $rewritten_link { ~^(.*)https://upstream/(.*)$ $1https://example.org/$2; default $rewritten2_link; } proxy_hide_header Link; add_header Link $rewritten_link;Note that this requires at least nginx 1.23.0 to properly handle multiple
Linkheaders.Having said that, it might still make sense to support easy rewriting of the
Linkheaders, so keeping this feature request open for now.