Skip to content

Commit b952d5d

Browse files
committed
--rewrite-host-header flag
1 parent a182f7d commit b952d5d

File tree

5 files changed

+62
-11
lines changed

5 files changed

+62
-11
lines changed

README.md

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,7 +1075,7 @@ following `Nginx` config:
10751075

10761076
```console
10771077
location /get {
1078-
proxy_pass http://httpbin.org/get
1078+
proxy_pass http://httpbin.org/get;
10791079
}
10801080
```
10811081

@@ -1094,6 +1094,36 @@ Verify using `curl -v localhost:8899/get`:
10941094
}
10951095
```
10961096

1097+
#### Rewrite Host Header
1098+
1099+
With above example, you may sometimes see:
1100+
1101+
```console
1102+
>
1103+
* Empty reply from server
1104+
* Closing connection
1105+
curl: (52) Empty reply from server
1106+
```
1107+
1108+
This is happenening because our default reverse proxy plugin `ReverseProxyPlugin` is configured
1109+
with a `http` and a `https` upstream server. And, by default `ReverseProxyPlugin` preserves the
1110+
original host header. While this works with `https` upstreams, this doesn't work reliably with
1111+
`http` upstreams. To work around this problem use the `--rewrite-host-header` flags.
1112+
1113+
Example:
1114+
1115+
1116+
```console
1117+
proxy --enable-reverse-proxy \
1118+
--plugins proxy.plugin.ReverseProxyPlugin \
1119+
--rewrite-host-header
1120+
```
1121+
1122+
This will ensure that `Host` header field is set as `httpbin.org` and works with both `http` and
1123+
`https` upstreams.
1124+
1125+
> NOTE: Whether to use `--rewrite-host-header` or not depends upon your use-case.
1126+
10971127
## Plugin Ordering
10981128

10991129
When using multiple plugins, depending upon plugin functionality,
@@ -2613,7 +2643,7 @@ usage: -m [-h] [--tunnel-hostname TUNNEL_HOSTNAME] [--tunnel-port TUNNEL_PORT]
26132643
[--proxy-pool PROXY_POOL] [--enable-web-server]
26142644
[--enable-static-server] [--static-server-dir STATIC_SERVER_DIR]
26152645
[--min-compression-length MIN_COMPRESSION_LENGTH]
2616-
[--enable-reverse-proxy] [--enable-metrics]
2646+
[--enable-reverse-proxy] [--rewrite-host-header] [--enable-metrics]
26172647
[--metrics-path METRICS_PATH] [--pac-file PAC_FILE]
26182648
[--pac-file-url-path PAC_FILE_URL_PATH]
26192649
[--cloudflare-dns-mode CLOUDFLARE_DNS_MODE]
@@ -2622,7 +2652,7 @@ usage: -m [-h] [--tunnel-hostname TUNNEL_HOSTNAME] [--tunnel-port TUNNEL_PORT]
26222652
[--filtered-client-ips FILTERED_CLIENT_IPS]
26232653
[--filtered-url-regex-config FILTERED_URL_REGEX_CONFIG]
26242654

2625-
proxy.py v2.4.6.dev25+g2754b928.d20240812
2655+
proxy.py v2.4.8.dev8+gc703edac.d20241013
26262656

26272657
options:
26282658
-h, --help show this help message and exit
@@ -2791,6 +2821,9 @@ options:
27912821
response that will be compressed (gzipped).
27922822
--enable-reverse-proxy
27932823
Default: False. Whether to enable reverse proxy core.
2824+
--rewrite-host-header
2825+
Default: False. If used, reverse proxy server will
2826+
rewrite Host header field before sending to upstream.
27942827
--enable-metrics Default: False. Enables metrics.
27952828
--metrics-path METRICS_PATH
27962829
Default: /metrics. Web server path to serve proxy.py

proxy/common/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ def _env_threadless_compliant() -> bool:
165165
if sys.version_info >= (3, 10)
166166
else (ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1)
167167
)
168+
DEFAULT_ENABLE_REWRITE_HOST = False
168169

169170
DEFAULT_DEVTOOLS_DOC_URL = 'http://proxy'
170171
DEFAULT_DEVTOOLS_FRAME_ID = secrets.token_hex(8)

proxy/common/utils.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
from types import TracebackType
2626
from typing import Any, Dict, List, Type, Tuple, Callable, Optional
2727

28-
import _ssl # noqa: WPS436
28+
# noqa: WPS436
29+
import _ssl # type: ignore[import-not-found]
2930

3031
from .types import HostPort
3132
from .constants import (
@@ -322,6 +323,7 @@ def set_open_file_limit(soft_limit: int) -> None:
322323
if IS_WINDOWS: # pragma: no cover
323324
return
324325

326+
# pylint: disable=possibly-used-before-assignment
325327
curr_soft_limit, curr_hard_limit = resource.getrlimit(
326328
resource.RLIMIT_NOFILE,
327329
)

proxy/http/server/reverse.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,15 @@ def handle_request(self, request: HttpParser) -> None:
128128
self.upstream.queue(
129129
memoryview(
130130
request.build(
131-
host=self.choice.hostname
132-
+ (
133-
COLON + bytes_(self.choice.port)
134-
if self.choice.port is not None
135-
else b''
131+
host=(
132+
self.choice.hostname
133+
+ (
134+
COLON + bytes_(self.choice.port)
135+
if self.choice.port is not None
136+
else b''
137+
)
138+
if self.flags.rewrite_host_header
139+
else None
136140
),
137141
),
138142
),

proxy/http/server/web.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@
2929
from ...common.utils import text_, build_websocket_handshake_response
3030
from ...common.constants import (
3131
DEFAULT_ENABLE_WEB_SERVER, DEFAULT_STATIC_SERVER_DIR,
32-
DEFAULT_ENABLE_REVERSE_PROXY, DEFAULT_ENABLE_STATIC_SERVER,
33-
DEFAULT_WEB_ACCESS_LOG_FORMAT, DEFAULT_MIN_COMPRESSION_LENGTH,
32+
DEFAULT_ENABLE_REWRITE_HOST, DEFAULT_ENABLE_REVERSE_PROXY,
33+
DEFAULT_ENABLE_STATIC_SERVER, DEFAULT_WEB_ACCESS_LOG_FORMAT,
34+
DEFAULT_MIN_COMPRESSION_LENGTH,
3435
)
3536

3637

@@ -78,6 +79,16 @@
7879
help='Default: False. Whether to enable reverse proxy core.',
7980
)
8081

82+
flags.add_argument(
83+
'--rewrite-host-header',
84+
action='store_true',
85+
default=DEFAULT_ENABLE_REWRITE_HOST,
86+
help='Default: '
87+
+ str(DEFAULT_ENABLE_REWRITE_HOST)
88+
+ '. '
89+
+ 'If used, reverse proxy server will rewrite Host header field before sending to upstream.',
90+
)
91+
8192

8293
class HttpWebServerPlugin(HttpProtocolHandlerPlugin):
8394
"""HttpProtocolHandler plugin which handles incoming requests to local web server."""

0 commit comments

Comments
 (0)