Add HTTP version to flow.Request

This is a serialization format change, that makes us incompatible with previous
versions.
This commit is contained in:
Aldo Cortesi 2012-06-10 10:46:22 +12:00
parent a3b47e0cb5
commit 55ddf853cd
5 changed files with 41 additions and 20 deletions

View File

@ -346,9 +346,10 @@ class Request(HTTPMsg):
timestamp: Seconds since the epoch timestamp: Seconds since the epoch
method: HTTP method method: HTTP method
""" """
def __init__(self, client_conn, host, port, scheme, method, path, headers, content, timestamp=None): def __init__(self, client_conn, httpversion, host, port, scheme, method, path, headers, content, timestamp=None):
assert isinstance(headers, ODictCaseless) assert isinstance(headers, ODictCaseless)
self.client_conn = client_conn self.client_conn = client_conn
self.httpversion = httpversion
self.host, self.port, self.scheme = host, port, scheme self.host, self.port, self.scheme = host, port, scheme
self.method, self.path, self.headers, self.content = method, path, headers, content self.method, self.path, self.headers, self.content = method, path, headers, content
self.timestamp = timestamp or utils.timestamp() self.timestamp = timestamp or utils.timestamp()
@ -420,6 +421,7 @@ class Request(HTTPMsg):
def _get_state(self): def _get_state(self):
return dict( return dict(
client_conn = self.client_conn._get_state() if self.client_conn else None, client_conn = self.client_conn._get_state() if self.client_conn else None,
httpversion = self.httpversion,
host = self.host, host = self.host,
port = self.port, port = self.port,
scheme = self.scheme, scheme = self.scheme,
@ -434,6 +436,7 @@ class Request(HTTPMsg):
def _from_state(klass, state): def _from_state(klass, state):
return klass( return klass(
ClientConnect._from_state(state["client_conn"]), ClientConnect._from_state(state["client_conn"]),
tuple(state["httpversion"]),
str(state["host"]), str(state["host"]),
state["port"], state["port"],
str(state["scheme"]), str(state["scheme"]),
@ -523,8 +526,8 @@ class Request(HTTPMsg):
""" """
if self.content == CONTENT_MISSING: if self.content == CONTENT_MISSING:
return None return None
FMT = '%s %s HTTP/1.1\r\n%s\r\n%s' FMT = '%s %s HTTP/%s.%s\r\n%s\r\n%s'
FMT_PROXY = '%s %s://%s:%s%s HTTP/1.1\r\n%s\r\n%s' FMT_PROXY = '%s %s://%s:%s%s HTTP/%s.%s\r\n%s\r\n%s'
headers = self.headers.copy() headers = self.headers.copy()
utils.del_all( utils.del_all(
@ -547,9 +550,26 @@ class Request(HTTPMsg):
if self.close: if self.close:
headers["connection"] = ["close"] headers["connection"] = ["close"]
if not _proxy: if not _proxy:
return FMT % (self.method, self.path, str(headers), content) return FMT % (
self.method,
self.path,
self.httpversion[0],
self.httpversion[1],
str(headers),
content
)
else: else:
return FMT_PROXY % (self.method, self.scheme, self.host, self.port, self.path, str(headers), content) return FMT_PROXY % (
self.method,
self.scheme,
self.host,
self.port,
self.path,
self.httpversion[0],
self.httpversion[1],
str(headers),
content
)
def replace(self, pattern, repl, *args, **kwargs): def replace(self, pattern, repl, *args, **kwargs):
""" """

View File

@ -465,7 +465,7 @@ class ProxyHandler(SocketServer.StreamRequestHandler):
method, path, httpversion = parse_init_http(line) method, path, httpversion = parse_init_http(line)
headers = read_headers(self.rfile) headers = read_headers(self.rfile)
content = self.read_contents(client_conn, headers, httpversion) content = self.read_contents(client_conn, headers, httpversion)
return flow.Request(client_conn, host, port, "http", method, path, headers, content) return flow.Request(client_conn, httpversion, host, port, "http", method, path, headers, content)
elif line.startswith("CONNECT"): elif line.startswith("CONNECT"):
host, port, httpversion = parse_init_connect(line) host, port, httpversion = parse_init_connect(line)
# FIXME: Discard additional headers sent to the proxy. Should I expose # FIXME: Discard additional headers sent to the proxy. Should I expose
@ -486,12 +486,12 @@ class ProxyHandler(SocketServer.StreamRequestHandler):
method, path, httpversion = parse_init_http(self.rfile.readline(line)) method, path, httpversion = parse_init_http(self.rfile.readline(line))
headers = read_headers(self.rfile) headers = read_headers(self.rfile)
content = self.read_contents(client_conn, headers, httpversion) content = self.read_contents(client_conn, headers, httpversion)
return flow.Request(client_conn, host, port, "https", method, path, headers, content) return flow.Request(client_conn, httpversion, host, port, "https", method, path, headers, content)
else: else:
method, scheme, host, port, path, httpversion = parse_init_proxy(line) method, scheme, host, port, path, httpversion = parse_init_proxy(line)
headers = read_headers(self.rfile) headers = read_headers(self.rfile)
content = self.read_contents(client_conn, headers, httpversion) content = self.read_contents(client_conn, headers, httpversion)
return flow.Request(client_conn, host, port, scheme, method, path, headers, content) return flow.Request(client_conn, httpversion, host, port, scheme, method, path, headers, content)
def send_response(self, response): def send_response(self, response):
d = response._assemble() d = response._assemble()

View File

@ -77,6 +77,7 @@ class TestMatching:
headers["header"] = ["qvalue"] headers["header"] = ["qvalue"]
req = flow.Request( req = flow.Request(
conn, conn,
(1, 1),
"host", "host",
80, 80,
"http", "http",

View File

@ -686,7 +686,7 @@ class TestRequest:
h = flow.ODictCaseless() h = flow.ODictCaseless()
h["test"] = ["test"] h["test"] = ["test"]
c = flow.ClientConnect(("addr", 2222)) c = flow.ClientConnect(("addr", 2222))
r = flow.Request(c, "host", 22, "https", "GET", "/", h, "content") r = flow.Request(c, (1, 1), "host", 22, "https", "GET", "/", h, "content")
u = r.get_url() u = r.get_url()
assert r.set_url(u) assert r.set_url(u)
assert not r.set_url("") assert not r.set_url("")
@ -711,7 +711,7 @@ class TestRequest:
h = flow.ODictCaseless() h = flow.ODictCaseless()
h["content-type"] = [flow.HDR_FORM_URLENCODED] h["content-type"] = [flow.HDR_FORM_URLENCODED]
d = flow.ODict([("one", "two"), ("three", "four")]) d = flow.ODict([("one", "two"), ("three", "four")])
r = flow.Request(None, "host", 22, "https", "GET", "/", h, utils.urlencode(d.lst)) r = flow.Request(None, (1, 1), "host", 22, "https", "GET", "/", h, utils.urlencode(d.lst))
assert r.get_form_urlencoded() == d assert r.get_form_urlencoded() == d
d = flow.ODict([("x", "y")]) d = flow.ODict([("x", "y")])
@ -724,19 +724,19 @@ class TestRequest:
def test_getset_query(self): def test_getset_query(self):
h = flow.ODictCaseless() h = flow.ODictCaseless()
r = flow.Request(None, "host", 22, "https", "GET", "/foo?x=y&a=b", h, "content") r = flow.Request(None, (1, 1), "host", 22, "https", "GET", "/foo?x=y&a=b", h, "content")
q = r.get_query() q = r.get_query()
assert q.lst == [("x", "y"), ("a", "b")] assert q.lst == [("x", "y"), ("a", "b")]
r = flow.Request(None, "host", 22, "https", "GET", "/", h, "content") r = flow.Request(None, (1, 1), "host", 22, "https", "GET", "/", h, "content")
q = r.get_query() q = r.get_query()
assert not q assert not q
r = flow.Request(None, "host", 22, "https", "GET", "/?adsfa", h, "content") r = flow.Request(None, (1, 1), "host", 22, "https", "GET", "/?adsfa", h, "content")
q = r.get_query() q = r.get_query()
assert not q assert not q
r = flow.Request(None, "host", 22, "https", "GET", "/foo?x=y&a=b", h, "content") r = flow.Request(None, (1, 1), "host", 22, "https", "GET", "/foo?x=y&a=b", h, "content")
assert r.get_query() assert r.get_query()
r.set_query(flow.ODict([])) r.set_query(flow.ODict([]))
assert not r.get_query() assert not r.get_query()
@ -746,7 +746,7 @@ class TestRequest:
def test_anticache(self): def test_anticache(self):
h = flow.ODictCaseless() h = flow.ODictCaseless()
r = flow.Request(None, "host", 22, "https", "GET", "/", h, "content") r = flow.Request(None, (1, 1), "host", 22, "https", "GET", "/", h, "content")
h["if-modified-since"] = ["test"] h["if-modified-since"] = ["test"]
h["if-none-match"] = ["test"] h["if-none-match"] = ["test"]
r.anticache() r.anticache()
@ -757,7 +757,7 @@ class TestRequest:
h = flow.ODictCaseless() h = flow.ODictCaseless()
h["test"] = ["test"] h["test"] = ["test"]
c = flow.ClientConnect(("addr", 2222)) c = flow.ClientConnect(("addr", 2222))
r = flow.Request(c, "host", 22, "https", "GET", "/", h, "content") r = flow.Request(c, (1, 1), "host", 22, "https", "GET", "/", h, "content")
state = r._get_state() state = r._get_state()
assert flow.Request._from_state(state) == r assert flow.Request._from_state(state) == r
@ -765,7 +765,7 @@ class TestRequest:
state = r._get_state() state = r._get_state()
assert flow.Request._from_state(state) == r assert flow.Request._from_state(state) == r
r2 = flow.Request(c, "testing", 20, "http", "PUT", "/foo", h, "test") r2 = flow.Request(c, (1, 1), "testing", 20, "http", "PUT", "/foo", h, "test")
assert not r == r2 assert not r == r2
r._load_state(r2._get_state()) r._load_state(r2._get_state())
assert r == r2 assert r == r2
@ -825,7 +825,7 @@ class TestResponse:
h = flow.ODictCaseless() h = flow.ODictCaseless()
h["test"] = ["test"] h["test"] = ["test"]
c = flow.ClientConnect(("addr", 2222)) c = flow.ClientConnect(("addr", 2222))
req = flow.Request(c, "host", 22, "https", "GET", "/", h, "content") req = flow.Request(c, (1, 1), "host", 22, "https", "GET", "/", h, "content")
resp = flow.Response(req, 200, "msg", h.copy(), "content", None) resp = flow.Response(req, 200, "msg", h.copy(), "content", None)
assert resp._assemble() assert resp._assemble()
@ -883,7 +883,7 @@ class TestResponse:
h = flow.ODictCaseless() h = flow.ODictCaseless()
h["test"] = ["test"] h["test"] = ["test"]
c = flow.ClientConnect(("addr", 2222)) c = flow.ClientConnect(("addr", 2222))
req = flow.Request(c, "host", 22, "https", "GET", "/", h, "content") req = flow.Request(c, (1, 1), "host", 22, "https", "GET", "/", h, "content")
resp = flow.Response(req, 200, "msg", h.copy(), "content", None) resp = flow.Response(req, 200, "msg", h.copy(), "content", None)
state = resp._get_state() state = resp._get_state()

View File

@ -12,7 +12,7 @@ def treq(conn=None):
conn = flow.ClientConnect(("address", 22)) conn = flow.ClientConnect(("address", 22))
headers = flow.ODictCaseless() headers = flow.ODictCaseless()
headers["header"] = ["qvalue"] headers["header"] = ["qvalue"]
return flow.Request(conn, "host", 80, "http", "GET", "/path", headers, "content") return flow.Request(conn, (1, 1), "host", 80, "http", "GET", "/path", headers, "content")
def tresp(req=None): def tresp(req=None):