| 286 | |
| 287 | |
| 288 | class Response: |
| 289 | |
| 290 | def __init__(self, req, sock, cfg): |
| 291 | self.req = req |
| 292 | self.sock = sock |
| 293 | self.version = SERVER |
| 294 | self.status = None |
| 295 | self.chunked = False |
| 296 | self.must_close = False |
| 297 | self.headers = [] |
| 298 | self.headers_sent = False |
| 299 | self.response_length = None |
| 300 | self.sent = 0 |
| 301 | self.upgrade = False |
| 302 | self.cfg = cfg |
| 303 | |
| 304 | def force_close(self): |
| 305 | self.must_close = True |
| 306 | |
| 307 | def should_close(self): |
| 308 | if self.must_close or self.req.should_close(): |
| 309 | return True |
| 310 | if self.response_length is not None or self.chunked: |
| 311 | return False |
| 312 | if self.req.method == 'HEAD': |
| 313 | return False |
| 314 | if self.status_code < 200 or self.status_code in (204, 304): |
| 315 | return False |
| 316 | return True |
| 317 | |
| 318 | def start_response(self, status, headers, exc_info=None): |
| 319 | if exc_info: |
| 320 | try: |
| 321 | if self.status and self.headers_sent: |
| 322 | util.reraise(exc_info[0], exc_info[1], exc_info[2]) |
| 323 | finally: |
| 324 | exc_info = None |
| 325 | elif self.status is not None: |
| 326 | raise AssertionError("Response headers already set!") |
| 327 | |
| 328 | self.status = status |
| 329 | |
| 330 | # get the status code from the response here so we can use it to check |
| 331 | # the need for the connection header later without parsing the string |
| 332 | # each time. |
| 333 | try: |
| 334 | self.status_code = int(self.status.split()[0]) |
| 335 | except ValueError: |
| 336 | self.status_code = None |
| 337 | |
| 338 | self.process_headers(headers) |
| 339 | self.chunked = self.is_chunked() |
| 340 | return self.write |
| 341 | |
| 342 | def process_headers(self, headers): |
| 343 | for name, value in headers: |
| 344 | if not isinstance(name, str): |
| 345 | raise TypeError('%r is not a string' % name) |
no outgoing calls