aboutsummaryrefslogtreecommitdiffstats
path: root/netlib
diff options
context:
space:
mode:
Diffstat (limited to 'netlib')
-rw-r--r--netlib/http/__init__.py2
-rw-r--r--netlib/http/authentication.py (renamed from netlib/http_auth.py)5
-rw-r--r--netlib/http/cookies.py (renamed from netlib/http_cookies.py)8
-rw-r--r--netlib/http/exceptions.py9
-rw-r--r--netlib/http/http1/__init__.py1
-rw-r--r--netlib/http/http1/protocol.py (renamed from netlib/http.py)95
-rw-r--r--netlib/http/http2/__init__.py (renamed from netlib/http2/__init__.py)0
-rw-r--r--netlib/http/http2/frame.py (renamed from netlib/http2/frame.py)0
-rw-r--r--netlib/http/http2/protocol.py (renamed from netlib/http2/protocol.py)0
-rw-r--r--netlib/http/semantics.py94
-rw-r--r--netlib/http/status_codes.py (renamed from netlib/http_status.py)0
-rw-r--r--netlib/http/user_agents.py (renamed from netlib/http_uastrings.py)0
-rw-r--r--netlib/http_semantics.py23
-rw-r--r--netlib/websockets/frame.py2
-rw-r--r--netlib/websockets/protocol.py2
15 files changed, 130 insertions, 111 deletions
diff --git a/netlib/http/__init__.py b/netlib/http/__init__.py
new file mode 100644
index 00000000..9b4b0e6b
--- /dev/null
+++ b/netlib/http/__init__.py
@@ -0,0 +1,2 @@
+from exceptions import *
+from semantics import *
diff --git a/netlib/http_auth.py b/netlib/http/authentication.py
index adab4aed..26e3c2c4 100644
--- a/netlib/http_auth.py
+++ b/netlib/http/authentication.py
@@ -1,6 +1,7 @@
from __future__ import (absolute_import, print_function, division)
from argparse import Action, ArgumentTypeError
-from . import http
+
+from .. import http
class NullProxyAuth(object):
@@ -46,7 +47,7 @@ class BasicProxyAuth(NullProxyAuth):
auth_value = headers.get(self.AUTH_HEADER, [])
if not auth_value:
return False
- parts = http.parse_http_basic_auth(auth_value[0])
+ parts = http.http1.parse_http_basic_auth(auth_value[0])
if not parts:
return False
scheme, username, password = parts
diff --git a/netlib/http_cookies.py b/netlib/http/cookies.py
index e91ee5c0..b77e3503 100644
--- a/netlib/http_cookies.py
+++ b/netlib/http/cookies.py
@@ -1,3 +1,7 @@
+import re
+
+from .. import odict
+
"""
A flexible module for cookie parsing and manipulation.
@@ -22,10 +26,6 @@ variants. Serialization follows RFC6265.
# TODO
# - Disallow LHS-only Cookie values
-import re
-
-import odict
-
def _read_until(s, start, term):
"""
diff --git a/netlib/http/exceptions.py b/netlib/http/exceptions.py
new file mode 100644
index 00000000..8a2bbebc
--- /dev/null
+++ b/netlib/http/exceptions.py
@@ -0,0 +1,9 @@
+class HttpError(Exception):
+
+ def __init__(self, code, message):
+ super(HttpError, self).__init__(message)
+ self.code = code
+
+
+class HttpErrorConnClosed(HttpError):
+ pass
diff --git a/netlib/http/http1/__init__.py b/netlib/http/http1/__init__.py
new file mode 100644
index 00000000..6b5043af
--- /dev/null
+++ b/netlib/http/http1/__init__.py
@@ -0,0 +1 @@
+from protocol import *
diff --git a/netlib/http.py b/netlib/http/http1/protocol.py
index 073e9a3f..0f7a0bd3 100644
--- a/netlib/http.py
+++ b/netlib/http/http1/protocol.py
@@ -1,37 +1,13 @@
from __future__ import (absolute_import, print_function, division)
+import binascii
import collections
import string
-import urlparse
-import binascii
import sys
-from . import odict, utils, tcp, http_semantics, http_status
-
-
-class HttpError(Exception):
-
- def __init__(self, code, message):
- super(HttpError, self).__init__(message)
- self.code = code
-
-
-class HttpErrorConnClosed(HttpError):
- pass
-
-
-def _is_valid_port(port):
- if not 0 <= port <= 65535:
- return False
- return True
-
+import urlparse
-def _is_valid_host(host):
- try:
- host.decode("idna")
- except ValueError:
- return False
- if "\0" in host:
- return None
- return True
+from netlib import odict, utils, tcp, http
+from .. import status_codes
+from ..exceptions import *
def get_request_line(fp):
@@ -44,51 +20,6 @@ def get_request_line(fp):
line = fp.readline()
return line
-
-def parse_url(url):
- """
- Returns a (scheme, host, port, path) tuple, or None on error.
-
- Checks that:
- port is an integer 0-65535
- host is a valid IDNA-encoded hostname with no null-bytes
- path is valid ASCII
- """
- try:
- scheme, netloc, path, params, query, fragment = urlparse.urlparse(url)
- except ValueError:
- return None
- if not scheme:
- return None
- if '@' in netloc:
- # FIXME: Consider what to do with the discarded credentials here Most
- # probably we should extend the signature to return these as a separate
- # value.
- _, netloc = string.rsplit(netloc, '@', maxsplit=1)
- if ':' in netloc:
- host, port = string.rsplit(netloc, ':', maxsplit=1)
- try:
- port = int(port)
- except ValueError:
- return None
- else:
- host = netloc
- if scheme == "https":
- port = 443
- else:
- port = 80
- path = urlparse.urlunparse(('', '', path, params, query, fragment))
- if not path.startswith("/"):
- path = "/" + path
- if not _is_valid_host(host):
- return None
- if not utils.isascii(path):
- return None
- if not _is_valid_port(port):
- return None
- return scheme, host, port, path
-
-
def read_headers(fp):
"""
Read a set of headers from a file pointer. Stop once a blank line is
@@ -193,6 +124,7 @@ def parse_http_protocol(s):
def parse_http_basic_auth(s):
+ # TODO: check if this is HTTP/1 only - otherwise move it to netlib.http.semantics
words = s.split()
if len(words) != 2:
return None
@@ -208,6 +140,7 @@ def parse_http_basic_auth(s):
def assemble_http_basic_auth(scheme, username, password):
+ # TODO: check if this is HTTP/1 only - otherwise move it to netlib.http.semantics
v = binascii.b2a_base64(username + ":" + password)
return scheme + " " + v
@@ -245,9 +178,9 @@ def parse_init_connect(line):
port = int(port)
except ValueError:
return None
- if not _is_valid_port(port):
+ if not http.is_valid_port(port):
return None
- if not _is_valid_host(host):
+ if not http.is_valid_host(host):
return None
return host, port, httpversion
@@ -258,7 +191,7 @@ def parse_init_proxy(line):
return None
method, url, httpversion = v
- parts = parse_url(url)
+ parts = http.parse_url(url)
if not parts:
return None
scheme, host, port, path = parts
@@ -421,6 +354,7 @@ def expected_http_body_size(headers, is_request, request_method, response_code):
return -1
+# TODO: make this a regular class - just like Response
Request = collections.namedtuple(
"Request",
[
@@ -529,7 +463,7 @@ def read_request(rfile, include_body=True, body_size_limit=None, wfile=None):
def read_response(rfile, request_method, body_size_limit, include_body=True):
"""
- Return an (httpversion, code, msg, headers, content) tuple.
+ Returns an http.Response
By default, both response header and body are read.
If include_body=False is specified, content may be one of the
@@ -538,6 +472,7 @@ def read_response(rfile, request_method, body_size_limit, include_body=True):
- "", if the response must not have a response body (e.g. it's a
response to a HEAD request)
"""
+
line = rfile.readline()
# Possible leftover from previous message
if line == "\r\n" or line == "\n":
@@ -568,7 +503,7 @@ def read_response(rfile, request_method, body_size_limit, include_body=True):
# if include_body==False then a None content means the body should be
# read separately
content = None
- return http_semantics.Response(httpversion, code, msg, headers, content)
+ return http.Response(httpversion, code, msg, headers, content)
def request_preamble(method, resource, http_major="1", http_minor="1"):
@@ -579,5 +514,5 @@ def request_preamble(method, resource, http_major="1", http_minor="1"):
def response_preamble(code, message=None, http_major="1", http_minor="1"):
if message is None:
- message = http_status.RESPONSES.get(code)
+ message = status_codes.RESPONSES.get(code)
return 'HTTP/%s.%s %s %s' % (http_major, http_minor, code, message)
diff --git a/netlib/http2/__init__.py b/netlib/http/http2/__init__.py
index 5acf7696..5acf7696 100644
--- a/netlib/http2/__init__.py
+++ b/netlib/http/http2/__init__.py
diff --git a/netlib/http2/frame.py b/netlib/http/http2/frame.py
index f7e60471..f7e60471 100644
--- a/netlib/http2/frame.py
+++ b/netlib/http/http2/frame.py
diff --git a/netlib/http2/protocol.py b/netlib/http/http2/protocol.py
index 8e5f5429..8e5f5429 100644
--- a/netlib/http2/protocol.py
+++ b/netlib/http/http2/protocol.py
diff --git a/netlib/http/semantics.py b/netlib/http/semantics.py
new file mode 100644
index 00000000..e7e84fe3
--- /dev/null
+++ b/netlib/http/semantics.py
@@ -0,0 +1,94 @@
+from __future__ import (absolute_import, print_function, division)
+import binascii
+import collections
+import string
+import sys
+import urlparse
+
+from .. import utils
+
+class Response(object):
+
+ def __init__(
+ self,
+ httpversion,
+ status_code,
+ msg,
+ headers,
+ content,
+ sslinfo=None,
+ ):
+ self.httpversion = httpversion
+ self.status_code = status_code
+ self.msg = msg
+ self.headers = headers
+ self.content = content
+ self.sslinfo = sslinfo
+
+ def __eq__(self, other):
+ return self.__dict__ == other.__dict__
+
+ def __repr__(self):
+ return "Response(%s - %s)" % (self.status_code, self.msg)
+
+
+
+def is_valid_port(port):
+ if not 0 <= port <= 65535:
+ return False
+ return True
+
+
+def is_valid_host(host):
+ try:
+ host.decode("idna")
+ except ValueError:
+ return False
+ if "\0" in host:
+ return None
+ return True
+
+
+
+def parse_url(url):
+ """
+ Returns a (scheme, host, port, path) tuple, or None on error.
+
+ Checks that:
+ port is an integer 0-65535
+ host is a valid IDNA-encoded hostname with no null-bytes
+ path is valid ASCII
+ """
+ try:
+ scheme, netloc, path, params, query, fragment = urlparse.urlparse(url)
+ except ValueError:
+ return None
+ if not scheme:
+ return None
+ if '@' in netloc:
+ # FIXME: Consider what to do with the discarded credentials here Most
+ # probably we should extend the signature to return these as a separate
+ # value.
+ _, netloc = string.rsplit(netloc, '@', maxsplit=1)
+ if ':' in netloc:
+ host, port = string.rsplit(netloc, ':', maxsplit=1)
+ try:
+ port = int(port)
+ except ValueError:
+ return None
+ else:
+ host = netloc
+ if scheme == "https":
+ port = 443
+ else:
+ port = 80
+ path = urlparse.urlunparse(('', '', path, params, query, fragment))
+ if not path.startswith("/"):
+ path = "/" + path
+ if not is_valid_host(host):
+ return None
+ if not utils.isascii(path):
+ return None
+ if not is_valid_port(port):
+ return None
+ return scheme, host, port, path
diff --git a/netlib/http_status.py b/netlib/http/status_codes.py
index dc09f465..dc09f465 100644
--- a/netlib/http_status.py
+++ b/netlib/http/status_codes.py
diff --git a/netlib/http_uastrings.py b/netlib/http/user_agents.py
index e8681908..e8681908 100644
--- a/netlib/http_uastrings.py
+++ b/netlib/http/user_agents.py
diff --git a/netlib/http_semantics.py b/netlib/http_semantics.py
deleted file mode 100644
index e8313e3c..00000000
--- a/netlib/http_semantics.py
+++ /dev/null
@@ -1,23 +0,0 @@
-class Response(object):
-
- def __init__(
- self,
- httpversion,
- status_code,
- msg,
- headers,
- content,
- sslinfo=None,
- ):
- self.httpversion = httpversion
- self.status_code = status_code
- self.msg = msg
- self.headers = headers
- self.content = content
- self.sslinfo = sslinfo
-
- def __eq__(self, other):
- return self.__dict__ == other.__dict__
-
- def __repr__(self):
- return "Response(%s - %s)" % (self.status_code, self.msg)
diff --git a/netlib/websockets/frame.py b/netlib/websockets/frame.py
index d41059fa..49d8ee10 100644
--- a/netlib/websockets/frame.py
+++ b/netlib/websockets/frame.py
@@ -6,7 +6,7 @@ import struct
import io
from .protocol import Masker
-from .. import utils, odict, tcp
+from netlib import utils, odict, tcp
DEFAULT = object()
diff --git a/netlib/websockets/protocol.py b/netlib/websockets/protocol.py
index dcab53fb..29b4db3d 100644
--- a/netlib/websockets/protocol.py
+++ b/netlib/websockets/protocol.py
@@ -5,7 +5,7 @@ import os
import struct
import io
-from .. import utils, odict, tcp
+from netlib import utils, odict, tcp
# Colleciton of utility functions that implement small portions of the RFC6455
# WebSockets Protocol Useful for building WebSocket clients and servers.