| 95 | self.wsgi_application = wsgi_application |
| 96 | |
| 97 | def __call__(self, request: httputil.HTTPServerRequest) -> None: |
| 98 | data = {} # type: Dict[str, Any] |
| 99 | response = [] # type: List[bytes] |
| 100 | |
| 101 | def start_response( |
| 102 | status: str, |
| 103 | headers: List[Tuple[str, str]], |
| 104 | exc_info: Optional[ |
| 105 | Tuple[ |
| 106 | "Optional[Type[BaseException]]", |
| 107 | Optional[BaseException], |
| 108 | Optional[TracebackType], |
| 109 | ] |
| 110 | ] = None, |
| 111 | ) -> Callable[[bytes], Any]: |
| 112 | data["status"] = status |
| 113 | data["headers"] = headers |
| 114 | return response.append |
| 115 | |
| 116 | app_response = self.wsgi_application( |
| 117 | WSGIContainer.environ(request), start_response |
| 118 | ) |
| 119 | try: |
| 120 | response.extend(app_response) |
| 121 | body = b"".join(response) |
| 122 | finally: |
| 123 | if hasattr(app_response, "close"): |
| 124 | app_response.close() # type: ignore |
| 125 | if not data: |
| 126 | raise Exception("WSGI app did not call start_response") |
| 127 | |
| 128 | status_code_str, reason = data["status"].split(" ", 1) |
| 129 | status_code = int(status_code_str) |
| 130 | headers = data["headers"] # type: List[Tuple[str, str]] |
| 131 | header_set = set(k.lower() for (k, v) in headers) |
| 132 | body = escape.utf8(body) |
| 133 | if status_code != 304: |
| 134 | if "content-length" not in header_set: |
| 135 | headers.append(("Content-Length", str(len(body)))) |
| 136 | if "content-type" not in header_set: |
| 137 | headers.append(("Content-Type", "text/html; charset=UTF-8")) |
| 138 | if "server" not in header_set: |
| 139 | headers.append(("Server", "TornadoServer/%s" % tornado.version)) |
| 140 | |
| 141 | start_line = httputil.ResponseStartLine("HTTP/1.1", status_code, reason) |
| 142 | header_obj = httputil.HTTPHeaders() |
| 143 | for key, value in headers: |
| 144 | header_obj.add(key, value) |
| 145 | assert request.connection is not None |
| 146 | request.connection.write_headers(start_line, header_obj, chunk=body) |
| 147 | request.connection.finish() |
| 148 | self._log(status_code, request) |
| 149 | |
| 150 | @staticmethod |
| 151 | def environ(request: httputil.HTTPServerRequest) -> Dict[Text, Any]: |