header_data = yield self.stream.read_until_regex(b"\r?\n\r?\n")
self._finish_future = Future()
start_line, headers = self._parse_headers(header_data)
+ if is_client:
+ start_line = httputil.parse_response_start_line(start_line)
+ else:
+ start_line = httputil.parse_request_start_line(start_line)
self._disconnect_on_finish = not self._can_keep_alive(
start_line, headers)
ret = delegate.headers_received(start_line, headers)
if is_client:
if method == 'HEAD':
skip_body = True
- code = httputil.parse_response_start_line(start_line).code
+ code = start_line.code
if code == 304:
skip_body = True
if code >= 100 and code < 200:
connection_header = headers.get("Connection")
if connection_header is not None:
connection_header = connection_header.lower()
- if start_line.endswith("HTTP/1.1"):
+ if start_line.version == "HTTP/1.1":
return connection_header != "close"
elif ("Content-Length" in headers
- or start_line.startswith(("HEAD ", "GET "))):
+ or start_line.method in ("HEAD", "GET")):
return connection_header == "keep-alive"
return False
self.connection = connection
def headers_received(self, start_line, headers):
- try:
- method, uri, version = start_line.split(" ")
- except ValueError:
- raise httputil.HTTPMessageException("Malformed HTTP request line")
- if not version.startswith("HTTP/"):
- raise httputil.HTTPMessageException(
- "Malformed HTTP version in HTTP Request-Line")
# HTTPRequest wants an IP, not a full socket address
if self.connection.address_family in (socket.AF_INET, socket.AF_INET6):
remote_ip = self.connection.address[0]
protocol = proto_header
self.request = httputil.HTTPServerRequest(
- connection=self.connection, method=method, uri=uri, version=version,
+ connection=self.connection, method=start_line.method,
+ uri=start_line.path, version=start_line.version,
headers=headers, remote_ip=remote_ip, protocol=protocol)
def data_received(self, chunk):
'RequestStartLine', ['method', 'path', 'version'])
+def parse_request_start_line(line):
+ """Returns a (method, path, version) tuple for an HTTP 1.x request line.
+
+ The response is a `collections.namedtuple`.
+
+ >>> parse_request_start_line("GET /foo HTTP/1.1")
+ RequestStartLine(method='GET', path='/foo', version='HTTP/1.1')
+ """
+ try:
+ method, path, version = line.split(" ")
+ except ValueError:
+ raise HTTPMessageException("Malformed HTTP request line")
+ if not version.startswith("HTTP/"):
+ raise HTTPMessageException(
+ "Malformed HTTP version in HTTP Request-Line: %r" % version)
+ return RequestStartLine(method, path, version)
+
+
ResponseStartLine = collections.namedtuple(
'ResponseStartLine', ['version', 'code', 'reason'])
def headers_received(self, first_line, headers):
self.headers = headers
- version, code, reason = httputil.parse_response_start_line(first_line)
- self.code = code
- self.reason = reason
+ self.code = first_line.code
+ self.reason = first_line.reason
if "Content-Length" in self.headers:
if "," in self.headers["Content-Length"]:
content_length = None
if self.request.header_callback is not None:
- # re-attach the newline we split on earlier
- self.request.header_callback(first_line + '\r\n')
+ # Reassemble the start line.
+ self.request.header_callback('%s %s %s\r\n' % first_line)
for k, v in self.headers.get_all():
self.request.header_callback("%s: %s\r\n" % (k, v))
self.request.header_callback('\r\n')
"Non-websocket response"))
def headers_received(self, start_line, headers):
- code = httputil.parse_response_start_line(start_line).code
-
- if code != 101:
+ if start_line.code != 101:
return super(WebSocketClientConnection, self).headers_received(
start_line, headers)