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