From b71ec473bbea7b5efa32f2a25e2656a690baa722 Mon Sep 17 00:00:00 2001 From: chengkang <1412950785@qq.com> Date: Fri, 1 Jun 2018 19:57:51 +0800 Subject: [PATCH 1/3] _HTTPConnection: verify whether location is specified while check _should_follow_redirect() --- tornado/simple_httpclient.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tornado/simple_httpclient.py b/tornado/simple_httpclient.py index 35c719362d..e0b0ebc30d 100644 --- a/tornado/simple_httpclient.py +++ b/tornado/simple_httpclient.py @@ -491,9 +491,17 @@ def headers_received(self, first_line, headers): self.request.header_callback('\r\n') def _should_follow_redirect(self): - return (self.request.follow_redirects and + if not (self.request.follow_redirects and self.request.max_redirects > 0 and - self.code in (301, 302, 303, 307, 308)) + self.code in (301, 302, 303, 307, 308)): + return False + # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.4 + # According to the spec, the temporary URI may not be specified when the + # request method was HEAD. + # TODO: Unless the request method was HEAD, give a warning or raise an + # exception when the temporary URI is not specified? + redirect_location = self.headers.get("Location") + return (redirect_location is not None) def finish(self): data = b''.join(self.chunks) @@ -515,7 +523,8 @@ def finish(self): # compatibility with pre-HTTP/1.1 user agents which don't # understand the 303 status. if self.code in (302, 303): - new_request.method = "GET" + if self.request.method != "HEAD": + new_request.method = "GET" new_request.body = None for h in ["Content-Length", "Content-Type", "Content-Encoding", "Transfer-Encoding"]: From b96e8fa8435a7e176e995abf5f64626329ea7a23 Mon Sep 17 00:00:00 2001 From: chengkang <1412950785@qq.com> Date: Sun, 3 Jun 2018 18:57:28 +0800 Subject: [PATCH 2/3] check location on _should_follow_redirect() and retain safe request when following redirects --- tornado/simple_httpclient.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/tornado/simple_httpclient.py b/tornado/simple_httpclient.py index e0b0ebc30d..fdf9403d6f 100644 --- a/tornado/simple_httpclient.py +++ b/tornado/simple_httpclient.py @@ -209,6 +209,7 @@ def _on_timeout(self, key, info=None): class _HTTPConnection(httputil.HTTPMessageDelegate): _SUPPORTED_METHODS = set(["GET", "HEAD", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"]) + _SAFE_NETHODS = set(["GET", "HEAD", "OPTIONS"]) def __init__(self, client, request, release_callback, final_callback, max_buffer_size, tcp_client, @@ -491,17 +492,10 @@ def headers_received(self, first_line, headers): self.request.header_callback('\r\n') def _should_follow_redirect(self): - if not (self.request.follow_redirects and + return (self.request.follow_redirects and self.request.max_redirects > 0 and - self.code in (301, 302, 303, 307, 308)): - return False - # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.4 - # According to the spec, the temporary URI may not be specified when the - # request method was HEAD. - # TODO: Unless the request method was HEAD, give a warning or raise an - # exception when the temporary URI is not specified? - redirect_location = self.headers.get("Location") - return (redirect_location is not None) + self.code in (301, 302, 303, 307, 308) and + self.headers.get("Location") is not None) def finish(self): data = b''.join(self.chunks) @@ -522,8 +516,8 @@ def finish(self): # treat 302 the same as 303, and many servers use 302 for # compatibility with pre-HTTP/1.1 user agents which don't # understand the 303 status. - if self.code in (302, 303): - if self.request.method != "HEAD": + if self.code in (301, 302, 303): + if self.request.method not in self._SAFE_NETHODS: new_request.method = "GET" new_request.body = None for h in ["Content-Length", "Content-Type", From c940eb8195476abf8d1e4e3990fe29a99523526b Mon Sep 17 00:00:00 2001 From: chengkang <1412950785@qq.com> Date: Mon, 4 Jun 2018 09:24:16 +0800 Subject: [PATCH 3/3] fix minor typo --- tornado/simple_httpclient.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tornado/simple_httpclient.py b/tornado/simple_httpclient.py index fdf9403d6f..b4076d32f0 100644 --- a/tornado/simple_httpclient.py +++ b/tornado/simple_httpclient.py @@ -209,7 +209,7 @@ def _on_timeout(self, key, info=None): class _HTTPConnection(httputil.HTTPMessageDelegate): _SUPPORTED_METHODS = set(["GET", "HEAD", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"]) - _SAFE_NETHODS = set(["GET", "HEAD", "OPTIONS"]) + _SAFE_METHODS = set(["GET", "HEAD", "OPTIONS"]) def __init__(self, client, request, release_callback, final_callback, max_buffer_size, tcp_client, @@ -517,7 +517,7 @@ def finish(self): # compatibility with pre-HTTP/1.1 user agents which don't # understand the 303 status. if self.code in (301, 302, 303): - if self.request.method not in self._SAFE_NETHODS: + if self.request.method not in self._SAFE_METHODS: new_request.method = "GET" new_request.body = None for h in ["Content-Length", "Content-Type",