diff --git a/libpathod/language/http2.py b/libpathod/language/http2.py index b206c0cf8..6dd93d5f3 100644 --- a/libpathod/language/http2.py +++ b/libpathod/language/http2.py @@ -104,7 +104,6 @@ class Header(_HeaderMixin, base.KeyValue): preamble = "h" - class ShortcutContentType(_HeaderMixin, base.Value): preamble = "c" key = base.TokValueLiteral("content-type") @@ -143,70 +142,6 @@ class Times(base.Integer): preamble = "x" -class Request(_HTTP2Message): - comps = ( - Header, - ShortcutContentType, - ShortcutUserAgent, - Raw, - # NestedResponse, - Body, - Times, - ) - logattrs = ["method", "path"] - - def __init__(self, tokens): - super(Request, self).__init__(tokens) - self.rendered_values = None - - @property - def method(self): - return self.tok(Method) - - @property - def path(self): - return self.tok(Path) - - @property - def times(self): - return self.tok(Times) - - @classmethod - def expr(cls): - parts = [i.expr() for i in cls.comps] - atom = pp.MatchFirst(parts) - resp = pp.And( - [ - Method.expr(), - base.Sep, - Path.expr(), - pp.ZeroOrMore(base.Sep + atom) - ] - ) - resp = resp.setParseAction(cls) - return resp - - def values(self, settings): - if self.rendered_values: - return self.rendered_values - else: - headers = [header.values(settings) for header in self.headers] - - body = self.body - if body: - body = body.string() - - self.rendered_values = settings.protocol.create_request( - self.method.string(), - self.path.string(), - headers, - body) - return self.rendered_values - - def spec(self): - return ":".join([i.spec() for i in self.tokens]) - - class Response(_HTTP2Message): unique_name = None comps = ( @@ -260,6 +195,82 @@ class Response(_HTTP2Message): return ":".join([i.spec() for i in self.tokens]) +class NestedResponse(base.NestedMessage): + preamble = "s" + nest_type = Response + + +class Request(_HTTP2Message): + comps = ( + Header, + ShortcutContentType, + ShortcutUserAgent, + Raw, + NestedResponse, + Body, + Times, + ) + logattrs = ["method", "path"] + + def __init__(self, tokens): + super(Request, self).__init__(tokens) + self.rendered_values = None + + @property + def method(self): + return self.tok(Method) + + @property + def path(self): + return self.tok(Path) + + @property + def nested_response(self): + return self.tok(NestedResponse) + + @property + def times(self): + return self.tok(Times) + + @classmethod + def expr(cls): + parts = [i.expr() for i in cls.comps] + atom = pp.MatchFirst(parts) + resp = pp.And( + [ + Method.expr(), + base.Sep, + Path.expr(), + pp.ZeroOrMore(base.Sep + atom) + ] + ) + resp = resp.setParseAction(cls) + return resp + + def values(self, settings): + if self.rendered_values: + return self.rendered_values + else: + path = self.path.string() + if self.nested_response: + path += self.nested_response.parsed.spec() + + headers = [header.values(settings) for header in self.headers] + + body = self.body + if body: + body = body.string() + + self.rendered_values = settings.protocol.create_request( + self.method.string(), + path, + headers, + body) + return self.rendered_values + + def spec(self): + return ":".join([i.spec() for i in self.tokens]) + def make_error_response(reason, body=None): tokens = [ Code("800"), diff --git a/test/test_language_http2.py b/test/test_language_http2.py index b25ad43c0..3b36c01bc 100644 --- a/test/test_language_http2.py +++ b/test/test_language_http2.py @@ -132,6 +132,14 @@ class TestRequest: default_settings(), ) + def test_nested_response(self): + l = "get:/p/:s'200'" + r = parse_request(l) + assert len(r.tokens) == 3 + assert isinstance(r.tokens[2], http2.NestedResponse) + assert r.values(default_settings()) + + def test_render_with_body(self): s = cStringIO.StringIO() r = parse_request("GET:'/foo':bfoobar")