Add a raw modifier to requests and responses, which turn off automatic additions.

For now, this just turns off adding a Content-Length header when a body is specified.
This commit is contained in:
Aldo Cortesi 2012-07-24 12:18:14 +12:00
parent 2dd2137d44
commit dbed251fb9
2 changed files with 41 additions and 12 deletions

View File

@ -8,6 +8,7 @@ TRUNCATE = 1024
class FileAccessDenied(Exception): pass
class ParseException(Exception):
def __init__(self, msg, s, col):
Exception.__init__(self)
@ -22,7 +23,6 @@ class ParseException(Exception):
return "%s at offset %s of %s"%(self.msg, self.col, repr(self.s))
def actions_log(lst):
ret = []
for i in lst:
@ -344,6 +344,16 @@ class Body:
return e.setParseAction(lambda x: klass(*x))
class Raw:
def accept(self, settings, r):
r.raw = True
@classmethod
def expr(klass):
e = pp.Literal("r").suppress()
return e.setParseAction(lambda x: klass(*x))
class Path:
def __init__(self, value):
if isinstance(value, basestring):
@ -496,6 +506,12 @@ class Code:
class Message:
version = "HTTP/1.1"
def __init__(self):
self.body = LiteralGenerator("")
self.headers = []
self.actions = []
self.raw = False
def length(self):
"""
Calculate the length of the base message without any applied actions.
@ -528,12 +544,12 @@ class Message:
fp: The file pointer to write to.
check: A function called with the effective actions (after random
values have been calculated). If it returns False service
proceeds, otherwise the return is treated as an error message to be
sent to the client, and service stops.
values have been calculated). If it returns False service proceeds,
otherwise the return is treated as an error message to be sent to
the client, and service stops.
"""
started = time.time()
if self.body and not utils.get_header("Content-Length", self.headers):
if self.body and not self.raw and not utils.get_header("Content-Length", self.headers):
self.headers.append(
(
LiteralGenerator("Content-Length"),
@ -596,14 +612,13 @@ class Response(Message):
InjectAt,
ShortcutContentType,
ShortcutLocation,
Raw
)
logattrs = ["code", "version"]
def __init__(self):
self.headers = []
self.actions = []
Message.__init__(self)
self.code = 200
self.msg = LiteralGenerator(http_status.RESPONSES[self.code])
self.body = LiteralGenerator("")
def preamble(self):
return [self.version, " ", str(self.code), " ", self.msg]
@ -635,14 +650,13 @@ class Request(Message):
DisconnectAt,
InjectAt,
ShortcutContentType,
Raw
)
logattrs = ["method", "path"]
def __init__(self):
Message.__init__(self)
self.method = None
self.path = None
self.body = LiteralGenerator("")
self.headers = []
self.actions = []
def preamble(self):
return [self.method, " ", self.path, " ", self.version]

View File

@ -116,6 +116,10 @@ class TestMisc:
assert e.parseString("'foo'")[0].value.val == "foo"
assert e.parseString("'get'")[0].value.val == "get"
def test_raw(self):
e = rparse.Raw.expr()
assert e.parseString("r")[0]
def test_body(self):
e = rparse.Body.expr()
v = e.parseString("b'foo'")[0]
@ -436,6 +440,17 @@ class TestResponse:
r = rparse.parse_response({}, "400'msg'")
assert r.serve(s)
def test_raw(self):
s = cStringIO.StringIO()
r = rparse.parse_response({}, "400:b'foo'")
r.serve(s)
assert "Content-Length" in s.getvalue()
s = cStringIO.StringIO()
r = rparse.parse_response({}, "400:b'foo':r")
r.serve(s)
assert not "Content-Length" in s.getvalue()
def test_length(self):
def testlen(x):
s = cStringIO.StringIO()