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
| 2019 | |
| 2020 | |
| 2021 | class BaseResponse(object): |
| 2022 | """ Storage class for a response body as well as headers and cookies. |
| 2023 | |
| 2024 | This class does support dict-like case-insensitive item-access to |
| 2025 | headers, but is NOT a dict. Most notably, iterating over a response |
| 2026 | yields parts of the body and not the headers. |
| 2027 | |
| 2028 | :param body: The response body as one of the supported types. |
| 2029 | :param status: Either an HTTP status code (e.g. 200) or a status line |
| 2030 | including the reason phrase (e.g. '200 OK'). |
| 2031 | :param headers: A dictionary or a list of name-value pairs. |
| 2032 | |
| 2033 | Additional keyword arguments are added to the list of headers. |
| 2034 | Underscores in the header name are replaced with dashes. |
| 2035 | """ |
| 2036 | |
| 2037 | default_status = 200 |
| 2038 | default_content_type = 'text/html; charset=UTF-8' |
| 2039 | |
| 2040 | # Header denylist for specific response codes |
| 2041 | # (rfc2616 section 10.2.3 and 10.3.5) |
| 2042 | bad_headers = { |
| 2043 | 204: frozenset(('Content-Type', 'Content-Length')), |
| 2044 | 304: frozenset(('Allow', 'Content-Encoding', 'Content-Language', |
| 2045 | 'Content-Length', 'Content-Range', 'Content-Type', |
| 2046 | 'Content-Md5', 'Last-Modified')) |
| 2047 | } |
| 2048 | |
| 2049 | def __init__(self, body='', status=None, headers=None, **more_headers): |
| 2050 | self._cookies = None |
| 2051 | self._headers = {} |
| 2052 | self.body = body |
| 2053 | self.status = status or self.default_status |
| 2054 | if headers: |
| 2055 | if isinstance(headers, dict): |
| 2056 | headers = headers.items() |
| 2057 | for name, value in headers: |
| 2058 | self.add_header(name, value) |
| 2059 | if more_headers: |
| 2060 | for name, value in more_headers.items(): |
| 2061 | self.add_header(name, value) |
| 2062 | |
| 2063 | def copy(self, cls=None): |
| 2064 | """ Returns a copy of self. """ |
| 2065 | cls = cls or BaseResponse |
| 2066 | assert issubclass(cls, BaseResponse) |
| 2067 | copy = cls() |
| 2068 | copy.status = self.status |
| 2069 | copy._headers = dict((k, v[:]) for (k, v) in self._headers.items()) |
| 2070 | if self._cookies: |
| 2071 | cookies = copy._cookies = SimpleCookie() |
| 2072 | for k,v in self._cookies.items(): |
| 2073 | cookies[k] = v.value |
| 2074 | cookies[k].update(v) # also copy cookie attributes |
| 2075 | return copy |
| 2076 | |
| 2077 | def __iter__(self): |
| 2078 | return iter(self.body) |
nothing calls this directly
no test coverage detected
searching dependent graphs…