From 46255e6e9cfca6ee5b32d287be7d2a0eb8d73c20 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Mon, 22 Jun 2015 12:42:39 +0200 Subject: http2: implement more language features --- libpathod/language/http.py | 12 ++-- libpathod/language/http2.py | 140 +++++++++++++++++++++++++++++++------------- test/test_language_http2.py | 52 ++++++++++++++-- 3 files changed, 151 insertions(+), 53 deletions(-) diff --git a/libpathod/language/http.py b/libpathod/language/http.py index 3979a1ee..3c9df484 100644 --- a/libpathod/language/http.py +++ b/libpathod/language/http.py @@ -82,12 +82,10 @@ class ShortcutUserAgent(_HeaderMixin, base.OptionsOrValue): key = base.TokValueLiteral("User-Agent") def values(self, settings): + value = self.value.val if self.option_used: - value = http_uastrings.get_by_shortcut( - self.value.val.lower() - )[2] - else: - value = self.value.val + value = http_uastrings.get_by_shortcut(value.lower())[2] + return self.format_header( self.key.get_generator(settings), value @@ -143,12 +141,12 @@ class _HTTPMessage(message.Message): class Response(_HTTPMessage): unique_name = None comps = ( - Body, Header, ShortcutContentType, ShortcutLocation, Raw, Reason, + Body, actions.PauseAt, actions.DisconnectAt, @@ -256,12 +254,12 @@ class NestedResponse(base.NestedMessage): class Request(_HTTPMessage): comps = ( - Body, Header, ShortcutContentType, ShortcutUserAgent, Raw, NestedResponse, + Body, Times, actions.PauseAt, diff --git a/libpathod/language/http2.py b/libpathod/language/http2.py index 86e04056..b206c0cf 100644 --- a/libpathod/language/http2.py +++ b/libpathod/language/http2.py @@ -1,4 +1,6 @@ import pyparsing as pp + +from netlib import http_status, http_uastrings from . import base, message """ @@ -24,6 +26,65 @@ from . import base, message h2f:42:DATA:END_STREAM,PADDED:0x1234567:'content body payload' """ +def get_header(val, headers): + """ + Header keys may be Values, so we have to "generate" them as we try the + match. + """ + for h in headers: + k = h.key.get_generator({}) + if len(k) == len(val) and k[:].lower() == val.lower(): + return h + return None + + +class _HeaderMixin(object): + unique_name = None + + def values(self, settings): + return ( + self.key.get_generator(settings), + self.value.get_generator(settings), + ) + +class _HTTP2Message(message.Message): + @property + def actions(self): + return [] # self.toks(actions._Action) + + @property + def headers(self): + headers = self.toks(_HeaderMixin) + + if not self.raw: + if not get_header("content-length", headers): + if not self.body: + length = 0 + else: + length = len(self.body.string()) + headers.append( + Header( + base.TokValueLiteral("content-length"), + base.TokValueLiteral(str(length)), + ) + ) + return headers + + @property + def raw(self): + return bool(self.tok(Raw)) + + @property + def body(self): + return self.tok(Body) + + def resolve(self, settings): + return self + + +class Code(base.Integer): + pass + class Method(base.OptionsOrValue): options = [ @@ -39,17 +100,41 @@ class Path(base.Value): pass -class Header(base.KeyValue): - unique_name = None +class Header(_HeaderMixin, base.KeyValue): preamble = "h" + + +class ShortcutContentType(_HeaderMixin, base.Value): + preamble = "c" + key = base.TokValueLiteral("content-type") + + +class ShortcutLocation(_HeaderMixin, base.Value): + preamble = "l" + key = base.TokValueLiteral("location") + + +class ShortcutUserAgent(_HeaderMixin, base.OptionsOrValue): + preamble = "u" + options = [i[1] for i in http_uastrings.UASTRINGS] + key = base.TokValueLiteral("user-agent") + def values(self, settings): + value = self.value.val + if self.option_used: + value = http_uastrings.get_by_shortcut(value.lower())[2] + return ( self.key.get_generator(settings), - self.value.get_generator(settings), + value ) +class Raw(base.CaselessLiteral): + TOK = "r" + + class Body(base.Value): preamble = "b" @@ -58,13 +143,13 @@ class Times(base.Integer): preamble = "x" -class Code(base.Integer): - pass - - -class Request(message.Message): +class Request(_HTTP2Message): comps = ( Header, + ShortcutContentType, + ShortcutUserAgent, + Raw, + # NestedResponse, Body, Times, ) @@ -82,22 +167,10 @@ class Request(message.Message): def path(self): return self.tok(Path) - @property - def headers(self): - return self.toks(Header) - - @property - def body(self): - return self.tok(Body) - @property def times(self): return self.tok(Times) - @property - def actions(self): - return [] - @classmethod def expr(cls): parts = [i.expr() for i in cls.comps] @@ -113,9 +186,6 @@ class Request(message.Message): resp = resp.setParseAction(cls) return resp - def resolve(self, settings, msg=None): - return self - def values(self, settings): if self.rendered_values: return self.rendered_values @@ -129,7 +199,7 @@ class Request(message.Message): self.rendered_values = settings.protocol.create_request( self.method.string(), self.path.string(), - headers, # TODO: parse that into a dict?! + headers, body) return self.rendered_values @@ -137,11 +207,14 @@ class Request(message.Message): return ":".join([i.spec() for i in self.tokens]) -class Response(message.Message): +class Response(_HTTP2Message): unique_name = None comps = ( Header, Body, + ShortcutContentType, + ShortcutLocation, + Raw, ) def __init__(self, tokens): @@ -153,21 +226,6 @@ class Response(message.Message): 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(cls): parts = [i.expr() for i in cls.comps] @@ -194,7 +252,7 @@ class Response(message.Message): self.rendered_values = settings.protocol.create_response( self.code.string(), self.stream_id, - headers, # TODO: parse that into a dict?! + headers, body) return self.rendered_values diff --git a/test/test_language_http2.py b/test/test_language_http2.py index a78c2bee..b25ad43c 100644 --- a/test/test_language_http2.py +++ b/test/test_language_http2.py @@ -90,6 +90,39 @@ class TestRequest: default_settings(), ) + def test_raw_content_length(self): + r = parse_request('GET:/:r') + assert len(r.headers) == 0 + + r = parse_request('GET:/:r:b"foobar"') + assert len(r.headers) == 0 + + r = parse_request('GET:/') + assert len(r.headers) == 1 + assert r.headers[0].values(default_settings()) == ("content-length", "0") + + r = parse_request('GET:/:b"foobar"') + assert len(r.headers) == 1 + assert r.headers[0].values(default_settings()) == ("content-length", "6") + + r = parse_request('GET:/:b"foobar":h"content-length"="42"') + assert len(r.headers) == 1 + assert r.headers[0].values(default_settings()) == ("content-length", "42") + + r = parse_request('GET:/:r:b"foobar":h"content-length"="42"') + assert len(r.headers) == 1 + assert r.headers[0].values(default_settings()) == ("content-length", "42") + + def test_content_type(self): + r = parse_request('GET:/:r:c"foobar"') + assert len(r.headers) == 1 + assert r.headers[0].values(default_settings()) == ("content-type", "foobar") + + def test_user_agent(self): + r = parse_request('GET:/:r:ua') + assert len(r.headers) == 1 + assert r.headers[0].values(default_settings()) == ("user-agent", netlib.http_uastrings.get_by_shortcut('a')[2]) + def test_render_with_headers(self): s = cStringIO.StringIO() r = parse_request('GET:/foo:h"foo"="bar"') @@ -129,18 +162,27 @@ class TestResponse: def test_err(self): tutils.raises(language.ParseException, parse_response, 'GET:/') - def test_simple(self): - r = parse_response('200') - assert r.code.string() == "200" + def test_raw_content_length(self): + r = parse_response('200:r') assert len(r.headers) == 0 - r = parse_response('200:h"foo"="bar"') + r = parse_response('200') + assert len(r.headers) == 1 + assert r.headers[0].values(default_settings()) == ("content-length", "0") + + def test_content_type(self): + r = parse_response('200:r:c"foobar"') + assert len(r.headers) == 1 + assert r.headers[0].values(default_settings()) == ("content-type", "foobar") + + def test_simple(self): + r = parse_response('200:r:h"foo"="bar"') assert r.code.string() == "200" assert len(r.headers) == 1 assert r.headers[0].values(default_settings()) == ("foo", "bar") assert r.body is None - r = parse_response('200:h"foo"="bar":bfoobar:h"bla"="fasel"') + r = parse_response('200:r:h"foo"="bar":bfoobar:h"bla"="fasel"') assert r.code.string() == "200" assert len(r.headers) == 2 assert r.headers[0].values(default_settings()) == ("foo", "bar") -- cgit v1.2.3 From 5c0f0c2c221edf9e9d94c0ab4ad809e668f04894 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Mon, 22 Jun 2015 13:11:40 +0200 Subject: http2: update docs --- libpathod/templates/docs_lang_requests.html | 113 +++++++++++++-------------- libpathod/templates/docs_lang_responses.html | 70 ++++++++--------- 2 files changed, 90 insertions(+), 93 deletions(-) diff --git a/libpathod/templates/docs_lang_requests.html b/libpathod/templates/docs_lang_requests.html index fe73f0af..92921ec4 100644 --- a/libpathod/templates/docs_lang_requests.html +++ b/libpathod/templates/docs_lang_requests.html @@ -1,113 +1,112 @@ - -
method:path:[colon-separated list of features]

+
method:path:[colon-separated list of features]
+

- - + - + - + - + - + - + + - + - + - + - + - - + - + - + diff --git a/libpathod/templates/docs_lang_responses.html b/libpathod/templates/docs_lang_responses.html index e8590add..8939ab26 100644 --- a/libpathod/templates/docs_lang_responses.html +++ b/libpathod/templates/docs_lang_responses.html @@ -1,89 +1,87 @@ - -
code:[colon-separated list of features]

+
code:[colon-separated list of features]
method method - -

A VALUE specifying the HTTP - method to use. Standard methods do not need to be - enclosed in quotes, while non-standard methods can be - specified as quoted strings.

- -

The special method ws creates a valid - websocket upgrade GET request, and signals to pathoc to - switch to websocket recieve mode if the server responds - correctly. Apart from that, websocket requests are just - like any other, and all aspects of the request can be - over-ridden.

+

+ A VALUE specifying the HTTP method to use. Standard + methods do not need to be enclosed in quotes, while non-standard methods + can be specified as quoted strings. +

+ +

+ The special method ws creates a valid websocket upgrade GET + request, and signals to pathoc to switch to websocket recieve mode + if the server responds correctly. Apart from that, websocket requests + are just like any other, and all aspects of the request can be over-ridden. +

bVALUE hVALUE=VALUE - Set the body. The appropriate Content-Length header is - added automatically unless the "r" flag is set. + Set a header.
cVALUE r - A shortcut for setting the Content-Type header. Equivalent to - h"Content-Type"=VALUE + Set the "raw" flag on this response. Pathod will not calculate a Content-Length header + if a body is set.
dOFFSET cVALUE - Disconnect after OFFSET bytes. + A shortcut for setting the Content-Type header. Equivalent to h"Content-Type"=VALUE
hVALUE=VALUE uVALUE +
uSHORTCUT +
- Set a header. + Set a User-Agent header on this request. You can specify either a complete + VALUE, or a User-Agent shortcut: + + + {% for i in uastrings %} + + + + + {% endfor %} +
{{ i[1] }}{{ i[0] }}
iOFFSET,VALUE bVALUE - Inject the specified value at the offset. + Set the body. The appropriate Content-Length header is added automatically unless the + "r" flag is set.
pOFFSET,SECONDS sVALUE - Pause for SECONDS seconds after OFFSET bytes. SECONDS can - be an integer or "f" to pause forever. + An embedded Response specification, appended to the path of the request.
r xINTEGER - Set the "raw" flag on this response. Pathod will not - calculate a Content-Length header if a body is set. + Repeat this message N times.
sVALUE dOFFSET - An embedded Response specification, appended to the path - of the request. + HTTP/1 only + Disconnect after OFFSET bytes.
uVALUE
uSHORTCUT
iOFFSET,VALUE - - Set a User-Agent header on this request. You can - specify either a complete VALUE, or a User-Agent shortcut: - - - {% for i in uastrings %} - - - - - {% endfor %} -
{{ i[1] }}{{ i[0] }}
- + HTTP/1 only + Inject the specified value at the offset.
xINTEGER pOFFSET,SECONDS - Repeat this message N times. + HTTP/1 only + Pause for SECONDS seconds after OFFSET bytes. SECONDS can be an integer or "f" to pause + forever.
- + - + - + - + - + - + - - + - + - + - + - + -- cgit v1.2.3 From 01f098296870cf56f835fa1222607d8216f52811 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Mon, 22 Jun 2015 15:12:20 +0200 Subject: prettify html docs --- .gitignore | 2 +- libpathod/templates/about.html | 40 ++-- libpathod/templates/docframe.html | 22 +- libpathod/templates/docs_lang.html | 306 ++++++++++++++------------ libpathod/templates/docs_lang_websockets.html | 28 ++- libpathod/templates/docs_libpathod.html | 24 +- libpathod/templates/docs_pathoc.html | 268 +++++++++++----------- libpathod/templates/docs_pathod.html | 155 +++++++------ libpathod/templates/docs_test.html | 70 +++--- libpathod/templates/download.html | 34 +-- libpathod/templates/examples_context.html | 1 + libpathod/templates/examples_setup.html | 3 + libpathod/templates/examples_setupall.html | 6 +- libpathod/templates/frame.html | 8 +- libpathod/templates/index.html | 51 ++--- libpathod/templates/layout.html | 85 ++++--- libpathod/templates/libpathod_pathoc.html | 3 +- libpathod/templates/log.html | 59 +++-- libpathod/templates/onelog.html | 14 +- libpathod/templates/request_preview.html | 58 +++-- libpathod/templates/request_previewform.html | 20 +- libpathod/templates/response_preview.html | 56 +++-- libpathod/templates/response_previewform.html | 38 ++-- 23 files changed, 668 insertions(+), 683 deletions(-) diff --git a/.gitignore b/.gitignore index c88c25ce..4c8c70a2 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,4 @@ MANIFEST netlib venv .idea/ -pathod.egg-info/ \ No newline at end of file +pathod.egg-info/ diff --git a/libpathod/templates/about.html b/libpathod/templates/about.html index 9a695a6a..340dc386 100644 --- a/libpathod/templates/about.html +++ b/libpathod/templates/about.html @@ -1,30 +1,22 @@ -{% extends "frame.html" %} -{% block body %} - - +{% extends "frame.html" %} {% block body %}
- -
-
-
-

pathod is developed by Aldo - Cortesi.

-
+ +
+
+
+

pathod is developed by Aldo Cortesi.

+
-
- +
+ +
-
- - {% endblock %} diff --git a/libpathod/templates/docframe.html b/libpathod/templates/docframe.html index f780f379..4cbdeebc 100644 --- a/libpathod/templates/docframe.html +++ b/libpathod/templates/docframe.html @@ -1,26 +1,26 @@ {% extends "layout.html" %} {% macro subs(s) %} -{% if subsection == s %} class="active" {% endif %} + {% if subsection == s %} + class="active" + {% endif %} {% endmacro %} - -{% block content %} +{% block content %}
- {% block body %} - {% endblock %} + {% block body %} {% endblock %}
-{% endblock %} +{% endblock %} diff --git a/libpathod/templates/docs_lang.html b/libpathod/templates/docs_lang.html index ce778dc9..e3195939 100644 --- a/libpathod/templates/docs_lang.html +++ b/libpathod/templates/docs_lang.html @@ -1,17 +1,15 @@ -{% extends "docframe.html" %} -{% block body %} - +{% extends "docframe.html" %} {% block body %}
@@ -28,151 +26,171 @@
- -

OFFSET

- -

Offsets are calculated relative to the base message, before any - injections or other transforms are applied. They have 3 flavors:

- -
    -
  • An integer byte offset
  • -
  • r for a random location
  • -
  • a for the end of the message
  • -
- - -

VALUE

+ +

OFFSET

-

Literals

+

+ Offsets are calculated relative to the base message, before any injections or other transforms + are applied. They have 3 flavors: +

-

Literal values are specified as a quoted strings:

+
    +
  • An integer byte offset
  • +
  • r for a random location
  • +
  • a for the end of the message
  • +
-
"foo"
+ +

VALUE

-

Either single or double quotes are accepted, and quotes can be escaped with - backslashes within the string:

+

Literals

-
'fo\'o'
+

Literal values are specified as a quoted strings:

-

Literal values can contain Python-style backslash escape sequences:

+
"foo"
-
'foo\r\nbar'
- - -

Files

- -

You can load a value from a specified file path. To do so, you have to specify - a _staticdir_ option to pathod on the command-line, like so:

- -
pathod -d ~/myassets
- -

All paths are relative paths under this directory. File loads are indicated by - starting the value specifier with the left angle bracket: - -

<my/path

- -

The path value can also be a quoted string, with the same syntax as literals:

- -
<"my/path"
- - -

Generated values

- -

An @-symbol lead-in specifies that generated data should be used. There are two - components to a generator specification - a size, and a data type. By default - pathod assumes a data type of "bytes".

- -

Here's a value specifier for generating 100 bytes: - -

@100

- -

You can use standard suffixes to indicate larger values. Here, for instance, is - a specifier for generating 100 megabytes:

- -
@100m
- -

Data is generated and served efficiently - if you really want to send a - terabyte of data to a client, pathod can do it. The supported suffixes are:

- - -
code code

An integer specifying the HTTP response code.

- -

The special method ws creates a valid - websocket upgrade response (code 101), and moves pathod - to websocket mode. Apart from that, websocket responses - are just like any other, and all aspects of the - response can be over-ridden.

+

+ The special method ws creates a valid websocket upgrade response + (code 101), and moves pathod to websocket mode. Apart from that, websocket + responses are just like any other, and all aspects of the response + can be over-ridden. +

bVALUE mVALUE - Set the body. The appropriate Content-Length header is - added automatically unless the "r" flag is set. + HTTP/1 only + HTTP Reason message. Automatically chosen according to the response code if not specified.
cVALUE hVALUE=VALUE - A shortcut for setting the Content-Type header. Equivalent to - h"Content-Type"=VALUE + Set a header.
dOFFSET r - Disconnect after OFFSET bytes. + Set the "raw" flag on this response. Pathod will not calculate a Content-Length header + if a body is set, or add a Date header to the response.
hVALUE=VALUE lVALUE - Set a header. + A shortcut for setting the Location header. Equivalent to h"Location"=VALUE
iOFFSET,VALUE cVALUE - Inject the specified value at the offset. + A shortcut for setting the Content-Type header. Equivalent to h"Content-Type"=VALUE
lVALUE bVALUE - A shortcut for setting the Location header. Equivalent to - h"Location"=VALUE + Set the body. The appropriate Content-Length header is added automatically unless the + "r" flag is set.
mVALUE dOFFSET - HTTP Reason message. Automatically chosen according to - the response code if not specified. + HTTP/1 only + Disconnect after OFFSET bytes.
pOFFSET,SECONDS iOFFSET,VALUE - Pause for SECONDS seconds after OFFSET bytes. SECONDS can - be an integer or "f" to pause forever. + HTTP/1 only + Inject the specified value at the offset.
r pOFFSET,SECONDS - Set the "raw" flag on this response. Pathod will not - calculate a Content-Length header if a body is set, or add - a Date header to the response. + HTTP/1 only + Pause for SECONDS seconds after OFFSET bytes. SECONDS can be an integer or "f" to pause + forever.
- - - - - - - - - - - - - - - - - -
b 1024**0 (bytes)
k 1024**1 (kilobytes)
m 1024**2 (megabytes)
g 1024**3 (gigabytes)
t 1024**4 (terabytes)
- -

Data types are separated from the size specification by a comma. This - specification generates 100mb of ASCII:

- -
@100m,ascii
- -

Supported data types are:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
asciiAll ASCII characters
ascii_lettersA-Za-z
ascii_lowercasea-z
ascii_uppercaseA-Z
bytesAll 256 byte values
digits0-9
hexdigits0-f
octdigits0-7
punctuation -
!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~
-
whitespace -
\t\n\x0b\x0c\r and space
-
+

+ Either single or double quotes are accepted, and quotes can be escaped with backslashes + within the string: +

+ +
'fo\'o'
+ +

Literal values can contain Python-style backslash escape sequences:

+ +
'foo\r\nbar'
+ +

Files

+ +

+ You can load a value from a specified file path. To do so, you have to specify a _staticdir_ + option to pathod on the command-line, like so: +

+ +
pathod -d ~/myassets
+ +

+ All paths are relative paths under this directory. File loads are indicated by starting + the value specifier with the left angle bracket: +

+ +
<my/path
+ +

The path value can also be a quoted string, with the same syntax as literals:

+ +
<"my/path"
+ + +

Generated values

+ +

+ An @-symbol lead-in specifies that generated data should be used. There are two components + to a generator specification - a size, and a data type. By default pathod assumes + a data type of "bytes". +

+ +

Here's a value specifier for generating 100 bytes: + +

@100
+

+ +

+ You can use standard suffixes to indicate larger values. Here, for instance, is a specifier + for generating 100 megabytes: +

+ +
@100m
+ +

+ Data is generated and served efficiently - if you really want to send a terabyte of data + to a client, pathod can do it. The supported suffixes are: +

+ + + + + + + + + + + + + + + + + + + + + + + + +
b1024**0 (bytes)
k1024**1 (kilobytes)
m1024**2 (megabytes)
g1024**3 (gigabytes)
t1024**4 (terabytes)
+ +

+ Data types are separated from the size specification by a comma. This specification generates + 100mb of ASCII: +

+ +
@100m,ascii
+ +

Supported data types are:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
asciiAll ASCII characters
ascii_lettersA-Za-z
ascii_lowercasea-z
ascii_uppercaseA-Z
bytesAll 256 byte values
digits0-9
hexdigits0-f
octdigits0-7
punctuation +
!"#$%&\'()*+,-./:;
+                        <=>?@[\\]^_`{|}~
+
whitespace +
\t\n\x0b\x0c\r and space
+
- {% endblock %} diff --git a/libpathod/templates/docs_lang_websockets.html b/libpathod/templates/docs_lang_websockets.html index 32bd71f9..682f4cc8 100644 --- a/libpathod/templates/docs_lang_websockets.html +++ b/libpathod/templates/docs_lang_websockets.html @@ -1,13 +1,13 @@ -
wf:[colon-separated list of features]

+
wf:[colon-separated list of features]
+

- + @@ -15,8 +15,8 @@ @@ -71,16 +70,15 @@ diff --git a/libpathod/templates/docs_libpathod.html b/libpathod/templates/docs_libpathod.html index 3e18c1d9..72b24e83 100644 --- a/libpathod/templates/docs_libpathod.html +++ b/libpathod/templates/docs_libpathod.html @@ -1,8 +1,6 @@ -{% extends "docframe.html" %} -{% block body %} - +{% extends "docframe.html" %} {% block body %}
bVALUE - Set the frame payload. If a masking key is present, the - value is encoded automatically. + Set the frame payload. If a masking key is present, the value is encoded automatically.
cINTEGER - Set the op code. This can either be an integer from 0-15, or be - one of the following opcode names: text (the default), + Set the op code. This can either be an integer from 0-15, or be one of the following opcode + names: text (the default), continue, binary, close, ping, pong. @@ -47,17 +47,16 @@
kVALUE - Set the masking key. The resulting value must be exactly 4 - bytes long. The special form knone specifies that no key - should be set, even if the mask bit is on. + Set the masking key. The resulting value must be exactly 4 bytes long. The special form + knone specifies that no key should be set, even + if the mask bit is on.
lINTEGER - Set the payload length in the frame header, regardless of the - actual body length. + Set the payload length in the frame header, regardless of the actual body length.
pOFFSET,SECONDS - Pause for SECONDS seconds after OFFSET bytes. SECONDS can - be an integer or "f" to pause forever. + Pause for SECONDS seconds after OFFSET bytes. SECONDS can be an integer or "f" to pause + forever.
rVALUE - Set the raw frame payload. This disables masking, even if the - key is present. + Set the raw frame payload. This disables masking, even if the key is present.
- +
/api/clear_log @@ -147,18 +158,16 @@ disabled if no directory is specified:

/api/log
- Returns the current log buffer. At the moment the buffer size is 500 entries - - when the log grows larger than this, older entries are discarded. The returned + Returns the current log buffer. At the moment the buffer size is 500 entries - when the + log grows larger than this, older entries are discarded. The returned data is a JSON dictionary, with the form:
{ 'log': [ ENTRIES ] } 
- You can preview the JSON data returned for a log entry through the built-in web - interface. + You can preview the JSON data returned for a log entry through the built-in web interface.
- {% endblock %} diff --git a/libpathod/templates/docs_test.html b/libpathod/templates/docs_test.html index 25205d41..5db45f3f 100644 --- a/libpathod/templates/docs_test.html +++ b/libpathod/templates/docs_test.html @@ -1,52 +1,50 @@ -{% extends "docframe.html" %} -{% block body %} +{% extends "docframe.html" %} {% block body %} -
-
+

The libpathod.test module is a light, flexible testing layer for HTTP clients. + It works by firing up a Pathod instance in a separate thread, letting you use Pathod's + full abilities to generate responses, and then query Pathod's internal logs to establish + what happened. All the mechanics of startup, shutdown, finding free ports and so forth + are taken care of for you. +

-

The libpathod.test module is a light, flexible testing layer - for HTTP clients. It works by firing up a Pathod instance in a separate - thread, letting you use Pathod's full abilities to generate responses, - and then query Pathod's internal logs to establish what happened. All - the mechanics of startup, shutdown, finding free ports and so forth are - taken care of for you.

+

The canonical docs can be accessed using pydoc:

-

The canonical docs can be accessed using pydoc:

+
pydoc libpathod.test
-
pydoc libpathod.test
+

+ The remainder of this page demonstrates some common interaction patterns using + nose. These examples are also applicable with only minor modification to most + commonly used Python testing engines. +

-

The remainder of this page demonstrates some common interaction - patterns using nose. These examples - are also applicable with only minor modification to most commonly used - Python testing engines.

- -
-
-

Context Manager

- - {% include "examples_context.html" %} +
+ -
-
-
-

One instance per test

+ {% include "examples_context.html" %} + - {% include "examples_setup.html" %} +
+ -
-

One instance per suite

- {% include "examples_setupall.html" %} -
-
+ {% include "examples_setup.html" %} + +
+ -{% endblock %} + {% include "examples_setupall.html" %} +
+{% endblock %} diff --git a/libpathod/templates/download.html b/libpathod/templates/download.html index 2f6ed287..02ae9d41 100644 --- a/libpathod/templates/download.html +++ b/libpathod/templates/download.html @@ -1,53 +1,37 @@ -{% extends "frame.html" %} -{% block body %} - +{% extends "frame.html" %} {% block body %}

The easiest way to install pathod is to use pip:

pip install pathod
-

This will automatically pull in all the dependencies, and you should be - good to go.

- +

This will automatically pull in all the dependencies, and you should be good to go.

-
-

You can find the project source on GitHub:

+

You can find the project source on GitHub:

-

Please also use the github issue tracker to - report bugs.

+

Please also use the github issue tracker to report bugs.

-
- - {% endblock %} diff --git a/libpathod/templates/examples_context.html b/libpathod/templates/examples_context.html index 39146d37..afb3bd48 100644 --- a/libpathod/templates/examples_context.html +++ b/libpathod/templates/examples_context.html @@ -1,6 +1,7 @@
import requests
 from libpathod import test
 
+
 def test_simple():
     """
         Testing the requests module with
diff --git a/libpathod/templates/examples_setup.html b/libpathod/templates/examples_setup.html
index b80ad379..c2da1cd1 100644
--- a/libpathod/templates/examples_setup.html
+++ b/libpathod/templates/examples_setup.html
@@ -1,12 +1,15 @@
 
import requests
 from libpathod import test
 
+
 class Test:
+
     """
         Testing the requests module with
         a pathod instance started for
         each test.
     """
+
     def setUp(self):
         self.d = test.Daemon()
 
diff --git a/libpathod/templates/examples_setupall.html b/libpathod/templates/examples_setupall.html
index b7f79975..629d11e0 100644
--- a/libpathod/templates/examples_setupall.html
+++ b/libpathod/templates/examples_setupall.html
@@ -1,10 +1,12 @@
 
import requests
 from libpathod import test
 
+
 class Test:
+
     """
-        Testing the requests module with 
-        a single pathod instance started 
+        Testing the requests module with
+        a single pathod instance started
         for the test suite.
     """
     @classmethod
diff --git a/libpathod/templates/frame.html b/libpathod/templates/frame.html
index b5c5c67c..4223458d 100644
--- a/libpathod/templates/frame.html
+++ b/libpathod/templates/frame.html
@@ -1,9 +1,7 @@
-{% extends "layout.html" %}
-{% block content %}  
+{% extends "layout.html" %} {% block content %}
 
- {% block body %} - {% endblock %} + {% block body %} {% endblock %}
-{% endblock %} +{% endblock %} diff --git a/libpathod/templates/index.html b/libpathod/templates/index.html index 06a42dec..a85a4040 100644 --- a/libpathod/templates/index.html +++ b/libpathod/templates/index.html @@ -1,7 +1,4 @@ -{% extends "frame.html" %} -{% block body %} - - +{% extends "frame.html" %} {% block body %}

pathod: pathological HTTP

@@ -12,58 +9,52 @@
-
-

pathod

+

pathod

A pathological web daemon.

{% include "response_previewform.html" %} -
-
+
-

pathoc

+

pathoc

A perverse HTTP client.

{% include "request_previewform.html" %} -
- -
-
-
-

pip

- -
pip install pathod
+ +
+
+
+

pip

+
pip install pathod
+
-
-
-
-

source

-
-
- - {% endblock %} diff --git a/libpathod/templates/layout.html b/libpathod/templates/layout.html index 5278e5aa..b405ec34 100644 --- a/libpathod/templates/layout.html +++ b/libpathod/templates/layout.html @@ -1,6 +1,7 @@ - + + pathod @@ -14,60 +15,58 @@ - - - + + {% if syntaxerror %} -
-
- Error: -
-
-

{{ syntaxerror }}

-
{{ marked }}
-
+
+
+ Error:
+
+

{{ syntaxerror }}

+
{{ marked }}
+
+
{% elif error %} -
-
- Error: -
-
-

{{ error }}

-
+
+
+ Error: +
+
+

{{ error }}

+
{% else %} -
-
- Request: -
-
-
{{ output }}
-

Note: pauses are skipped when generating previews!

-
-
-{% endif %} - -{% endblock %} - - +
+
+ Request: +
+
+
{{ output }}
+

Note: pauses are skipped when generating previews!

+
+
+{% endif %} {% endblock %} diff --git a/libpathod/templates/request_previewform.html b/libpathod/templates/request_previewform.html index d3083735..0c6755de 100644 --- a/libpathod/templates/request_previewform.html +++ b/libpathod/templates/request_previewform.html @@ -1,23 +1,17 @@
- +
examples
-

Check out the complete language docs. Here - are some examples to get you started:

+

Check out the complete language docs. Here are some examples + to get you started:

- + @@ -39,7 +33,9 @@ - + diff --git a/libpathod/templates/response_preview.html b/libpathod/templates/response_preview.html index ce6a4098..bbce6d6c 100644 --- a/libpathod/templates/response_preview.html +++ b/libpathod/templates/response_preview.html @@ -1,6 +1,4 @@ -{% extends "frame.html" %} -{% block body %} - +{% extends "frame.html" %} {% block body %} @@ -15,34 +13,32 @@ {% if syntaxerror %} -
-
- Error: -
-
-

{{ syntaxerror }}

-
{{ marked }}
-
+
+
+ Error: +
+
+

{{ syntaxerror }}

+
{{ marked }}
+
{% elif error %} -
-
- Error: -
-
-

{{ error }}

-
+
+
+ Error: +
+
+

{{ error }}

+
{% else %} -
-
- Response: -
-
-
{{ output }}
-

Note: pauses are skipped when generating previews!

-
-
-{% endif %} - -{% endblock %} +
+
+ Response: +
+
+
{{ output }}
+

Note: pauses are skipped when generating previews!

+
+
+{% endif %} {% endblock %} diff --git a/libpathod/templates/response_previewform.html b/libpathod/templates/response_previewform.html index d91a2a67..51e17814 100644 --- a/libpathod/templates/response_previewform.html +++ b/libpathod/templates/response_previewform.html @@ -1,26 +1,18 @@
- - - {% if not nocraft %} - go - {% endif %} + + {% if not nocraft %} + go {% endif %} examples
-

Check out the complete language docs. Here - are some examples to get you started:

+

Check out the complete language docs. Here are some examples + to get you started:

get:/ Get path /Drop the connection randomly
+ +
- + @@ -35,8 +27,8 @@ - + @@ -66,18 +58,20 @@ - +
200 A basic HTTP 200 response.
200:b@100100 random bytes as the body. A Content-Lenght header is - added, so the disconnect is no longer needed.100 random bytes as the body. A Content-Lenght header is added, so the + disconnect is no longer needed.
200:b@100:h"Etag"="';drop table servers;" 200:b@100:h@1k,ascii_letters='foo' 100 ASCII bytes as the body, randomly generated 100k header name, with the value 'foo'.100 ASCII bytes as the body, randomly generated 100k header name, with + the value 'foo'.
+{% if not nocraft %} +{% endif %} -- cgit v1.2.3 From 7d7ae446a2543720c6da0698170a91bf20b6b62a Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Mon, 22 Jun 2015 16:11:28 +0200 Subject: http2: fix framedump argument usage --- libpathod/pathoc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libpathod/pathoc.py b/libpathod/pathoc.py index af43defc..e4aadd40 100644 --- a/libpathod/pathoc.py +++ b/libpathod/pathoc.py @@ -224,7 +224,7 @@ class Pathoc(tcp.TCPClient): "Please use OpenSSL >= 1.0.2. " "Pathoc might not be working as expected without ALPN." ) - self.protocol = http2.HTTP2Protocol(self) + self.protocol = http2.HTTP2Protocol(self, dump_frames=self.http2_framedump) else: # TODO: create HTTP or Websockets protocol self.protocol = None -- cgit v1.2.3 From 49707dd97f525bdce968678fa77be4b35951d008 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Mon, 22 Jun 2015 16:11:55 +0200 Subject: http2: implement embedded response --- libpathod/language/http2.py | 85 +++++++++++++++++++++++++-------------------- test/test_language_http2.py | 8 +++++ 2 files changed, 56 insertions(+), 37 deletions(-) diff --git a/libpathod/language/http2.py b/libpathod/language/http2.py index b206c0cf..6dd93d5f 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,33 +142,24 @@ class Times(base.Integer): preamble = "x" -class Request(_HTTP2Message): +class Response(_HTTP2Message): + unique_name = None comps = ( Header, + Body, ShortcutContentType, - ShortcutUserAgent, + ShortcutLocation, Raw, - # NestedResponse, - Body, - Times, ) - logattrs = ["method", "path"] def __init__(self, tokens): - super(Request, self).__init__(tokens) + super(Response, self).__init__(tokens) self.rendered_values = None + self.stream_id = 0 @property - def method(self): - return self.tok(Method) - - @property - def path(self): - return self.tok(Path) - - @property - def times(self): - return self.tok(Times) + def code(self): + return self.tok(Code) @classmethod def expr(cls): @@ -177,9 +167,7 @@ class Request(_HTTP2Message): atom = pp.MatchFirst(parts) resp = pp.And( [ - Method.expr(), - base.Sep, - Path.expr(), + Code.expr(), pp.ZeroOrMore(base.Sep + atom) ] ) @@ -196,9 +184,9 @@ class Request(_HTTP2Message): if body: body = body.string() - self.rendered_values = settings.protocol.create_request( - self.method.string(), - self.path.string(), + self.rendered_values = settings.protocol.create_response( + self.code.string(), + self.stream_id, headers, body) return self.rendered_values @@ -207,24 +195,42 @@ class Request(_HTTP2Message): return ":".join([i.spec() for i in self.tokens]) -class Response(_HTTP2Message): - unique_name = None +class NestedResponse(base.NestedMessage): + preamble = "s" + nest_type = Response + + +class Request(_HTTP2Message): comps = ( Header, - Body, ShortcutContentType, - ShortcutLocation, + ShortcutUserAgent, Raw, + NestedResponse, + Body, + Times, ) + logattrs = ["method", "path"] def __init__(self, tokens): - super(Response, self).__init__(tokens) + super(Request, self).__init__(tokens) self.rendered_values = None - self.stream_id = 0 @property - def code(self): - return self.tok(Code) + 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): @@ -232,7 +238,9 @@ class Response(_HTTP2Message): atom = pp.MatchFirst(parts) resp = pp.And( [ - Code.expr(), + Method.expr(), + base.Sep, + Path.expr(), pp.ZeroOrMore(base.Sep + atom) ] ) @@ -243,15 +251,19 @@ class Response(_HTTP2Message): 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_response( - self.code.string(), - self.stream_id, + self.rendered_values = settings.protocol.create_request( + self.method.string(), + path, headers, body) return self.rendered_values @@ -259,7 +271,6 @@ class Response(_HTTP2Message): 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 b25ad43c..3b36c01b 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") -- cgit v1.2.3 From b3b4a63b055c9d66db6663b932ae4e67a7f75e84 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Fri, 26 Jun 2015 21:24:21 +1200 Subject: Add a .jsbeautifyrc to prevent war --- .jsbeautifyrc | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .jsbeautifyrc diff --git a/.jsbeautifyrc b/.jsbeautifyrc new file mode 100644 index 00000000..ec740152 --- /dev/null +++ b/.jsbeautifyrc @@ -0,0 +1,22 @@ +{ + "indent_size": 4, + "indent_char": " ", + "eol": "\n", + "indent_level": 0, + "indent_with_tabs": false, + "preserve_newlines": true, + "max_preserve_newlines": 10, + "jslint_happy": false, + "space_after_anon_function": false, + "brace_style": "collapse", + "keep_array_indentation": false, + "keep_function_indentation": false, + "space_before_conditional": true, + "break_chained_methods": false, + "eval_code": false, + "unescape_strings": false, + "wrap_line_length": 80, + "wrap_attributes": "auto", + "wrap_attributes_indent_size": 4, + "end_with_newline": false +} -- cgit v1.2.3 From 427e6d23ef76ab9f113bce1d17e6a7a8cddb275c Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Fri, 26 Jun 2015 11:47:39 +0200 Subject: apply js-beautify changes selectivly --- .jsbeautifyrc | 2 +- libpathod/templates/docs_lang.html | 24 +++--- libpathod/templates/docs_lang_requests.html | 31 +++---- libpathod/templates/docs_lang_responses.html | 28 +++--- libpathod/templates/docs_lang_websockets.html | 15 ++-- libpathod/templates/docs_libpathod.html | 8 +- libpathod/templates/docs_pathoc.html | 118 +++++++++++++------------- libpathod/templates/docs_pathod.html | 75 ++++++++-------- libpathod/templates/docs_test.html | 14 +-- libpathod/templates/download.html | 4 +- libpathod/templates/layout.html | 3 + libpathod/templates/request_previewform.html | 6 +- libpathod/templates/response_previewform.html | 28 ++++-- 13 files changed, 188 insertions(+), 168 deletions(-) diff --git a/.jsbeautifyrc b/.jsbeautifyrc index ec740152..725c15ad 100644 --- a/.jsbeautifyrc +++ b/.jsbeautifyrc @@ -18,5 +18,5 @@ "wrap_line_length": 80, "wrap_attributes": "auto", "wrap_attributes_indent_size": 4, - "end_with_newline": false + "end_with_newline": true } diff --git a/libpathod/templates/docs_lang.html b/libpathod/templates/docs_lang.html index e3195939..a1d22aef 100644 --- a/libpathod/templates/docs_lang.html +++ b/libpathod/templates/docs_lang.html @@ -33,8 +33,8 @@

OFFSET

- Offsets are calculated relative to the base message, before any injections or other transforms - are applied. They have 3 flavors: + Offsets are calculated relative to the base message, before any injections or other + transforms are applied. They have 3 flavors:

    @@ -66,8 +66,8 @@

    Files

    - You can load a value from a specified file path. To do so, you have to specify a _staticdir_ - option to pathod on the command-line, like so: + You can load a value from a specified file path. To do so, you have to specify a + _staticdir_ option to pathod on the command-line, like so:

    pathod -d ~/myassets
    @@ -88,8 +88,8 @@

    An @-symbol lead-in specifies that generated data should be used. There are two components - to a generator specification - a size, and a data type. By default pathod assumes - a data type of "bytes". + to a generator specification - a size, and a data type. By default pathod + assumes a data type of "bytes".

    Here's a value specifier for generating 100 bytes: @@ -98,15 +98,15 @@

    - You can use standard suffixes to indicate larger values. Here, for instance, is a specifier - for generating 100 megabytes: + You can use standard suffixes to indicate larger values. Here, for instance, is a + specifier for generating 100 megabytes:

    @100m

    - Data is generated and served efficiently - if you really want to send a terabyte of data - to a client, pathod can do it. The supported suffixes are: + Data is generated and served efficiently - if you really want to send a terabyte + of data to a client, pathod can do it. The supported suffixes are:

    @@ -135,8 +135,8 @@

    - Data types are separated from the size specification by a comma. This specification generates - 100mb of ASCII: + Data types are separated from the size specification by a comma. This specification + generates 100mb of ASCII:

    @100m,ascii
    diff --git a/libpathod/templates/docs_lang_requests.html b/libpathod/templates/docs_lang_requests.html index 92921ec4..81aff535 100644 --- a/libpathod/templates/docs_lang_requests.html +++ b/libpathod/templates/docs_lang_requests.html @@ -7,16 +7,17 @@ method

    - A VALUE specifying the HTTP method to use. Standard - methods do not need to be enclosed in quotes, while non-standard methods - can be specified as quoted strings. + A VALUE specifying the HTTP method to + use. Standard methods do not need to be enclosed in quotes, while + non-standard methods can be specified as quoted strings.

    - The special method ws creates a valid websocket upgrade GET - request, and signals to pathoc to switch to websocket recieve mode - if the server responds correctly. Apart from that, websocket requests - are just like any other, and all aspects of the request can be over-ridden. + The special method ws creates a valid websocket upgrade + GET request, and signals to pathoc to switch to websocket recieve + mode if the server responds correctly. Apart from that, websocket + requests are just like any other, and all aspects of the request + can be over-ridden.

    @@ -66,8 +67,8 @@ bVALUE - Set the body. The appropriate Content-Length header is added automatically unless the - "r" flag is set. + Set the body. The appropriate Content-Length header is added automatically unless + the "r" flag is set. @@ -88,24 +89,24 @@ dOFFSET - HTTP/1 only - Disconnect after OFFSET bytes. + HTTP/1 only Disconnect after + OFFSET bytes. iOFFSET,VALUE - HTTP/1 only - Inject the specified value at the offset. + HTTP/1 only Inject the specified + value at the offset. pOFFSET,SECONDS - HTTP/1 only - Pause for SECONDS seconds after OFFSET bytes. SECONDS can be an integer or "f" to pause + HTTP/1 only Pause for SECONDS + seconds after OFFSET bytes. SECONDS can be an integer or "f" to pause forever. diff --git a/libpathod/templates/docs_lang_responses.html b/libpathod/templates/docs_lang_responses.html index 8939ab26..9a85ff1a 100644 --- a/libpathod/templates/docs_lang_responses.html +++ b/libpathod/templates/docs_lang_responses.html @@ -7,10 +7,10 @@

    An integer specifying the HTTP response code.

    - The special method ws creates a valid websocket upgrade response - (code 101), and moves pathod to websocket mode. Apart from that, websocket - responses are just like any other, and all aspects of the response - can be over-ridden. + The special method ws creates a valid websocket upgrade + response (code 101), and moves pathod to websocket mode. Apart + from that, websocket responses are just like any other, and all + aspects of the response can be over-ridden.

    @@ -18,8 +18,8 @@ mVALUE - HTTP/1 only - HTTP Reason message. Automatically chosen according to the response code if not specified. + HTTP/1 only HTTP Reason message. + Automatically chosen according to the response code if not specified. @@ -55,32 +55,32 @@ bVALUE - Set the body. The appropriate Content-Length header is added automatically unless the - "r" flag is set. + Set the body. The appropriate Content-Length header is added automatically unless + the "r" flag is set. dOFFSET - HTTP/1 only - Disconnect after OFFSET bytes. + HTTP/1 only Disconnect after + OFFSET bytes. iOFFSET,VALUE - HTTP/1 only - Inject the specified value at the offset. + HTTP/1 only Inject the specified + value at the offset. pOFFSET,SECONDS - HTTP/1 only - Pause for SECONDS seconds after OFFSET bytes. SECONDS can be an integer or "f" to pause + HTTP/1 only Pause for SECONDS + seconds after OFFSET bytes. SECONDS can be an integer or "f" to pause forever. diff --git a/libpathod/templates/docs_lang_websockets.html b/libpathod/templates/docs_lang_websockets.html index 682f4cc8..dd318e0b 100644 --- a/libpathod/templates/docs_lang_websockets.html +++ b/libpathod/templates/docs_lang_websockets.html @@ -15,8 +15,8 @@ cINTEGER - Set the op code. This can either be an integer from 0-15, or be one of the following opcode - names: text (the default), + Set the op code. This can either be an integer from 0-15, or be one of the following + opcode names: text (the default), continue, binary, close, ping, pong. @@ -47,9 +47,10 @@ kVALUE - Set the masking key. The resulting value must be exactly 4 bytes long. The special form - knone specifies that no key should be set, even - if the mask bit is on. + Set the masking key. The resulting value must be exactly 4 bytes long. The special + form + knone specifies that no key should be set, even if the mask + bit is on. @@ -70,8 +71,8 @@ pOFFSET,SECONDS - Pause for SECONDS seconds after OFFSET bytes. SECONDS can be an integer or "f" to pause - forever. + Pause for SECONDS seconds after OFFSET bytes. SECONDS can be an integer or "f" to + pause forever. diff --git a/libpathod/templates/docs_libpathod.html b/libpathod/templates/docs_libpathod.html index 72b24e83..6d504fe5 100644 --- a/libpathod/templates/docs_libpathod.html +++ b/libpathod/templates/docs_libpathod.html @@ -9,10 +9,10 @@

    - Behind the pathod and pathoc command-line tools lurks libpathod, a - powerful library for manipulating and serving HTTP requests and responses. - The canonical documentation for the library is in the code, and can be accessed - using pydoc. + Behind the pathod and pathoc command-line tools lurks libpathod, + a powerful library for manipulating and serving HTTP requests and responses. + The canonical documentation for the library is in the code, and can be + accessed using pydoc.

    diff --git a/libpathod/templates/docs_pathoc.html b/libpathod/templates/docs_pathoc.html index e4c12873..d38c3a77 100644 --- a/libpathod/templates/docs_pathoc.html +++ b/libpathod/templates/docs_pathoc.html @@ -7,12 +7,12 @@

    - Pathoc is a perverse HTTP daemon designed to let you craft almost any conceivable HTTP - request, including ones that creatively violate the standards. HTTP requests are specified - using a - small, terse language, which pathod shares with its server-side - twin pathod. To view pathoc's complete range of options, - use the command-line help: + Pathoc is a perverse HTTP daemon designed to let you craft almost any conceivable + HTTP request, including ones that creatively violate the standards. HTTP requests + are specified using a + small, terse language, which pathod shares with + its server-side twin pathod. To view pathoc's complete + range of options, use the command-line help:

    pathoc --help
    @@ -27,8 +27,8 @@
    pathoc hostname request [request ...]

    - That is, we specify the hostname to connect to, followed by one or more requests. Lets - start with a simple example: + That is, we specify the hostname to connect to, followed by one or more requests. + Lets start with a simple example:

    @@ -36,10 +36,10 @@
         

    - Here, we make a GET request to the path / on port 80 of google.com. Pathoc's output tells - us that the server responded with a 301. We can tell pathoc to connect using SSL, - in which case the default port is changed to 443 (you can over-ride the default - port with the -p command-line option): + Here, we make a GET request to the path / on port 80 of google.com. Pathoc's output + tells us that the server responded with a 301. We can tell pathoc to connect + using SSL, in which case the default port is changed to 443 (you can over-ride + the default port with the -p command-line option):

    @@ -64,8 +64,8 @@
         

    - In this case, pathoc issues the specified requests over the same TCP connection - so in - the above example only one connection is made to google.com + In this case, pathoc issues the specified requests over the same TCP connection - + so in the above example only one connection is made to google.com

    The other way to issue multiple requets is to use the -n flag:

    @@ -76,8 +76,8 @@

- The output is identical, but two separate TCP connections are made to the upstream server. - These two specification styles can be combined: + The output is identical, but two separate TCP connections are made to the upstream + server. These two specification styles can be combined:

@@ -96,8 +96,9 @@
     

- The combination of pathoc's powerful request specification language and a few of its command-line - options makes for quite a powerful basic fuzzer. Here's an example: + The combination of pathoc's powerful request specification language and a few of + its command-line options makes for quite a powerful basic fuzzer. Here's + an example:

@@ -105,18 +106,18 @@
     

- The request specified here is a valid GET with a body consisting of 10 random bytes, but - with 1 random byte inserted in a random place. This could be in the headers, in - the initial request line, or in the body itself. There are a few things to note - here: + The request specified here is a valid GET with a body consisting of 10 random bytes, + but with 1 random byte inserted in a random place. This could be in the headers, + in the initial request line, or in the body itself. There are a few things + to note here:

  • - Corrupting the request in this way will often make the server enter a state where it's - awaiting more input from the client. This is where the - -t option comes in, which sets a timeout that causes pathoc to disconnect - after two seconds. + Corrupting the request in this way will often make the server enter a state where + it's awaiting more input from the client. This is where the + -t option comes in, which sets a timeout that causes pathoc to + disconnect after two seconds.
  • @@ -124,16 +125,16 @@
  • - The -I option tells pathoc to ignore HTTP 200 response codes. You can - use this to fine-tune what pathoc considers to be an exceptional condition, - and therefore log-worthy. + The -I option tells pathoc to ignore HTTP 200 response codes. + You can use this to fine-tune what pathoc considers to be an exceptional + condition, and therefore log-worthy.
  • - The -e option tells pathoc to print an explanation of each logged request, - in the form of an expanded pathoc specification with all random portions and - automatic header additions resolved. This lets you precisely replay a request - that triggered an error. + The -e option tells pathoc to print an explanation of each logged + request, in the form of an expanded pathoc specification with all random + portions and automatic header additions resolved. This lets you precisely + replay a request that triggered an error.
@@ -146,25 +147,26 @@

Pathoc has a reasonably sophisticated suite of features for interacting with proxies. - The proxy request syntax very closely mirrors that of straight HTTP, which means - that it is possible to make proxy-style requests using pathoc without any additional - syntax, by simply specifying a full URL instead of a simple path: + The proxy request syntax very closely mirrors that of straight HTTP, which + means that it is possible to make proxy-style requests using pathoc without + any additional syntax, by simply specifying a full URL instead of a simple + path:

> pathoc -p 8080 localhost "get:'http://google.com'"

- Another common use case is to use an HTTP CONNECT request to probe remote servers via - a proxy. This is done with the -c command-line option, which allows - you to specify a remote host and port pair: + Another common use case is to use an HTTP CONNECT request to probe remote servers + via a proxy. This is done with the -c command-line option, + which allows you to specify a remote host and port pair:

> pathoc -c google.com:80 -p 8080 localhost get:/

Note that pathoc does not negotiate SSL without being explictly instructed - to do so. If you're making a CONNECT request to an SSL-protected resource, you - must also pass the -s flag: + to do so. If you're making a CONNECT request to an SSL-protected resource, + you must also pass the -s flag:

> pathoc -sc google.com:443 -p 8080 localhost get:/
@@ -177,33 +179,33 @@

- One interesting feature of the Request sppecification language is that you can embed a - response specifcation in it, which is then added to the request path. Here's an - example: + One interesting feature of the Request sppecification language is that you can embed + a response specifcation in it, which is then added to the request path. Here's + an example:

> pathoc localhost:9999 "get:/p/:s'401:ir,@1'"

- This crafts a request that connects to the pathod server, and which then crafts a response - that generates a 401, with one random byte embedded at a random point. The response - specification is parsed and expanded by pathoc, so you see syntax errors immediately. - This really becomes handy when combined with the -e flag to show - the expanded request: + This crafts a request that connects to the pathod server, and which then crafts a + response that generates a 401, with one random byte embedded at a random + point. The response specification is parsed and expanded by pathoc, so you + see syntax errors immediately. This really becomes handy when combined with + the -e flag to show the expanded request:

         > > pathoc -e localhost:9999 "get:/p/:s'401:ir,@1'" >> Spec: get:/p/:s'401:i15,\'o\':h\'Content-Length\'=\'0\'':h'Content-Length'='0'
         << 401 Unoauthorized: 0 bytes 
-

- Note that the embedded response has been resolved before being - sent to the server, so that "ir,@1" (embed a random byte at a random location) - has become "i15,\'o\'" (embed the character "o" at offset 15). You now - have a pathoc request specification that is precisely reproducable, even - with random components. This feature comes in terribly handy when testing - a proxy, since you can now drive the server repsonse completely from the - client, and have a complete log of reproducible requests to analyse afterwards. -

+

+ Note that the embedded response has been resolved before being sent + to the server, so that "ir,@1" (embed a random byte at a random location) + has become "i15,\'o\'" (embed the character "o" at offset 15). You now have + a pathoc request specification that is precisely reproducable, even with + random components. This feature comes in terribly handy when testing a proxy, + since you can now drive the server repsonse completely from the client, and + have a complete log of reproducible requests to analyse afterwards. +

{% endblock %} diff --git a/libpathod/templates/docs_pathod.html b/libpathod/templates/docs_pathod.html index 21e7919a..0d0ae933 100644 --- a/libpathod/templates/docs_pathod.html +++ b/libpathod/templates/docs_pathod.html @@ -10,8 +10,8 @@ Pathod is a pathological HTTP daemon designed to let you craft almost any conceivable HTTP response, including ones that creatively violate the standards. HTTP responses are specified using a - small, terse language, which pathod shares with its evil - twin pathoc. + small, terse language, which pathod shares with + its evil twin pathoc.

@@ -24,27 +24,27 @@
./pathod

- By default, the service listens on port 9999 of localhost. Pathod's documentation is self-hosting, - and the pathod daemon exposes an interface that lets you play with the specifciation - language, preview what responses and requests would look like on the wire, and - view internal logs. To access all of this, just fire up your browser, and point - it to the following URL: + By default, the service listens on port 9999 of localhost. Pathod's documentation + is self-hosting, and the pathod daemon exposes an interface that lets you + play with the specifciation language, preview what responses and requests + would look like on the wire, and view internal logs. To access all of this, + just fire up your browser, and point it to the following URL:

http://localhost:9999

- The default crafting anchor point is the path /p/. Anything after this - URL prefix is treated as a response specifier. So, hitting the following URL will - generate an HTTP 200 response with 100 bytes of random data: + The default crafting anchor point is the path /p/. Anything after + this URL prefix is treated as a response specifier. So, hitting the following + URL will generate an HTTP 200 response with 100 bytes of random data:

http://localhost:9999/p/200:b@100

- See the language documentation to get (much) fancier. - The pathod daemon also takes a range of configuration options. To view those, - use the command-line help: + See the language documentation to get (much) + fancier. The pathod daemon also takes a range of configuration options. To + view those, use the command-line help:

./pathod --help
@@ -57,17 +57,17 @@

- Pathod automatically responds to both straight HTTP and proxy requests. For proxy requests, - the upstream host is ignored, and the path portion of the URL is used to match - anchors. This lets you test software that supports a proxy configuration by spoofing - responses from upstream servers. + Pathod automatically responds to both straight HTTP and proxy requests. For proxy + requests, the upstream host is ignored, and the path portion of the URL is + used to match anchors. This lets you test software that supports a proxy + configuration by spoofing responses from upstream servers.

By default, we treat all proxy CONNECT requests as HTTPS traffic, serving the response - using either pathod's built-in certificates, or the cert/key pair specified by - the user. You can over-ride this behaviour if you're testing a client that makes - a non-SSL CONNECT request using the -C command-line option. + using either pathod's built-in certificates, or the cert/key pair specified + by the user. You can over-ride this behaviour if you're testing a client + that makes a non-SSL CONNECT request using the -C command-line option.

@@ -78,16 +78,16 @@

- Anchors provide an alternative to specifying the response in the URL. Instead, you attach - a response to a pre-configured anchor point, specified with a regex. When a URL - matching the regex is requested, the specified response is served. + Anchors provide an alternative to specifying the response in the URL. Instead, you + attach a response to a pre-configured anchor point, specified with a regex. + When a URL matching the regex is requested, the specified response is served.

./pathod -a "/foo=200"

- Here, "/foo" is the regex specifying the anchor path, and the part after the "=" is a - response specifier. + Here, "/foo" is the regex specifying the anchor path, and the part after the "=" + is a response specifier.

@@ -98,11 +98,11 @@

- There are two operators in the language that load - contents from file - the + operator to load an entire request specification - from file, and the > value specifier. In pathod, both of these operators - are restricted to a directory specified at startup, or disabled if no directory - is specified:

+ There are two operators in the language that + load contents from file - the + operator to load an entire request + specification from file, and the > value specifier. In pathod, + both of these operators are restricted to a directory specified at startup, + or disabled if no directory is specified:

./pathod -d ~/staticdir"
@@ -131,8 +131,8 @@

- pathod exposes a simple API, intended to make it possible to drive and inspect the daemon - remotely for use in unit testing and the like. + pathod exposes a simple API, intended to make it possible to drive and inspect the + daemon remotely for use in unit testing and the like.

@@ -158,13 +158,12 @@ /api/log diff --git a/libpathod/templates/docs_test.html b/libpathod/templates/docs_test.html index 5db45f3f..0502c984 100644 --- a/libpathod/templates/docs_test.html +++ b/libpathod/templates/docs_test.html @@ -7,10 +7,10 @@

The libpathod.test module is a light, flexible testing layer for HTTP clients. - It works by firing up a Pathod instance in a separate thread, letting you use Pathod's - full abilities to generate responses, and then query Pathod's internal logs to establish - what happened. All the mechanics of startup, shutdown, finding free ports and so forth - are taken care of for you. + It works by firing up a Pathod instance in a separate thread, letting you use + Pathod's full abilities to generate responses, and then query Pathod's internal + logs to establish what happened. All the mechanics of startup, shutdown, finding + free ports and so forth are taken care of for you.

The canonical docs can be accessed using pydoc:

@@ -19,9 +19,9 @@

The remainder of this page demonstrates some common interaction patterns using - nose. These examples are also applicable with only minor modification to most - commonly used Python testing engines. + nose. These examples are + also applicable with only minor modification to most commonly used Python testing + engines.

diff --git a/libpathod/templates/download.html b/libpathod/templates/download.html index 02ae9d41..bd8950e8 100644 --- a/libpathod/templates/download.html +++ b/libpathod/templates/download.html @@ -8,7 +8,9 @@
pip install pathod
-

This will automatically pull in all the dependencies, and you should be good to go.

+

+ This will automatically pull in all the dependencies, and you should be good to go. +

diff --git a/libpathod/templates/layout.html b/libpathod/templates/layout.html index b405ec34..af2857b1 100644 --- a/libpathod/templates/layout.html +++ b/libpathod/templates/layout.html @@ -19,6 +19,7 @@ padding-top: 60px; padding-bottom: 40px; } +
- Returns the current log buffer. At the moment the buffer size is 500 entries - when the - log grows larger than this, older entries are discarded. The returned - data is a JSON dictionary, with the form: + Returns the current log buffer. At the moment the buffer size is 500 entries - when + the log grows larger than this, older entries are discarded. + The returned data is a JSON dictionary, with the form: -
{ 'log': [ ENTRIES ] } 
- - You can preview the JSON data returned for a log entry through the built-in web interface. +
{ 'log': [ ENTRIES ] } 
You can preview the JSON data + returned for a log entry through the built-in web interface.