Finishes this response, ending the HTTP request. Passing a ``chunk`` to ``finish()`` is equivalent to passing that chunk to ``write()`` and then calling ``finish()`` with no arguments. Returns a `.Future` which may optionally be awaited to track the sending of the r
(self, chunk: Optional[Union[str, bytes, dict]] = None)
| 1268 | return future |
| 1269 | |
| 1270 | def finish(self, chunk: Optional[Union[str, bytes, dict]] = None) -> "Future[None]": |
| 1271 | """Finishes this response, ending the HTTP request. |
| 1272 | |
| 1273 | Passing a ``chunk`` to ``finish()`` is equivalent to passing that |
| 1274 | chunk to ``write()`` and then calling ``finish()`` with no arguments. |
| 1275 | |
| 1276 | Returns a `.Future` which may optionally be awaited to track the sending |
| 1277 | of the response to the client. This `.Future` resolves when all the response |
| 1278 | data has been sent, and raises an error if the connection is closed before all |
| 1279 | data can be sent. |
| 1280 | |
| 1281 | .. versionchanged:: 5.1 |
| 1282 | |
| 1283 | Now returns a `.Future` instead of ``None``. |
| 1284 | """ |
| 1285 | if self._finished: |
| 1286 | raise RuntimeError("finish() called twice") |
| 1287 | |
| 1288 | if chunk is not None: |
| 1289 | self.write(chunk) |
| 1290 | |
| 1291 | # Automatically support ETags and add the Content-Length header if |
| 1292 | # we have not flushed any content yet. |
| 1293 | if not self._headers_written: |
| 1294 | if ( |
| 1295 | self._status_code == 200 |
| 1296 | and self.request.method in ("GET", "HEAD") |
| 1297 | and "Etag" not in self._headers |
| 1298 | ): |
| 1299 | self.set_etag_header() |
| 1300 | if self.check_etag_header(): |
| 1301 | self._write_buffer = [] |
| 1302 | self.set_status(304) |
| 1303 | if self._status_code in (204, 304) or (100 <= self._status_code < 200): |
| 1304 | assert not self._write_buffer, ( |
| 1305 | "Cannot send body with %s" % self._status_code |
| 1306 | ) |
| 1307 | self._clear_representation_headers() |
| 1308 | elif "Content-Length" not in self._headers: |
| 1309 | content_length = sum(len(part) for part in self._write_buffer) |
| 1310 | self.set_header("Content-Length", content_length) |
| 1311 | |
| 1312 | assert self.request.connection is not None |
| 1313 | # Now that the request is finished, clear the callback we |
| 1314 | # set on the HTTPConnection (which would otherwise prevent the |
| 1315 | # garbage collection of the RequestHandler when there |
| 1316 | # are keepalive connections) |
| 1317 | self.request.connection.set_close_callback(None) # type: ignore |
| 1318 | |
| 1319 | future = self.flush(include_footers=True) |
| 1320 | self.request.connection.finish() |
| 1321 | self._log() |
| 1322 | self._finished = True |
| 1323 | self.on_finish() |
| 1324 | self._break_cycles() |
| 1325 | return future |
| 1326 | |
| 1327 | def detach(self) -> iostream.IOStream: |