diff options
Diffstat (limited to 'netlib/http')
| -rw-r--r-- | netlib/http/cookies.py | 29 | ||||
| -rw-r--r-- | netlib/http/headers.py | 9 | ||||
| -rw-r--r-- | netlib/http/http2/__init__.py | 2 | ||||
| -rw-r--r-- | netlib/http/http2/utils.py | 37 | ||||
| -rw-r--r-- | netlib/http/message.py | 2 | ||||
| -rw-r--r-- | netlib/http/request.py | 12 | ||||
| -rw-r--r-- | netlib/http/response.py | 7 | 
7 files changed, 96 insertions, 2 deletions
| diff --git a/netlib/http/cookies.py b/netlib/http/cookies.py index 768a85df..dd0af99c 100644 --- a/netlib/http/cookies.py +++ b/netlib/http/cookies.py @@ -1,7 +1,8 @@  import collections +import email.utils  import re +import time -import email.utils  from netlib import multidict  """ @@ -260,3 +261,29 @@ def refresh_set_cookie_header(c, delta):      if not ret:          raise ValueError("Invalid Cookie")      return ret + + +def is_expired(cookie_attrs): +    """ +        Determines whether a cookie has expired. + +        Returns: boolean +    """ + +    # See if 'expires' time is in the past +    expires = False +    if 'expires' in cookie_attrs: +        e = email.utils.parsedate_tz(cookie_attrs["expires"]) +        if e: +            exp_ts = email.utils.mktime_tz(e) +            now_ts = time.time() +            expires = exp_ts < now_ts + +    # or if Max-Age is 0 +    max_age = False +    try: +        max_age = int(cookie_attrs.get('Max-Age', 1)) == 0 +    except ValueError: +        pass + +    return expires or max_age diff --git a/netlib/http/headers.py b/netlib/http/headers.py index 13a8c98f..b8aa212a 100644 --- a/netlib/http/headers.py +++ b/netlib/http/headers.py @@ -148,6 +148,15 @@ class Headers(multidict.MultiDict):          value = _always_bytes(value)          super(Headers, self).insert(index, key, value) +    def items(self, multi=False): +        if multi: +            return ( +                (_native(k), _native(v)) +                for k, v in self.fields +            ) +        else: +            return super(Headers, self).items() +      def replace(self, pattern, repl, flags=0):          """          Replaces a regular expression pattern with repl in each "name: value" diff --git a/netlib/http/http2/__init__.py b/netlib/http/http2/__init__.py index 6a979a0d..60064190 100644 --- a/netlib/http/http2/__init__.py +++ b/netlib/http/http2/__init__.py @@ -1,6 +1,8 @@  from __future__ import absolute_import, print_function, division  from netlib.http.http2 import framereader +from netlib.http.http2.utils import parse_headers  __all__ = [      "framereader", +    "parse_headers",  ] diff --git a/netlib/http/http2/utils.py b/netlib/http/http2/utils.py new file mode 100644 index 00000000..164bacc8 --- /dev/null +++ b/netlib/http/http2/utils.py @@ -0,0 +1,37 @@ +from netlib.http import url + + +def parse_headers(headers): +    authority = headers.get(':authority', '').encode() +    method = headers.get(':method', 'GET').encode() +    scheme = headers.get(':scheme', 'https').encode() +    path = headers.get(':path', '/').encode() + +    headers.pop(":method", None) +    headers.pop(":scheme", None) +    headers.pop(":path", None) + +    host = None +    port = None + +    if path == b'*' or path.startswith(b"/"): +        first_line_format = "relative" +    elif method == b'CONNECT':  # pragma: no cover +        raise NotImplementedError("CONNECT over HTTP/2 is not implemented.") +    else:  # pragma: no cover +        first_line_format = "absolute" +        # FIXME: verify if path or :host contains what we need +        scheme, host, port, _ = url.parse(path) + +    if authority: +        host, _, port = authority.partition(b':') + +    if not host: +        host = b'localhost' + +    if not port: +        port = 443 if scheme == b'https' else 80 + +    port = int(port) + +    return first_line_format, method, scheme, host, port, path diff --git a/netlib/http/message.py b/netlib/http/message.py index 1252ed25..34709f0a 100644 --- a/netlib/http/message.py +++ b/netlib/http/message.py @@ -263,7 +263,7 @@ class Message(basetypes.Serializable):                  if strict:                      raise                  is_strict = False -                decoded = self.content.decode(enc, "replace" if six.PY2 else "surrogateescape") +                decoded = self.content.decode("utf8", "replace" if six.PY2 else "surrogateescape")              self._text_cache = CachedDecode(content, enc, is_strict, decoded)          return self._text_cache.decoded diff --git a/netlib/http/request.py b/netlib/http/request.py index a8ec6238..ecaa9b79 100644 --- a/netlib/http/request.py +++ b/netlib/http/request.py @@ -22,8 +22,20 @@ host_header_re = re.compile(r"^(?P<host>[^:]+|\[.+\])(?::(?P<port>\d+))?$")  class RequestData(message.MessageData):      def __init__(self, first_line_format, method, scheme, host, port, path, http_version, headers=(), content=None,                   timestamp_start=None, timestamp_end=None): +        if isinstance(method, six.text_type): +            method = method.encode("ascii", "strict") +        if isinstance(scheme, six.text_type): +            scheme = scheme.encode("ascii", "strict") +        if isinstance(host, six.text_type): +            host = host.encode("idna", "strict") +        if isinstance(path, six.text_type): +            path = path.encode("ascii", "strict") +        if isinstance(http_version, six.text_type): +            http_version = http_version.encode("ascii", "strict")          if not isinstance(headers, nheaders.Headers):              headers = nheaders.Headers(headers) +        if isinstance(content, six.text_type): +            raise ValueError("Content must be bytes, not {}".format(type(content).__name__))          self.first_line_format = first_line_format          self.method = method diff --git a/netlib/http/response.py b/netlib/http/response.py index d2273edd..85f54940 100644 --- a/netlib/http/response.py +++ b/netlib/http/response.py @@ -2,6 +2,7 @@ from __future__ import absolute_import, print_function, division  from email.utils import parsedate_tz, formatdate, mktime_tz  import time +import six  from netlib.http import cookies  from netlib.http import headers as nheaders @@ -13,8 +14,14 @@ from netlib import human  class ResponseData(message.MessageData):      def __init__(self, http_version, status_code, reason=None, headers=(), content=None,                   timestamp_start=None, timestamp_end=None): +        if isinstance(http_version, six.text_type): +            http_version = http_version.encode("ascii", "strict") +        if isinstance(reason, six.text_type): +            reason = reason.encode("ascii", "strict")          if not isinstance(headers, nheaders.Headers):              headers = nheaders.Headers(headers) +        if isinstance(content, six.text_type): +            raise ValueError("Content must be bytes, not {}".format(type(content).__name__))          self.http_version = http_version          self.status_code = status_code | 
