aboutsummaryrefslogtreecommitdiffstats
path: root/netlib
diff options
context:
space:
mode:
authorMaximilian Hils <git@maximilianhils.com>2015-09-17 16:31:50 +0200
committerMaximilian Hils <git@maximilianhils.com>2015-09-17 16:31:50 +0200
commitd798ed955dab4681a5285024b3648b1a3f13c24e (patch)
treea95d96953cd7688451c3a515e4b31f0465d6a7d3 /netlib
parent8d71059d77c2dd1d9858d7971dd0b6b4387ed9f4 (diff)
downloadmitmproxy-d798ed955dab4681a5285024b3648b1a3f13c24e.tar.gz
mitmproxy-d798ed955dab4681a5285024b3648b1a3f13c24e.tar.bz2
mitmproxy-d798ed955dab4681a5285024b3648b1a3f13c24e.zip
python3++
Diffstat (limited to 'netlib')
-rw-r--r--netlib/encoding.py20
-rw-r--r--netlib/http/models.py48
-rw-r--r--netlib/odict.py25
-rw-r--r--netlib/tutils.py4
-rw-r--r--netlib/utils.py22
5 files changed, 51 insertions, 68 deletions
diff --git a/netlib/encoding.py b/netlib/encoding.py
index 06830f2c..8ac59905 100644
--- a/netlib/encoding.py
+++ b/netlib/encoding.py
@@ -5,28 +5,30 @@ from __future__ import absolute_import
from io import BytesIO
import gzip
import zlib
+from .utils import always_byte_args
-__ALL__ = ["ENCODINGS"]
-ENCODINGS = {"identity", "gzip", "deflate"}
+ENCODINGS = {b"identity", b"gzip", b"deflate"}
+@always_byte_args("ascii", "ignore")
def decode(e, content):
encoding_map = {
- "identity": identity,
- "gzip": decode_gzip,
- "deflate": decode_deflate,
+ b"identity": identity,
+ b"gzip": decode_gzip,
+ b"deflate": decode_deflate,
}
if e not in encoding_map:
return None
return encoding_map[e](content)
+@always_byte_args("ascii", "ignore")
def encode(e, content):
encoding_map = {
- "identity": identity,
- "gzip": encode_gzip,
- "deflate": encode_deflate,
+ b"identity": identity,
+ b"gzip": encode_gzip,
+ b"deflate": encode_deflate,
}
if e not in encoding_map:
return None
@@ -80,3 +82,5 @@ def encode_deflate(content):
Returns compressed content, always including zlib header and checksum.
"""
return zlib.compress(content)
+
+__all__ = ["ENCODINGS", "encode", "decode"]
diff --git a/netlib/http/models.py b/netlib/http/models.py
index 54b8b112..bc681de3 100644
--- a/netlib/http/models.py
+++ b/netlib/http/models.py
@@ -136,7 +136,7 @@ class Headers(MutableMapping, object):
def __len__(self):
return len(set(name.lower() for name, _ in self.fields))
- #__hash__ = object.__hash__
+ # __hash__ = object.__hash__
def _index(self, name):
name = name.lower()
@@ -227,11 +227,11 @@ class Request(Message):
# This list is adopted legacy code.
# We probably don't need to strip off keep-alive.
_headers_to_strip_off = [
- b'Proxy-Connection',
- b'Keep-Alive',
- b'Connection',
- b'Transfer-Encoding',
- b'Upgrade',
+ 'Proxy-Connection',
+ 'Keep-Alive',
+ 'Connection',
+ 'Transfer-Encoding',
+ 'Upgrade',
]
def __init__(
@@ -275,8 +275,8 @@ class Request(Message):
response. That is, we remove ETags and If-Modified-Since headers.
"""
delheaders = [
- b"if-modified-since",
- b"if-none-match",
+ b"If-Modified-Since",
+ b"If-None-Match",
]
for i in delheaders:
self.headers.pop(i, None)
@@ -286,16 +286,16 @@ class Request(Message):
Modifies this request to remove headers that will compress the
resource's data.
"""
- self.headers[b"accept-encoding"] = b"identity"
+ self.headers["Accept-Encoding"] = b"identity"
def constrain_encoding(self):
"""
Limits the permissible Accept-Encoding values, based on what we can
decode appropriately.
"""
- accept_encoding = self.headers.get(b"accept-encoding")
+ accept_encoding = self.headers.get(b"Accept-Encoding")
if accept_encoding:
- self.headers[b"accept-encoding"] = (
+ self.headers["Accept-Encoding"] = (
', '.join(
e
for e in encoding.ENCODINGS
@@ -316,9 +316,9 @@ class Request(Message):
indicates non-form data.
"""
if self.body:
- if HDR_FORM_URLENCODED in self.headers.get("content-type","").lower():
+ if HDR_FORM_URLENCODED in self.headers.get("Content-Type", "").lower():
return self.get_form_urlencoded()
- elif HDR_FORM_MULTIPART in self.headers.get("content-type","").lower():
+ elif HDR_FORM_MULTIPART in self.headers.get("Content-Type", "").lower():
return self.get_form_multipart()
return ODict([])
@@ -328,12 +328,12 @@ class Request(Message):
Returns an empty ODict if there is no data or the content-type
indicates non-form data.
"""
- if self.body and HDR_FORM_URLENCODED in self.headers.get("content-type","").lower():
+ if self.body and HDR_FORM_URLENCODED in self.headers.get("Content-Type", "").lower():
return ODict(utils.urldecode(self.body))
return ODict([])
def get_form_multipart(self):
- if self.body and HDR_FORM_MULTIPART in self.headers.get("content-type","").lower():
+ if self.body and HDR_FORM_MULTIPART in self.headers.get("Content-Type", "").lower():
return ODict(
utils.multipartdecode(
self.headers,
@@ -405,9 +405,9 @@ class Request(Message):
but not the resolved name. This is disabled by default, as an
attacker may spoof the host header to confuse an analyst.
"""
- if hostheader and b"Host" in self.headers:
+ if hostheader and "Host" in self.headers:
try:
- return self.headers[b"Host"].decode("idna")
+ return self.headers["Host"].decode("idna")
except ValueError:
pass
if self.host:
@@ -426,7 +426,7 @@ class Request(Message):
Returns a possibly empty netlib.odict.ODict object.
"""
ret = ODict()
- for i in self.headers.get_all("cookie"):
+ for i in self.headers.get_all("Cookie"):
ret.extend(cookies.parse_cookie_header(i))
return ret
@@ -468,9 +468,9 @@ class Request(Message):
class Response(Message):
_headers_to_strip_off = [
- b'Proxy-Connection',
- b'Alternate-Protocol',
- b'Alt-Svc',
+ 'Proxy-Connection',
+ 'Alternate-Protocol',
+ 'Alt-Svc',
]
def __init__(
@@ -498,7 +498,7 @@ class Response(Message):
return "<Response: {status_code} {msg} ({contenttype}, {size})>".format(
status_code=self.status_code,
msg=self.msg,
- contenttype=self.headers.get("content-type", "unknown content type"),
+ contenttype=self.headers.get("Content-Type", "unknown content type"),
size=size)
def get_cookies(self):
@@ -511,7 +511,7 @@ class Response(Message):
attributes (e.g. HTTPOnly) are indicated by a Null value.
"""
ret = []
- for header in self.headers.get_all(b"set-cookie"):
+ for header in self.headers.get_all("Set-Cookie"):
v = cookies.parse_set_cookie_header(header)
if v:
name, value, attrs = v
@@ -534,4 +534,4 @@ class Response(Message):
i[1][1]
)
)
- self.headers.set_all(b"Set-Cookie", values)
+ self.headers.set_all("Set-Cookie", values)
diff --git a/netlib/odict.py b/netlib/odict.py
index 11d5d52a..1124b23a 100644
--- a/netlib/odict.py
+++ b/netlib/odict.py
@@ -1,6 +1,7 @@
from __future__ import (absolute_import, print_function, division)
import re
import copy
+import six
def safe_subn(pattern, repl, target, *args, **kwargs):
@@ -67,10 +68,10 @@ class ODict(object):
Sets the values for key k. If there are existing values for this
key, they are cleared.
"""
- if isinstance(valuelist, basestring):
+ if isinstance(valuelist, six.text_type) or isinstance(valuelist, six.binary_type):
raise ValueError(
"Expected list of values instead of string. "
- "Example: odict['Host'] = ['www.example.com']"
+ "Example: odict[b'Host'] = [b'www.example.com']"
)
kc = self._kconv(k)
new = []
@@ -134,13 +135,6 @@ class ODict(object):
def __repr__(self):
return repr(self.lst)
- def format(self):
- elements = []
- for itm in self.lst:
- elements.append(itm[0] + ": " + str(itm[1]))
- elements.append("")
- return "\r\n".join(elements)
-
def in_any(self, key, value, caseless=False):
"""
Do any of the values matching key contain value?
@@ -156,19 +150,6 @@ class ODict(object):
return True
return False
- def match_re(self, expr):
- """
- Match the regular expression against each (key, value) pair. For
- each pair a string of the following format is matched against:
-
- "key: value"
- """
- for k, v in self.lst:
- s = "%s: %s" % (k, v)
- if re.search(expr, s):
- return True
- return False
-
def replace(self, pattern, repl, *args, **kwargs):
"""
Replaces a regular expression pattern with repl in both keys and
diff --git a/netlib/tutils.py b/netlib/tutils.py
index b69495a3..746e1488 100644
--- a/netlib/tutils.py
+++ b/netlib/tutils.py
@@ -123,9 +123,7 @@ def tresp(**kwargs):
status_code=200,
msg=b"OK",
headers=Headers(header_response=b"svalue"),
- body=b"message",
- timestamp_start=time.time(),
- timestamp_end=time.time()
+ body=b"message"
)
default.update(kwargs)
return Response(**default)
diff --git a/netlib/utils.py b/netlib/utils.py
index 14b428d7..6fed44b6 100644
--- a/netlib/utils.py
+++ b/netlib/utils.py
@@ -246,7 +246,7 @@ def unparse_url(scheme, host, port, path=""):
"""
Returns a URL string, constructed from the specified compnents.
"""
- return "%s://%s%s" % (scheme, hostport(scheme, host, port), path)
+ return b"%s://%s%s" % (scheme, hostport(scheme, host, port), path)
def urlencode(s):
@@ -295,7 +295,7 @@ def multipartdecode(headers, content):
"""
Takes a multipart boundary encoded string and returns list of (key, value) tuples.
"""
- v = headers.get("content-type")
+ v = headers.get(b"Content-Type")
if v:
v = parse_content_type(v)
if not v:
@@ -304,33 +304,33 @@ def multipartdecode(headers, content):
if not boundary:
return []
- rx = re.compile(r'\bname="([^"]+)"')
+ rx = re.compile(br'\bname="([^"]+)"')
r = []
- for i in content.split("--" + boundary):
+ for i in content.split(b"--" + boundary):
parts = i.splitlines()
- if len(parts) > 1 and parts[0][0:2] != "--":
+ if len(parts) > 1 and parts[0][0:2] != b"--":
match = rx.search(parts[1])
if match:
key = match.group(1)
- value = "".join(parts[3 + parts[2:].index(""):])
+ value = b"".join(parts[3 + parts[2:].index(b""):])
r.append((key, value))
return r
return []
-def always_bytes(unicode_or_bytes, encoding):
+def always_bytes(unicode_or_bytes, *encode_args):
if isinstance(unicode_or_bytes, six.text_type):
- return unicode_or_bytes.encode(encoding)
+ return unicode_or_bytes.encode(*encode_args)
return unicode_or_bytes
-def always_byte_args(encoding):
+def always_byte_args(*encode_args):
"""Decorator that transparently encodes all arguments passed as unicode"""
def decorator(fun):
def _fun(*args, **kwargs):
- args = [always_bytes(arg, encoding) for arg in args]
- kwargs = {k: always_bytes(v, encoding) for k, v in six.iteritems(kwargs)}
+ args = [always_bytes(arg, *encode_args) for arg in args]
+ kwargs = {k: always_bytes(v, *encode_args) for k, v in six.iteritems(kwargs)}
return fun(*args, **kwargs)
return _fun
return decorator