aboutsummaryrefslogtreecommitdiffstats
path: root/libpathod
diff options
context:
space:
mode:
authorAldo Cortesi <aldo@nullcube.com>2012-06-24 19:12:52 +1200
committerAldo Cortesi <aldo@nullcube.com>2012-06-24 19:12:52 +1200
commit8bec99f858deb8aaf35b6502355e3e00a98ffed7 (patch)
tree419ac606df005de5e96e5da328cdee5275dbcb38 /libpathod
parent2ac84be7cb0e4a17fd39c6155074a37161662593 (diff)
downloadmitmproxy-8bec99f858deb8aaf35b6502355e3e00a98ffed7.tar.gz
mitmproxy-8bec99f858deb8aaf35b6502355e3e00a98ffed7.tar.bz2
mitmproxy-8bec99f858deb8aaf35b6502355e3e00a98ffed7.zip
Request service rendering.
Diffstat (limited to 'libpathod')
-rw-r--r--libpathod/rparse.py177
1 files changed, 98 insertions, 79 deletions
diff --git a/libpathod/rparse.py b/libpathod/rparse.py
index af0f9671..bb45ae00 100644
--- a/libpathod/rparse.py
+++ b/libpathod/rparse.py
@@ -4,6 +4,7 @@ from netlib import http_status
import utils
BLOCKSIZE = 1024
+TRUNCATE = 1024
class ParseException(Exception):
def __init__(self, msg, s, col):
@@ -421,21 +422,82 @@ class Code:
return e.setParseAction(lambda x: klass(*x))
-class Request:
+
+class Message:
+ version = "HTTP/1.1"
+ def length(self):
+ l = sum(len(x) for x in self.preamble())
+ l += 2
+ for i in self.headers:
+ l += len(i[0]) + len(i[1])
+ l += 4
+ l += 2
+ l += len(self.body)
+ return l
+
+ def serve(self, fp):
+ started = time.time()
+ if self.body and not utils.get_header("Content-Length", self.headers):
+ self.headers.append(
+ (
+ LiteralGenerator("Content-Length"),
+ LiteralGenerator(str(len(self.body))),
+ )
+ )
+
+ hdrs = []
+ for k, v in self.headers:
+ hdrs.extend([
+ k,
+ ": ",
+ v,
+ "\r\n",
+ ])
+ vals = self.preamble()
+ vals.append("\r\n")
+ vals.extend(hdrs)
+ vals.append("\r\n")
+ if self.body:
+ vals.append(self.body)
+ vals.reverse()
+ actions = ready_actions(self.length(), self.actions)
+ actions.reverse()
+ disconnect = write_values(fp, vals, actions[:])
+ duration = time.time() - started
+ ret = dict(
+ disconnect = disconnect,
+ started = started,
+ duration = duration,
+ actions = actions,
+ )
+ for i in self.logattrs:
+ v = getattr(self, i)
+ # Careful not to log any VALUE specs without sanitizing them first. We truncate at 1k.
+ if hasattr(v, "__len__"):
+ v = v[:TRUNCATE]
+ ret[i] = v
+ return ret
+
+
+class Response(Message):
comps = (
Body,
Header,
PauseAt,
DisconnectAt,
ShortcutContentType,
+ ShortcutLocation,
)
- version = "HTTP/1.1"
+ logattrs = ["code", "version"]
def __init__(self):
- self.method = None
- self.path = None
- self.body = LiteralGenerator("")
self.headers = []
self.actions = []
+ 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]
@classmethod
def expr(klass):
@@ -443,115 +505,72 @@ class Request:
atom = pp.MatchFirst(parts)
resp = pp.And(
[
- Method.expr(),
- pp.Literal(":").suppress(),
- Path.expr(),
+ Code.expr(),
pp.ZeroOrMore(pp.Literal(":").suppress() + atom)
]
)
return resp
-
-class CraftedRequest(Request):
- def __init__(self, settings, spec, tokens):
- Request.__init__(self)
- self.spec, self.tokens = spec, tokens
- for i in tokens:
- i.accept(settings, self)
-
- def serve(self, fp):
- d = Request.serve(self, fp)
- d["spec"] = self.spec
- return d
+ def __str__(self):
+ parts = [
+ "%s %s"%(self.code, self.msg[:])
+ ]
+ return "\n".join(parts)
-class Response:
+class Request(Message):
comps = (
Body,
Header,
PauseAt,
DisconnectAt,
ShortcutContentType,
- ShortcutLocation,
)
- version = "HTTP/1.1"
- code = 200
- msg = LiteralGenerator(http_status.RESPONSES[code])
- body = LiteralGenerator("")
+ logattrs = ["method", "path"]
def __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]
+
@classmethod
def expr(klass):
parts = [i.expr() for i in klass.comps]
atom = pp.MatchFirst(parts)
resp = pp.And(
[
- Code.expr(),
+ Method.expr(),
+ pp.Literal(":").suppress(),
+ Path.expr(),
pp.ZeroOrMore(pp.Literal(":").suppress() + atom)
]
)
return resp
- def length(self):
- l = len("%s %s "%(self.version, self.code))
- l += len(self.msg)
- l += 2
- for i in self.headers:
- l += len(i[0]) + len(i[1])
- l += 4
- l += 2
- l += len(self.body)
- return l
-
- def serve(self, fp):
- started = time.time()
- if self.body and not utils.get_header("Content-Length", self.headers):
- self.headers.append(
- (
- LiteralGenerator("Content-Length"),
- LiteralGenerator(str(len(self.body))),
- )
- )
-
- hdrs = []
- for k, v in self.headers:
- hdrs.extend([
- k,
- ": ",
- v,
- "\r\n",
- ])
- vals = [
- "%s %s "%(self.version, self.code),
- self.msg,
- "\r\n",
- ]
- vals.extend(hdrs)
- vals.append("\r\n")
- if self.body:
- vals.append(self.body)
- vals.reverse()
- actions = ready_actions(self.length(), self.actions)
- actions.reverse()
- disconnect = write_values(fp, vals, actions[:])
- duration = time.time() - started
- return dict(
- disconnect = disconnect,
- started = started,
- duration = duration,
- actions = actions,
- code = self.code,
- )
-
def __str__(self):
parts = [
- "%s %s"%(self.code, self.msg[:])
+ "%s %s"%(self.method[:], self.path[:])
]
return "\n".join(parts)
+class CraftedRequest(Request):
+ def __init__(self, settings, spec, tokens):
+ Request.__init__(self)
+ self.spec, self.tokens = spec, tokens
+ for i in tokens:
+ i.accept(settings, self)
+
+ def serve(self, fp):
+ d = Request.serve(self, fp)
+ d["spec"] = self.spec
+ return d
+
+
class CraftedResponse(Response):
def __init__(self, settings, spec, tokens):
Response.__init__(self)