(self, delegate: httputil.HTTPMessageDelegate)
| 188 | return self._read_message(delegate) |
| 189 | |
| 190 | async def _read_message(self, delegate: httputil.HTTPMessageDelegate) -> bool: |
| 191 | need_delegate_close = False |
| 192 | try: |
| 193 | header_future = self.stream.read_until_regex( |
| 194 | b"\r?\n\r?\n", max_bytes=self.params.max_header_size |
| 195 | ) |
| 196 | if self.params.header_timeout is None: |
| 197 | header_data = await header_future |
| 198 | else: |
| 199 | try: |
| 200 | header_data = await gen.with_timeout( |
| 201 | self.stream.io_loop.time() + self.params.header_timeout, |
| 202 | header_future, |
| 203 | quiet_exceptions=iostream.StreamClosedError, |
| 204 | ) |
| 205 | except gen.TimeoutError: |
| 206 | self.close() |
| 207 | return False |
| 208 | start_line_str, headers = self._parse_headers(header_data) |
| 209 | if self.is_client: |
| 210 | resp_start_line = httputil.parse_response_start_line(start_line_str) |
| 211 | self._response_start_line = resp_start_line |
| 212 | start_line = ( |
| 213 | resp_start_line |
| 214 | ) # type: Union[httputil.RequestStartLine, httputil.ResponseStartLine] |
| 215 | # TODO: this will need to change to support client-side keepalive |
| 216 | self._disconnect_on_finish = False |
| 217 | else: |
| 218 | req_start_line = httputil.parse_request_start_line(start_line_str) |
| 219 | self._request_start_line = req_start_line |
| 220 | self._request_headers = headers |
| 221 | start_line = req_start_line |
| 222 | self._disconnect_on_finish = not self._can_keep_alive( |
| 223 | req_start_line, headers |
| 224 | ) |
| 225 | need_delegate_close = True |
| 226 | with _ExceptionLoggingContext(app_log): |
| 227 | header_recv_future = delegate.headers_received(start_line, headers) |
| 228 | if header_recv_future is not None: |
| 229 | await header_recv_future |
| 230 | if self.stream is None: |
| 231 | # We've been detached. |
| 232 | need_delegate_close = False |
| 233 | return False |
| 234 | skip_body = False |
| 235 | if self.is_client: |
| 236 | assert isinstance(start_line, httputil.ResponseStartLine) |
| 237 | if ( |
| 238 | self._request_start_line is not None |
| 239 | and self._request_start_line.method == "HEAD" |
| 240 | ): |
| 241 | skip_body = True |
| 242 | code = start_line.code |
| 243 | if code == 304: |
| 244 | # 304 responses may include the content-length header |
| 245 | # but do not actually have a body. |
| 246 | # http://tools.ietf.org/html/rfc7230#section-3.3 |
| 247 | skip_body = True |
no test coverage detected