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)
| 1108 | return future |
| 1109 | |
| 1110 | def finish(self, chunk: Optional[Union[str, bytes, dict]] = None) -> "Future[None]": |
| 1111 | """Finishes this response, ending the HTTP request. |
| 1112 | |
| 1113 | Passing a ``chunk`` to ``finish()`` is equivalent to passing that |
| 1114 | chunk to ``write()`` and then calling ``finish()`` with no arguments. |
| 1115 | |
| 1116 | Returns a `.Future` which may optionally be awaited to track the sending |
| 1117 | of the response to the client. This `.Future` resolves when all the response |
| 1118 | data has been sent, and raises an error if the connection is closed before all |
| 1119 | data can be sent. |
| 1120 | |
| 1121 | .. versionchanged:: 5.1 |
| 1122 | |
| 1123 | Now returns a `.Future` instead of ``None``. |
| 1124 | """ |
| 1125 | if self._finished: |
| 1126 | raise RuntimeError("finish() called twice") |
| 1127 | |
| 1128 | if chunk is not None: |
| 1129 | self.write(chunk) |
| 1130 | |
| 1131 | # Automatically support ETags and add the Content-Length header if |
| 1132 | # we have not flushed any content yet. |
| 1133 | if not self._headers_written: |
| 1134 | if ( |
| 1135 | self._status_code == 200 |
| 1136 | and self.request.method in ("GET", "HEAD") |
| 1137 | and "Etag" not in self._headers |
| 1138 | ): |
| 1139 | self.set_etag_header() |
| 1140 | if self.check_etag_header(): |
| 1141 | self._write_buffer = [] |
| 1142 | self.set_status(304) |
| 1143 | if self._status_code in (204, 304) or (100 <= self._status_code < 200): |
| 1144 | assert not self._write_buffer, ( |
| 1145 | "Cannot send body with %s" % self._status_code |
| 1146 | ) |
| 1147 | self._clear_representation_headers() |
| 1148 | elif "Content-Length" not in self._headers: |
| 1149 | content_length = sum(len(part) for part in self._write_buffer) |
| 1150 | self.set_header("Content-Length", content_length) |
| 1151 | |
| 1152 | assert self.request.connection is not None |
| 1153 | # Now that the request is finished, clear the callback we |
| 1154 | # set on the HTTPConnection (which would otherwise prevent the |
| 1155 | # garbage collection of the RequestHandler when there |
| 1156 | # are keepalive connections) |
| 1157 | self.request.connection.set_close_callback(None) # type: ignore |
| 1158 | |
| 1159 | future = self.flush(include_footers=True) |
| 1160 | self.request.connection.finish() |
| 1161 | self._log() |
| 1162 | self._finished = True |
| 1163 | self.on_finish() |
| 1164 | self._break_cycles() |
| 1165 | return future |
| 1166 | |
| 1167 | def detach(self) -> iostream.IOStream: |
no test coverage detected