diff options
Diffstat (limited to 'netlib/http/response.py')
| -rw-r--r-- | netlib/http/response.py | 124 | 
1 files changed, 123 insertions, 1 deletions
| diff --git a/netlib/http/response.py b/netlib/http/response.py index 02fac3df..7d64243d 100644 --- a/netlib/http/response.py +++ b/netlib/http/response.py @@ -1,3 +1,125 @@  from __future__ import absolute_import, print_function, division -# TODO
\ No newline at end of file +import warnings + +from . import cookies +from .headers import Headers +from .message import Message, _native, _always_bytes +from .. import utils +from ..odict import ODict + + +class ResponseData(object): +    def __init__(self, http_version, status_code, reason=None, headers=None, content=None, +                 timestamp_start=None, timestamp_end=None): +        if not headers: +            headers = Headers() +        assert isinstance(headers, Headers) + +        self.http_version = http_version +        self.status_code = status_code +        self.reason = reason +        self.headers = headers +        self.content = content +        self.timestamp_start = timestamp_start +        self.timestamp_end = timestamp_end + +    def __eq__(self, other): +        if isinstance(other, ResponseData): +            return self.__dict__ == other.__dict__ +        return False + +    def __ne__(self, other): +        return not self.__eq__(other) + + +class Response(Message): +    """ +    An HTTP response. +    """ +    def __init__(self, *args, **kwargs): +        data = ResponseData(*args, **kwargs) +        super(Response, self).__init__(data) + +    def __repr__(self): +        if self.content: +            details = "{}, {}".format( +                self.headers.get("content-type", "unknown content type"), +                utils.pretty_size(len(self.content)) +            ) +        else: +            details = "content missing" +        return "Response({status_code} {reason}, {details})".format( +            status_code=self.status_code, +            reason=self.reason, +            details=details +        ) + +    @property +    def status_code(self): +        """ +        HTTP Status Code, e.g. ``200``. +        """ +        return self.data.status_code + +    @status_code.setter +    def status_code(self, status_code): +        self.data.status_code = status_code + +    @property +    def reason(self): +        """ +        HTTP Reason Phrase, e.g. "Not Found". +        This is always :py:obj:`None` for HTTP2 requests, because HTTP2 responses do not contain a reason phrase. +        """ +        return _native(self.data.reason) + +    @reason.setter +    def reason(self, reason): +        self.data.reason = _always_bytes(reason) + +    @property +    def cookies(self): +        """ +        Get the contents of all Set-Cookie headers. + +        A possibly empty :py:class:`ODict`, where keys are cookie name strings, +        and values are [value, attr] lists. Value is a string, and attr is +        an ODictCaseless containing cookie attributes. Within attrs, unary +        attributes (e.g. HTTPOnly) are indicated by a Null value. +        """ +        ret = [] +        for header in self.headers.get_all("set-cookie"): +            v = cookies.parse_set_cookie_header(header) +            if v: +                name, value, attrs = v +                ret.append([name, [value, attrs]]) +        return ODict(ret) + +    @cookies.setter +    def cookies(self, odict): +        values = [] +        for i in odict.lst: +            header = cookies.format_set_cookie_header(i[0], i[1][0], i[1][1]) +            values.append(header) +        self.headers.set_all("set-cookie", values) + +    # Legacy + +    def get_cookies(self): +        warnings.warn(".get_cookies is deprecated, use .cookies instead.", DeprecationWarning) +        return self.cookies + +    def set_cookies(self, odict): +        warnings.warn(".set_cookies is deprecated, use .cookies instead.", DeprecationWarning) +        self.cookies = odict + +    @property +    def msg(self): +        warnings.warn(".msg is deprecated, use .reason instead.", DeprecationWarning) +        return self.reason + +    @msg.setter +    def msg(self, reason): +        warnings.warn(".msg is deprecated, use .reason instead.", DeprecationWarning) +        self.reason = reason | 
