From 0bc8fa1d0d4f2730311b9fc934a8fcdaae07ab66 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Mon, 8 Jun 2015 15:28:24 +0200 Subject: http2: add pathoc and language tests --- libpathod/language/http2.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'libpathod/language') diff --git a/libpathod/language/http2.py b/libpathod/language/http2.py index d78fc5c8..4a5b9084 100644 --- a/libpathod/language/http2.py +++ b/libpathod/language/http2.py @@ -102,7 +102,7 @@ class Request(message.Message): def values(self, settings): return settings.protocol.create_request( - self.method.value.get_generator(settings), + self.method.string(), self.path, self.headers, self.body) @@ -111,9 +111,5 @@ class Request(message.Message): return ":".join([i.spec() for i in self.tokens]) -# class H2F(base.CaselessLiteral): -# TOK = "h2f" -# -# -# class WebsocketFrame(message.Message): +# class Frame(message.Message): # pass -- cgit v1.2.3 From a0d8afd0fcc3c678da0dc956c5a80d4e07d5ac3e Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Thu, 11 Jun 2015 16:13:22 +0200 Subject: http2: add request-response to pathod --- libpathod/language/__init__.py | 14 +++-- libpathod/language/http.py | 6 +-- libpathod/language/http2.py | 113 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 113 insertions(+), 20 deletions(-) (limited to 'libpathod/language') diff --git a/libpathod/language/__init__.py b/libpathod/language/__init__.py index ae9a8c76..10050bf8 100644 --- a/libpathod/language/__init__.py +++ b/libpathod/language/__init__.py @@ -19,7 +19,7 @@ def expand(msg): yield msg -def parse_pathod(s): +def parse_pathod(s, use_http2=False): """ May raise ParseException """ @@ -28,12 +28,17 @@ def parse_pathod(s): except UnicodeError: raise exceptions.ParseException("Spec must be valid ASCII.", 0, 0) try: - reqs = pp.Or( - [ + if use_http2: + expressions = [ + # http2.Frame.expr(), + http2.Response.expr(), + ] + else: + expressions = [ websockets.WebsocketFrame.expr(), http.Response.expr(), ] - ).parseString(s, parseAll=True) + reqs = pp.Or(expressions).parseString(s, parseAll=True) except pp.ParseException as v: raise exceptions.ParseException(v.msg, v.line, v.col) return itertools.chain(*[expand(i) for i in reqs]) @@ -55,7 +60,6 @@ def parse_pathoc(s, use_http2=False): websockets.WebsocketClientFrame.expr(), http.Request.expr(), ] - reqs = pp.OneOrMore(pp.Or(expressions)).parseString(s, parseAll=True) except pp.ParseException as v: raise exceptions.ParseException(v.msg, v.line, v.col) diff --git a/libpathod/language/http.py b/libpathod/language/http.py index 9a8404f0..115f8069 100644 --- a/libpathod/language/http.py +++ b/libpathod/language/http.py @@ -367,10 +367,6 @@ class Request(_HTTPMessage): return ":".join([i.spec() for i in self.tokens]) -class PathodErrorResponse(Response): - pass - - def make_error_response(reason, body=None): tokens = [ Code("800"), @@ -381,4 +377,4 @@ def make_error_response(reason, body=None): Reason(base.TokValueLiteral(reason)), Body(base.TokValueLiteral("pathod error: " + (body or reason))), ] - return PathodErrorResponse(tokens) + return Response(tokens) diff --git a/libpathod/language/http2.py b/libpathod/language/http2.py index 4a5b9084..1d2517d3 100644 --- a/libpathod/language/http2.py +++ b/libpathod/language/http2.py @@ -45,14 +45,20 @@ class Body(base.Value): class Times(base.Integer): preamble = "x" +class Code(base.Integer): + pass class Request(message.Message): comps = ( Header, Body, - Times, ) + logattrs = ["method", "path"] + + def __init__(self, tokens): + super(Response, self).__init__(tokens) + self.rendered_values = None @property def method(self): @@ -87,7 +93,6 @@ class Request(message.Message): Method.expr(), base.Sep, Path.expr(), - base.Sep, pp.ZeroOrMore(base.Sep + atom) ] ) @@ -95,21 +100,109 @@ class Request(message.Message): return resp def resolve(self, settings, msg=None): - tokens = self.tokens[:] - return self.__class__( - [i.resolve(settings, self) for i in tokens] + return self + + def values(self, settings): + if self.rendered_values: + return self.rendered_values + else: + headers = self.headers + if headers: + headers = headers.values(settings) + + body = self.body + if body: + body = body.string() + + self.rendered_values = settings.protocol.create_request( + self.method.string(), + self.path.string(), + headers, # TODO: parse that into a dict?! + body) + return self.rendered_values + + def spec(self): + return ":".join([i.spec() for i in self.tokens]) + + +class Response(message.Message): + unique_name = None + comps = ( + Header, + Body, + ) + + def __init__(self, tokens): + super(Response, self).__init__(tokens) + self.rendered_values = None + self.stream_id = 0 + + @property + def code(self): + return self.tok(Code) + + @property + def headers(self): + return self.toks(Header) + + @property + def body(self): + return self.tok(Body) + + @property + def actions(self): + return [] + + def resolve(self, settings, msg=None): + return self + + @classmethod + def expr(klass): + parts = [i.expr() for i in klass.comps] + atom = pp.MatchFirst(parts) + resp = pp.And( + [ + Code.expr(), + pp.ZeroOrMore(base.Sep + atom) + ] ) + resp = resp.setParseAction(klass) + return resp def values(self, settings): - return settings.protocol.create_request( - self.method.string(), - self.path, - self.headers, - self.body) + if self.rendered_values: + return self.rendered_values + else: + headers = self.headers + if headers: + headers = headers.values(settings) + + body = self.body + if body: + body = body.values(settings) + + self.rendered_values = settings.protocol.create_response( + self.code.string(), + self.stream_id, + headers, # TODO: parse that into a dict?! + body) + return self.rendered_values def spec(self): return ":".join([i.spec() for i in self.tokens]) +def make_error_response(reason, body=None): + raise NotImplementedError + # tokens = [ + # Code("800"), + # Header( + # base.TokValueLiteral("Content-Type"), + # base.TokValueLiteral("text/plain") + # ), + # Reason(base.TokValueLiteral(reason)), + # Body(base.TokValueLiteral("pathod error: " + (body or reason))), + # ] + # return Response(tokens) # class Frame(message.Message): # pass -- cgit v1.2.3 From ec68aa303e89398ba34bbe01f3fbd1ac1fc441f3 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Tue, 16 Jun 2015 11:33:10 +0200 Subject: http2: implement error response --- libpathod/language/http2.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'libpathod/language') diff --git a/libpathod/language/http2.py b/libpathod/language/http2.py index 1d2517d3..c28b904e 100644 --- a/libpathod/language/http2.py +++ b/libpathod/language/http2.py @@ -179,7 +179,7 @@ class Response(message.Message): body = self.body if body: - body = body.values(settings) + body = body.string() self.rendered_values = settings.protocol.create_response( self.code.string(), @@ -192,17 +192,11 @@ class Response(message.Message): return ":".join([i.spec() for i in self.tokens]) def make_error_response(reason, body=None): - raise NotImplementedError - # tokens = [ - # Code("800"), - # Header( - # base.TokValueLiteral("Content-Type"), - # base.TokValueLiteral("text/plain") - # ), - # Reason(base.TokValueLiteral(reason)), - # Body(base.TokValueLiteral("pathod error: " + (body or reason))), - # ] - # return Response(tokens) + tokens = [ + Code("800"), + Body(base.TokValueLiteral("pathod error: " + (body or reason))), + ] + return Response(tokens) # class Frame(message.Message): # pass -- cgit v1.2.3 From 408b4ffef0a784bea7ec08c252e757bca6e28134 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Tue, 16 Jun 2015 13:52:41 +0200 Subject: http2: implement Headers for request & response improve test coverage fix super ctor call fix legacy httpversion simpliy SSLInfo without ALPN --- libpathod/language/http2.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'libpathod/language') diff --git a/libpathod/language/http2.py b/libpathod/language/http2.py index c28b904e..dec2d5fe 100644 --- a/libpathod/language/http2.py +++ b/libpathod/language/http2.py @@ -35,8 +35,15 @@ class Path(base.Value): class Header(base.KeyValue): + unique_name = None preamble = "h" + def values(self, settings): + return ( + self.key.get_generator(settings), + self.value.get_generator(settings), + ) + class Body(base.Value): preamble = "b" @@ -45,9 +52,11 @@ class Body(base.Value): class Times(base.Integer): preamble = "x" + class Code(base.Integer): pass + class Request(message.Message): comps = ( Header, @@ -57,7 +66,7 @@ class Request(message.Message): logattrs = ["method", "path"] def __init__(self, tokens): - super(Response, self).__init__(tokens) + super(Request, self).__init__(tokens) self.rendered_values = None @property @@ -106,9 +115,7 @@ class Request(message.Message): if self.rendered_values: return self.rendered_values else: - headers = self.headers - if headers: - headers = headers.values(settings) + headers = [header.values(settings) for header in self.headers] body = self.body if body: @@ -173,9 +180,7 @@ class Response(message.Message): if self.rendered_values: return self.rendered_values else: - headers = self.headers - if headers: - headers = headers.values(settings) + headers = [header.values(settings) for header in self.headers] body = self.body if body: -- cgit v1.2.3