diff options
Diffstat (limited to 'libpathod')
-rw-r--r-- | libpathod/language/base.py | 63 | ||||
-rw-r--r-- | libpathod/language/http.py | 53 | ||||
-rw-r--r-- | libpathod/language/websockets.py | 15 |
3 files changed, 73 insertions, 58 deletions
diff --git a/libpathod/language/base.py b/libpathod/language/base.py index eceeae26..f6530d75 100644 --- a/libpathod/language/base.py +++ b/libpathod/language/base.py @@ -213,19 +213,6 @@ Offset = pp.MatchFirst( ) -class Raw(_Token): - @classmethod - def expr(klass): - e = pp.Literal("r").suppress() - return e.setParseAction(lambda x: klass(*x)) - - def spec(self): - return "r" - - def freeze(self, settings): - return self - - class _Component(_Token): """ A value component of the primary specification of an HTTP message. @@ -386,7 +373,10 @@ class PathodSpec(_Token): return PathodSpec(ValueLiteral(f.encode("string_escape"))) -class Path(_Component): +class SimpleValue(_Component): + """ + A simple value - i.e. one without a preface. + """ def __init__(self, value): if isinstance(value, basestring): value = ValueLiteral(value) @@ -406,10 +396,13 @@ class Path(_Component): return "%s"%(self.value.spec()) def freeze(self, settings): - return Path(self.value.freeze(settings)) + return self.__class__(self.value.freeze(settings)) -class _Token(_Component): +class CaselessLiteral(_Component): + """ + A caseless token that can take only one value. + """ def __init__(self, value): self.value = value @@ -429,28 +422,12 @@ class _Token(_Component): return self -class WS(_Token): - TOK = "ws" - - -class WF(_Token): - TOK = "wf" - - -class Method(_Component): - methods = [ - "get", - "head", - "post", - "put", - "delete", - "options", - "trace", - "connect", - ] - +class OptionsOrValue(_Component): + """ + Can be any of a specified set of options, or a value specifier. + """ def __init__(self, value): - # If it's a string, we were passed one of the methods, so we upper-case + # If it's a string, we were passed one of the options, so we upper-case # it to be canonical. The user can specify a different case by using a # string value literal. if isinstance(value, basestring): @@ -459,7 +436,7 @@ class Method(_Component): @classmethod def expr(klass): - parts = [pp.CaselessLiteral(i) for i in klass.methods] + parts = [pp.CaselessLiteral(i) for i in klass.options] m = pp.MatchFirst(parts) spec = m | Value.copy() spec = spec.setParseAction(lambda x: klass(*x)) @@ -472,12 +449,12 @@ class Method(_Component): def spec(self): s = self.value.spec() - if s[1:-1].lower() in self.methods: + if s[1:-1].lower() in self.options: s = s[1:-1].lower() return "%s"%s def freeze(self, settings): - return Method(self.value.freeze(settings)) + return self.__class__(self.value.freeze(settings)) class Code(_Component): @@ -496,7 +473,7 @@ class Code(_Component): return "%s"%(self.code) def freeze(self, settings): - return Code(self.code) + return self class Reason(_Component): @@ -653,10 +630,6 @@ class _Message(object): return l[0] @property - def raw(self): - return bool(self.tok(Raw)) - - @property def actions(self): return self.toks(_Action) diff --git a/libpathod/language/http.py b/libpathod/language/http.py index df5d8ba8..7966b914 100644 --- a/libpathod/language/http.py +++ b/libpathod/language/http.py @@ -8,6 +8,31 @@ from netlib import http_status from . import base, generators, exceptions +class WS(base.CaselessLiteral): + TOK = "ws" + + +class Raw(base.CaselessLiteral): + TOK = "r" + + +class Path(base.SimpleValue): + pass + + +class Method(base.OptionsOrValue): + options = [ + "get", + "head", + "post", + "put", + "delete", + "options", + "trace", + "connect", + ] + + def get_header(val, headers): """ Header keys may be Values, so we have to "generate" them as we try the @@ -22,6 +47,10 @@ def get_header(val, headers): class _HTTPMessage(base._Message): version = "HTTP/1.1" + @property + def raw(self): + return bool(self.tok(Raw)) + @abc.abstractmethod def preamble(self, settings): # pragma: no cover @@ -47,14 +76,14 @@ class Response(_HTTPMessage): base.InjectAt, base.ShortcutContentType, base.ShortcutLocation, - base.Raw, + Raw, base.Reason ) logattrs = ["code", "reason", "version", "body"] @property def ws(self): - return self.tok(base.WS) + return self.tok(WS) @property def code(self): @@ -129,7 +158,7 @@ class Response(_HTTPMessage): [ pp.MatchFirst( [ - base.WS.expr() + pp.Optional( + WS.expr() + pp.Optional( base.Sep + base.Code.expr() ), base.Code.expr(), @@ -154,22 +183,22 @@ class Request(_HTTPMessage): base.InjectAt, base.ShortcutContentType, base.ShortcutUserAgent, - base.Raw, + Raw, base.PathodSpec, ) logattrs = ["method", "path", "body"] @property def ws(self): - return self.tok(base.WS) + return self.tok(WS) @property def method(self): - return self.tok(base.Method) + return self.tok(Method) @property def path(self): - return self.tok(base.Path) + return self.tok(Path) @property def pathodspec(self): @@ -191,7 +220,7 @@ class Request(_HTTPMessage): if not self.method: tokens.insert( 1, - base.Method("get") + Method("get") ) for i in netlib.websockets.client_handshake_headers().lst: if not get_header(i[0], self.headers): @@ -232,14 +261,14 @@ class Request(_HTTPMessage): [ pp.MatchFirst( [ - base.WS.expr() + pp.Optional( - base.Sep + base.Method.expr() + WS.expr() + pp.Optional( + base.Sep + Method.expr() ), - base.Method.expr(), + Method.expr(), ] ), base.Sep, - base.Path.expr(), + Path.expr(), pp.ZeroOrMore(base.Sep + atom) ] ) diff --git a/libpathod/language/websockets.py b/libpathod/language/websockets.py index 29b7311c..7ec4a2b1 100644 --- a/libpathod/language/websockets.py +++ b/libpathod/language/websockets.py @@ -3,6 +3,19 @@ import netlib.websockets import contrib.pyparsing as pp from . import base, generators +""" + wf:ctext:b'foo' + wf:c15:r'foo' + wf:fin:rsv1:rsv2:rsv3:mask + wf:-fin:-rsv1:-rsv2:-rsv3:-mask + wf:p234 + wf:m"mask" +""" + + +class WF(base.CaselessLiteral): + TOK = "wf" + class WebsocketFrame(base._Message): comps = ( @@ -19,7 +32,7 @@ class WebsocketFrame(base._Message): atom = pp.MatchFirst(parts) resp = pp.And( [ - base.WF.expr(), + WF.expr(), base.Sep, pp.ZeroOrMore(base.Sep + atom) ] |