From 91652aac48c60b4053d54c051b8a88b1ea2720f0 Mon Sep 17 00:00:00 2001 From: Gilles Filippini Date: Tue, 14 May 2024 22:30:06 +0200 Subject: [PATCH] fix: constistent behavior for `HTTPS_METHOD=nohttp` Without this fix the response of nohttp sites to HTTP requests changes depending on the existence of at least one HTTP enabled site: * no HTTP enabled sites -> connection refused * at least one HTTP enabled site -> 503 This fix ensures the response is always 503. --- nginx.tmpl | 3 +-- test/test_fallback.py | 12 +++++------- test/test_ssl/test_nohttp.py | 8 ++++---- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/nginx.tmpl b/nginx.tmpl index b50997c..72181d4 100644 --- a/nginx.tmpl +++ b/nginx.tmpl @@ -650,7 +650,7 @@ proxy_set_header Proxy ""; {{- $default_https_exists = or $default_https_exists (and $https $vhost.default) }} {{- $http3_enabled = or $http3_enabled $vhost.http3_enabled }} {{- end }} - {{- $fallback_http := and $http_exists (not $default_http_exists) }} + {{- $fallback_http := not $default_http_exists }} {{- $fallback_https := and $https_exists (not $default_https_exists) }} {{- /* * If there are no vhosts at all, create fallbacks for both plain http @@ -658,7 +658,6 @@ proxy_set_header Proxy ""; * refused error. */}} {{- if and (not $http_exists) (not $https_exists) }} - {{- $fallback_http = true }} {{- $fallback_https = true }} {{- end }} {{- if or $fallback_http $fallback_https }} diff --git a/test/test_fallback.py b/test/test_fallback.py index 1ee923a..16da3d7 100644 --- a/test/test_fallback.py +++ b/test/test_fallback.py @@ -60,19 +60,17 @@ CONNECTION_REFUSED_RE = re.compile("Connection refused") ("nodefault.yml", "http://unknown.nginx-proxy.test/", 503, None), ("nodefault.yml", "https://unknown.nginx-proxy.test/", None, INTERNAL_ERR_RE), # HTTPS_METHOD=nohttp on nginx-proxy, HTTPS_METHOD unset on the app container. - ("nohttp.yml", "http://https-only.nginx-proxy.test/", None, CONNECTION_REFUSED_RE), + ("nohttp.yml", "http://https-only.nginx-proxy.test/", 503, None), ("nohttp.yml", "https://https-only.nginx-proxy.test/", 200, None), - ("nohttp.yml", "http://unknown.nginx-proxy.test/", None, CONNECTION_REFUSED_RE), + ("nohttp.yml", "http://unknown.nginx-proxy.test/", 503, None), ("nohttp.yml", "https://unknown.nginx-proxy.test/", 503, None), # HTTPS_METHOD=redirect on nginx-proxy, HTTPS_METHOD=nohttp on the app container. - ("nohttp-on-app.yml", "http://https-only.nginx-proxy.test/", None, CONNECTION_REFUSED_RE), + ("nohttp-on-app.yml", "http://https-only.nginx-proxy.test/", 503, None), ("nohttp-on-app.yml", "https://https-only.nginx-proxy.test/", 200, None), - ("nohttp-on-app.yml", "http://unknown.nginx-proxy.test/", None, CONNECTION_REFUSED_RE), + ("nohttp-on-app.yml", "http://unknown.nginx-proxy.test/", 503, None), ("nohttp-on-app.yml", "https://unknown.nginx-proxy.test/", 503, None), # Same as nohttp.yml, except there is a vhost with a missing cert. This causes its - # HTTPS_METHOD=nohttp setting to effectively become HTTPS_METHOD=noredirect. This means that - # there will be a plain http server solely to support that vhost, so http requests to other - # vhosts get a 503, not a connection refused error. + # HTTPS_METHOD=nohttp setting to effectively become HTTPS_METHOD=noredirect. ("nohttp-with-missing-cert.yml", "http://https-only.nginx-proxy.test/", 503, None), ("nohttp-with-missing-cert.yml", "https://https-only.nginx-proxy.test/", 200, None), ("nohttp-with-missing-cert.yml", "http://missing-cert.nginx-proxy.test/", 200, None), diff --git a/test/test_ssl/test_nohttp.py b/test/test_ssl/test_nohttp.py index aecbb54..032f60f 100644 --- a/test/test_ssl/test_nohttp.py +++ b/test/test_ssl/test_nohttp.py @@ -3,15 +3,15 @@ import requests def test_web2_http_is_connection_refused(docker_compose, nginxproxy): - with pytest.raises(requests.exceptions.RequestException, match="Connection refused"): - nginxproxy.get("http://web2.nginx-proxy.tld/") + r = nginxproxy.get("http://web2.nginx-proxy.tld/", allow_redirects=False) + assert r.status_code == 503 def test_web2_http_is_connection_refused_for_acme_challenge( docker_compose, nginxproxy, acme_challenge_path ): - with pytest.raises(requests.exceptions.RequestException, match="Connection refused"): - nginxproxy.get(f"http://web2.nginx-proxy.tld/{acme_challenge_path}") + r = nginxproxy.get(f"http://web2.nginx-proxy.tld/{acme_challenge_path}", allow_redirects=False) + assert r.status_code == 503 def test_web2_https_is_forwarded(docker_compose, nginxproxy):