Storage class for a response body as well as headers and cookies. This class does support dict-like case-insensitive item-access to headers, but is NOT a dict. Most notably, iterating over a response yields parts of the body and not the headers. :param body: The re
| 1621 | |
| 1622 | |
| 1623 | class BaseResponse(object): |
| 1624 | """ Storage class for a response body as well as headers and cookies. |
| 1625 | |
| 1626 | This class does support dict-like case-insensitive item-access to |
| 1627 | headers, but is NOT a dict. Most notably, iterating over a response |
| 1628 | yields parts of the body and not the headers. |
| 1629 | |
| 1630 | :param body: The response body as one of the supported types. |
| 1631 | :param status: Either an HTTP status code (e.g. 200) or a status line |
| 1632 | including the reason phrase (e.g. '200 OK'). |
| 1633 | :param headers: A dictionary or a list of name-value pairs. |
| 1634 | |
| 1635 | Additional keyword arguments are added to the list of headers. |
| 1636 | Underscores in the header name are replaced with dashes. |
| 1637 | """ |
| 1638 | |
| 1639 | default_status = 200 |
| 1640 | default_content_type = 'text/html; charset=UTF-8' |
| 1641 | |
| 1642 | # Header denylist for specific response codes |
| 1643 | # (rfc2616 section 10.2.3 and 10.3.5) |
| 1644 | bad_headers = { |
| 1645 | 204: frozenset(('Content-Type', 'Content-Length')), |
| 1646 | 304: frozenset(('Allow', 'Content-Encoding', 'Content-Language', |
| 1647 | 'Content-Length', 'Content-Range', 'Content-Type', |
| 1648 | 'Content-Md5', 'Last-Modified')) |
| 1649 | } |
| 1650 | |
| 1651 | def __init__(self, body='', status=None, headers=None, **more_headers): |
| 1652 | self._cookies = None |
| 1653 | self._headers = {} |
| 1654 | self.body = body |
| 1655 | self.status = status or self.default_status |
| 1656 | if headers: |
| 1657 | if isinstance(headers, dict): |
| 1658 | headers = headers.items() |
| 1659 | for name, value in headers: |
| 1660 | self.add_header(name, value) |
| 1661 | if more_headers: |
| 1662 | for name, value in more_headers.items(): |
| 1663 | self.add_header(name, value) |
| 1664 | |
| 1665 | def copy(self, cls=None): |
| 1666 | """ Returns a copy of self. """ |
| 1667 | cls = cls or BaseResponse |
| 1668 | assert issubclass(cls, BaseResponse) |
| 1669 | copy = cls() |
| 1670 | copy.status = self.status |
| 1671 | copy._headers = dict((k, v[:]) for (k, v) in self._headers.items()) |
| 1672 | if self._cookies: |
| 1673 | cookies = copy._cookies = SimpleCookie() |
| 1674 | for k,v in self._cookies.items(): |
| 1675 | cookies[k] = v.value |
| 1676 | cookies[k].update(v) # also copy cookie attributes |
| 1677 | return copy |
| 1678 | |
| 1679 | def __iter__(self): |
| 1680 | return iter(self.body) |
nothing calls this directly
no test coverage detected