aboutsummaryrefslogtreecommitdiffstats
path: root/libpathod
diff options
context:
space:
mode:
Diffstat (limited to 'libpathod')
-rw-r--r--libpathod/language/base.py63
-rw-r--r--libpathod/language/http.py53
-rw-r--r--libpathod/language/websockets.py15
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)
]