diff options
author | Aldo Cortesi <aldo@nullcube.com> | 2016-05-21 10:15:37 +1200 |
---|---|---|
committer | Aldo Cortesi <aldo@nullcube.com> | 2016-05-21 10:15:37 +1200 |
commit | 96d8ec1ee33b076a472afc3053fdd8256559fcc3 (patch) | |
tree | 933549b94c497b70eb6165f90bef191eebca4cc7 /netlib/http/message.py | |
parent | 84144ca0c635f4a42c8ba8a13e779fe127a81d45 (diff) | |
parent | b538138ead1dc8550f2d4e4a3f30ff70abb95f53 (diff) | |
download | mitmproxy-96d8ec1ee33b076a472afc3053fdd8256559fcc3.tar.gz mitmproxy-96d8ec1ee33b076a472afc3053fdd8256559fcc3.tar.bz2 mitmproxy-96d8ec1ee33b076a472afc3053fdd8256559fcc3.zip |
Merge branch 'multidict' of https://github.com/mhils/mitmproxy into mhils-multidict
Diffstat (limited to 'netlib/http/message.py')
-rw-r--r-- | netlib/http/message.py | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/netlib/http/message.py b/netlib/http/message.py index da9681a0..db4054b1 100644 --- a/netlib/http/message.py +++ b/netlib/http/message.py @@ -4,6 +4,7 @@ import warnings import six +from ..multidict import MultiDict from .headers import Headers from .. import encoding, utils @@ -235,3 +236,72 @@ class decoded(object): def __exit__(self, type, value, tb): if self.ce: self.message.encode(self.ce) + + +class MultiDictView(MultiDict): + """ + Some parts in HTTP (Cookies, URL query strings, ...) require a specific data structure: A MultiDict. + It behaves mostly like an ordered dict but it can have several values for the same key. + + The MultiDictView provides a MultiDict *view* on an :py:class:`Request` or :py:class:`Response`. + That is, it represents a part of the request as a MultiDict, but doesn't contain state/data themselves. + + For example, ``request.cookies`` provides a view on the ``Cookie: ...`` header. + Any change to ``request.cookies`` will also modify the ``Cookie`` header. + Any change to the ``Cookie`` header will also modify ``request.cookies``. + + Example: + + .. code-block:: python + + # Cookies are represented as a MultiDict. + >>> request.cookies + MultiDictView[("name", "value"), ("a", "false"), ("a", "42")] + + # MultiDicts mostly behave like a normal dict. + >>> request.cookies["name"] + "value" + + # If there is more than one value, only the first value is returned. + >>> request.cookies["a"] + "false" + + # `.get_all(key)` returns a list of all values. + >>> request.cookies.get_all("a") + ["false", "42"] + + # Changes to the headers are immediately reflected in the cookies. + >>> request.cookies + MultiDictView[("name", "value"), ...] + >>> del request.headers["Cookie"] + >>> request.cookies + MultiDictView[] # empty now + """ + + def __init__(self, attr, message): + if False: # pragma: no cover + # We do not want to call the parent constructor here as that + # would cause an unnecessary parse/unparse pass. + # This is here to silence linters. Message + super(MultiDictView, self).__init__(None) + self._attr = attr + self._message = message # type: Message + + @staticmethod + def _kconv(key): + # All request-attributes are case-sensitive. + return key + + @staticmethod + def _reduce_values(values): + # We just return the first element if + # multiple elements exist with the same key. + return values[0] + + @property + def fields(self): + return getattr(self._message, "_" + self._attr) + + @fields.setter + def fields(self, value): + setattr(self._message, self._attr, value) |