From 5fb4b49a910642053ed390171d8d853196d6376b Mon Sep 17 00:00:00 2001 From: benoitc Date: Fri, 27 Dec 2013 17:15:46 +0100 Subject: [PATCH] dont' override SERVER_* by the Host header Gunicorn shouln't override the SERVER_* by the Host header. The client will take care about it during the URL reconstruction if needed. Since the spec don't support unix sockets, Gunicorn is using the HOST heeader when available to create viable SERVER_* if possible so the application and framworks will be happy. When the Host Header is not available (SocketPath, '') is returned. fix #628 --- gunicorn/http/wsgi.py | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/gunicorn/http/wsgi.py b/gunicorn/http/wsgi.py index 12ac8e70..becbac89 100644 --- a/gunicorn/http/wsgi.py +++ b/gunicorn/http/wsgi.py @@ -78,17 +78,22 @@ def proxy_environ(req): def create(req, sock, client, server, cfg): resp = Response(req, sock, cfg) + # set initial environ environ = default_environ(req, sock, cfg) + # default variables + host = None url_scheme = "https" if cfg.is_ssl else "http" script_name = os.environ.get("SCRIPT_NAME", "") + # set secure_headers secure_headers = cfg.secure_scheme_headers if client and not isinstance(client, string_types): if ('*' not in cfg.forwarded_allow_ips and client[0] not in cfg.forwarded_allow_ips): secure_headers = {} + # add the headers tot the environ for hdr_name, hdr_value in req.headers: if hdr_name == "EXPECT": # handle expect @@ -97,8 +102,8 @@ def create(req, sock, client, server, cfg): elif secure_headers and (hdr_name in secure_headers and hdr_value == secure_headers[hdr_name]): url_scheme = "https" - elif hdr_name == "HOST": - server = hdr_value + elif hdr_name == 'HOST': + host = hdr_value elif hdr_name == "SCRIPT_NAME": script_name = hdr_value elif hdr_name == "CONTENT-TYPE": @@ -113,8 +118,10 @@ def create(req, sock, client, server, cfg): hdr_value = "%s,%s" % (environ[key], hdr_value) environ[key] = hdr_value + # set the url schejeme environ['wsgi.url_scheme'] = url_scheme + # set the REMOTE_* keys in environ # authors should be aware that REMOTE_HOST and REMOTE_ADDR # may not qualify the remote addr: # http://www.ietf.org/rfc/rfc3875 @@ -124,26 +131,42 @@ def create(req, sock, client, server, cfg): environ['REMOTE_ADDR'] = client[0] environ['REMOTE_PORT'] = str(client[1]) + # handle the SERVER_* + # Normally only the application should use the Host header but since the + # WSGI spec doesn't support unix sockets, we are using it to create + # viable SERVER_* if possible. if isinstance(server, string_types): server = server.split(":") if len(server) == 1: - if url_scheme == "http": - server.append("80") - elif url_scheme == "https": - server.append("443") + # unix socket + if host and host is not None: + server = host.split(':') + if len(server) == 1: + if url_scheme == "http": + server.append(80), + elif url_scheme == "https": + server.append(443) + else: + server.append('') else: + # no host header given which means that we are not behind a + # proxy, so append an empty port. server.append('') environ['SERVER_NAME'] = server[0] environ['SERVER_PORT'] = str(server[1]) + # set the path and script name path_info = req.path if script_name: path_info = path_info.split(script_name, 1)[1] environ['PATH_INFO'] = unquote_to_wsgi_str(path_info) environ['SCRIPT_NAME'] = script_name + # override the environ with the correct remote and server address if + # we are behind a proxy using the proxy protocol. environ.update(proxy_environ(req)) + print(environ) return resp, environ