aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.appveyor.yml11
-rw-r--r--.gitignore2
-rw-r--r--.jsbeautifyrc22
-rw-r--r--.landscape.yml2
-rw-r--r--libpathod/language/http.py12
-rw-r--r--libpathod/language/http2.py197
-rw-r--r--libpathod/pathoc.py2
-rw-r--r--libpathod/templates/about.html40
-rw-r--r--libpathod/templates/docframe.html22
-rw-r--r--libpathod/templates/docs_lang.html306
-rw-r--r--libpathod/templates/docs_lang_requests.html114
-rw-r--r--libpathod/templates/docs_lang_responses.html70
-rw-r--r--libpathod/templates/docs_lang_websockets.html29
-rw-r--r--libpathod/templates/docs_libpathod.html24
-rw-r--r--libpathod/templates/docs_pathoc.html270
-rw-r--r--libpathod/templates/docs_pathod.html160
-rw-r--r--libpathod/templates/docs_test.html70
-rw-r--r--libpathod/templates/download.html36
-rw-r--r--libpathod/templates/examples_context.html1
-rw-r--r--libpathod/templates/examples_setup.html3
-rw-r--r--libpathod/templates/examples_setupall.html6
-rw-r--r--libpathod/templates/frame.html8
-rw-r--r--libpathod/templates/index.html51
-rw-r--r--libpathod/templates/layout.html88
-rw-r--r--libpathod/templates/libpathod_pathoc.html3
-rw-r--r--libpathod/templates/log.html59
-rw-r--r--libpathod/templates/onelog.html14
-rw-r--r--libpathod/templates/request_preview.html58
-rw-r--r--libpathod/templates/request_previewform.html22
-rw-r--r--libpathod/templates/response_preview.html56
-rw-r--r--libpathod/templates/response_previewform.html42
-rw-r--r--test/test_language_http2.py60
32 files changed, 1006 insertions, 854 deletions
diff --git a/.appveyor.yml b/.appveyor.yml
new file mode 100644
index 00000000..4e690c06
--- /dev/null
+++ b/.appveyor.yml
@@ -0,0 +1,11 @@
+version: '{build}'
+shallow_clone: true
+environment:
+ matrix:
+ - PYTHON: "C:\\Python27"
+install:
+ - "%PYTHON%\\Scripts\\pip install --src . -r requirements.txt"
+ - "%PYTHON%\\python -c \"from OpenSSL import SSL; print(SSL.SSLeay_version(SSL.SSLEAY_VERSION))\""
+build: off # Not a C# project
+test_script:
+ - "%PYTHON%\\Scripts\\nosetests" \ No newline at end of file
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/.jsbeautifyrc b/.jsbeautifyrc
new file mode 100644
index 00000000..725c15ad
--- /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": true
+}
diff --git a/.landscape.yml b/.landscape.yml
index ccaa5fc3..9a3b615f 100644
--- a/.landscape.yml
+++ b/.landscape.yml
@@ -13,4 +13,4 @@ pylint:
- too-many-public-methods
- too-many-return-statements
- too-many-statements
- - unpacking-non-sequence
+ - unpacking-non-sequence \ No newline at end of file
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..6dd93d5f 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,40 @@ 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,45 +142,24 @@ class Times(base.Integer):
preamble = "x"
-class Code(base.Integer):
- pass
-
-
-class Request(message.Message):
+class Response(_HTTP2Message):
+ unique_name = None
comps = (
Header,
Body,
- Times,
+ ShortcutContentType,
+ ShortcutLocation,
+ Raw,
)
- 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 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 []
+ def code(self):
+ return self.tok(Code)
@classmethod
def expr(cls):
@@ -104,18 +167,13 @@ class Request(message.Message):
atom = pp.MatchFirst(parts)
resp = pp.And(
[
- Method.expr(),
- base.Sep,
- Path.expr(),
+ Code.expr(),
pp.ZeroOrMore(base.Sep + atom)
]
)
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
@@ -126,10 +184,10 @@ class Request(message.Message):
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?!
+ self.rendered_values = settings.protocol.create_response(
+ self.code.string(),
+ self.stream_id,
+ headers,
body)
return self.rendered_values
@@ -137,36 +195,42 @@ class Request(message.Message):
return ":".join([i.spec() for i in self.tokens])
-class Response(message.Message):
- unique_name = None
+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(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 headers(self):
- return self.toks(Header)
+ def path(self):
+ return self.tok(Path)
@property
- def body(self):
- return self.tok(Body)
+ def nested_response(self):
+ return self.tok(NestedResponse)
@property
- def actions(self):
- return []
-
- def resolve(self, settings, msg=None):
- return self
+ def times(self):
+ return self.tok(Times)
@classmethod
def expr(cls):
@@ -174,7 +238,9 @@ class Response(message.Message):
atom = pp.MatchFirst(parts)
resp = pp.And(
[
- Code.expr(),
+ Method.expr(),
+ base.Sep,
+ Path.expr(),
pp.ZeroOrMore(base.Sep + atom)
]
)
@@ -185,23 +251,26 @@ class Response(message.Message):
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,
- headers, # TODO: parse that into a dict?!
+ 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/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
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 %}
<section>
-<div class="page-header">
- <h1>
- About
- </h1>
-</div>
-<div class="row">
- <div class="span6">
- <div>
- <p>pathod is developed by <a href="http://corte.si">Aldo
- Cortesi</a>.</p>
- </div>
+ <div class="page-header">
+ <h1>About</h1>
+ </div>
+ <div class="row">
+ <div class="span6">
+ <div>
+ <p>pathod is developed by <a href="http://corte.si">Aldo Cortesi</a>.</p>
+ </div>
- <div>
- <ul>
- <li>email: <a href="mailto:aldo@corte.si">aldo@corte.si</a></li>
- <li>twitter: <a href="http://twitter.com/cortesi">@cortesi</a></li>
- <li>github: <a href="https://github.com/cortesi">github.com/cortesi</a></li>
- </ul>
+ <div>
+ <ul>
+ <li>email: <a href="mailto:aldo@corte.si">aldo@corte.si</a></li>
+ <li>twitter: <a href="http://twitter.com/cortesi">@cortesi</a></li>
+ <li>github: <a href="https://github.com/cortesi">github.com/cortesi</a></li>
+ </ul>
+ </div>
</div>
</div>
-</div>
</section>
-
-
{% 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 %}
<div class="row">
<div class="span3">
<div class="well sidebar-nav">
<ul class="nav nav-list">
- <li {{subs("pathod")}}><a href="/docs/pathod">pathod</a></li>
- <li {{subs("pathoc")}}><a href="/docs/pathoc">pathoc</a></li>
- <li {{subs("lang")}}><a href="/docs/language">language</a></li>
- <li {{subs("libpathod")}}><a href="/docs/libpathod">libpathod</a></li>
- <li {{subs("test")}}><a href="/docs/test">libpathod.test</a></li>
+ <li {{subs( "pathod")}}><a href="/docs/pathod">pathod</a></li>
+ <li {{subs( "pathoc")}}><a href="/docs/pathoc">pathoc</a></li>
+ <li {{subs( "lang")}}><a href="/docs/language">language</a></li>
+ <li {{subs( "libpathod")}}><a href="/docs/libpathod">libpathod</a></li>
+ <li {{subs( "test")}}><a href="/docs/test">libpathod.test</a></li>
</ul>
</div>
</div>
<div class="span9">
- {% block body %}
- {% endblock %}
+ {% block body %} {% endblock %}
</div>
</div>
-{% endblock %}
+{% endblock %}
diff --git a/libpathod/templates/docs_lang.html b/libpathod/templates/docs_lang.html
index ce778dc9..a1d22aef 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 %}
<div class="page-header">
- <h1>
+ <h1>
Language Spec
<small>The mini-language at the heart of pathoc and pathod.</small>
</h1>
</div>
<ul class="nav nav-tabs">
- <li class="active" ><a href="#specifying_requests" data-toggle="tab">HTTP Requests</a></li>
- <li><a href="#specifying_responses" data-toggle="tab">HTTP Responses</a></li>
- <li><a href="#websockets" data-toggle="tab">Websocket Frames</a></li>
+ <li class="active"><a href="#specifying_requests" data-toggle="tab">HTTP Requests</a></li>
+ <li><a href="#specifying_responses" data-toggle="tab">HTTP Responses</a></li>
+ <li><a href="#websockets" data-toggle="tab">Websocket Frames</a></li>
</ul>
<div class="tab-content">
@@ -28,151 +26,171 @@
<section id="features">
<div class="page-header">
- <h1>Features</h1>
+ <h1>Features</h1>
</div>
- <a id="offsetspec"></a>
- <h2>OFFSET</h2>
-
- <p>Offsets are calculated relative to the base message, before any
- injections or other transforms are applied. They have 3 flavors:</p>
-
- <ul>
- <li>An integer byte offset </li>
- <li><b>r</b> for a random location</li>
- <li><b>a</b> for the end of the message</li>
- </ul>
-
- <a id="valuespec"></a>
- <h2>VALUE</h2>
+ <a id="offsetspec"></a>
+ <h2>OFFSET</h2>
- <h3>Literals</h3>
+ <p>
+ Offsets are calculated relative to the base message, before any injections or other
+ transforms are applied. They have 3 flavors:
+ </p>
- <p>Literal values are specified as a quoted strings: </p>
+ <ul>
+ <li>An integer byte offset </li>
+ <li><b>r</b> for a random location</li>
+ <li><b>a</b> for the end of the message</li>
+ </ul>
- <pre class="example">"foo"</pre>
+ <a id="valuespec"></a>
+ <h2>VALUE</h2>
- <p>Either single or double quotes are accepted, and quotes can be escaped with
- backslashes within the string:</p>
+ <h3>Literals</h3>
- <pre class="example">'fo\'o'</pre>
+ <p>Literal values are specified as a quoted strings: </p>
- <p>Literal values can contain Python-style backslash escape sequences:</p>
+ <pre class="example">"foo"</pre>
- <pre class="example">'foo\r\nbar'</pre>
-
-
- <h3>Files</h3>
-
- <p>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: </p>
-
- <pre class="example">pathod -d ~/myassets</pre>
-
- <p>All paths are relative paths under this directory. File loads are indicated by
- starting the value specifier with the left angle bracket:
-
- <pre class="example">&lt;my/path</pre></p>
-
- <p>The path value can also be a quoted string, with the same syntax as literals:</p>
-
- <pre class="example">&lt;"my/path"</pre>
-
-
- <h3>Generated values</h3>
-
- <p>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". </p>
-
- <p>Here's a value specifier for generating 100 bytes:
-
- <pre class="example">@100</pre></p>
-
- <p>You can use standard suffixes to indicate larger values. Here, for instance, is
- a specifier for generating 100 megabytes:</p>
-
- <pre class="example">@100m</pre>
-
- <p>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:</p>
-
-
- <table class="table table-bordered">
- <tbody >
- <tr>
- <td>b</td> <td>1024**0 (bytes)</td>
- </tr>
- <tr>
- <td>k</td> <td>1024**1 (kilobytes)</td>
- </tr>
- <tr>
- <td>m</td> <td>1024**2 (megabytes)</td>
- </tr>
- <tr>
- <td>g</td> <td>1024**3 (gigabytes)</td>
- </tr>
- <tr>
- <td>t</td> <td>1024**4 (terabytes)</td>
- </tr>
- </tbody>
- </table>
-
- <p>Data types are separated from the size specification by a comma. This
- specification generates 100mb of ASCII:</p>
-
- <pre class="example">@100m,ascii</pre>
-
- <p>Supported data types are:</p>
-
- <table class="table table-bordered">
- <tbody >
- <tr>
- <td>ascii</td>
- <td>All ASCII characters</td>
- </tr>
- <tr>
- <td>ascii_letters</td>
- <td>A-Za-z</td>
- </tr>
- <tr>
- <td>ascii_lowercase</td>
- <td>a-z</td>
- </tr>
- <tr>
- <td>ascii_uppercase</td>
- <td>A-Z</td>
- </tr>
- <tr>
- <td>bytes</td>
- <td>All 256 byte values</td>
- </tr>
- <tr>
- <td>digits</td>
- <td>0-9</td>
- </tr>
- <tr>
- <td>hexdigits</td>
- <td>0-f</td>
- </tr>
- <tr>
- <td>octdigits</td>
- <td>0-7</td>
- </tr>
- <tr>
- <td>punctuation</td>
- <td>
- <pre>!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~</pre>
- </td>
- </tr>
- <tr>
- <td>whitespace</td>
- <td>
- <pre>\t\n\x0b\x0c\r and space</pre>
- </td>
- </tr>
- </tbody>
- </table>
+ <p>
+ Either single or double quotes are accepted, and quotes can be escaped with backslashes
+ within the string:
+ </p>
+
+ <pre class="example">'fo\'o'</pre>
+
+ <p>Literal values can contain Python-style backslash escape sequences:</p>
+
+ <pre class="example">'foo\r\nbar'</pre>
+
+ <h3>Files</h3>
+
+ <p>
+ 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:
+ </p>
+
+ <pre class="example">pathod -d ~/myassets</pre>
+
+ <p>
+ All paths are relative paths under this directory. File loads are indicated by starting
+ the value specifier with the left angle bracket:
+ </p>
+
+ <pre class="example">&lt;my/path</pre>
+
+ <p>The path value can also be a quoted string, with the same syntax as literals:</p>
+
+ <pre class="example">&lt;"my/path"</pre>
+
+
+ <h3>Generated values</h3>
+
+ <p>
+ 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".
+ </p>
+
+ <p>Here's a value specifier for generating 100 bytes:
+
+ <pre class="example">@100</pre>
+ </p>
+
+ <p>
+ You can use standard suffixes to indicate larger values. Here, for instance, is a
+ specifier for generating 100 megabytes:
+ </p>
+
+ <pre class="example">@100m</pre>
+
+ <p>
+ 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:
+ </p>
+
+ <table class="table table-bordered">
+ <tbody>
+ <tr>
+ <td>b</td>
+ <td>1024**0 (bytes)</td>
+ </tr>
+ <tr>
+ <td>k</td>
+ <td>1024**1 (kilobytes)</td>
+ </tr>
+ <tr>
+ <td>m</td>
+ <td>1024**2 (megabytes)</td>
+ </tr>
+ <tr>
+ <td>g</td>
+ <td>1024**3 (gigabytes)</td>
+ </tr>
+ <tr>
+ <td>t</td>
+ <td>1024**4 (terabytes)</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <p>
+ Data types are separated from the size specification by a comma. This specification
+ generates 100mb of ASCII:
+ </p>
+
+ <pre class="example">@100m,ascii</pre>
+
+ <p>Supported data types are:</p>
+
+ <table class="table table-bordered">
+ <tbody>
+ <tr>
+ <td>ascii</td>
+ <td>All ASCII characters</td>
+ </tr>
+ <tr>
+ <td>ascii_letters</td>
+ <td>A-Za-z</td>
+ </tr>
+ <tr>
+ <td>ascii_lowercase</td>
+ <td>a-z</td>
+ </tr>
+ <tr>
+ <td>ascii_uppercase</td>
+ <td>A-Z</td>
+ </tr>
+ <tr>
+ <td>bytes</td>
+ <td>All 256 byte values</td>
+ </tr>
+ <tr>
+ <td>digits</td>
+ <td>0-9</td>
+ </tr>
+ <tr>
+ <td>hexdigits</td>
+ <td>0-f</td>
+ </tr>
+ <tr>
+ <td>octdigits</td>
+ <td>0-7</td>
+ </tr>
+ <tr>
+ <td>punctuation</td>
+ <td>
+ <pre>!"#$%&\'()*+,-./:;
+ <=>?@[\\]^_`{|}~</pre>
+ </td>
+ </tr>
+ <tr>
+ <td>whitespace</td>
+ <td>
+ <pre>\t\n\x0b\x0c\r and space</pre>
+ </td>
+ </tr>
+ </tbody>
+ </table>
</section>
-
{% endblock %}
diff --git a/libpathod/templates/docs_lang_requests.html b/libpathod/templates/docs_lang_requests.html
index fe73f0af..81aff535 100644
--- a/libpathod/templates/docs_lang_requests.html
+++ b/libpathod/templates/docs_lang_requests.html
@@ -1,113 +1,113 @@
-
-<pre class="example">method:path:[colon-separated list of features]</pre></p>
+<pre class="example">method:path:[colon-separated list of features]</pre>
+</p>
<table class="table table-bordered">
- <tbody >
-
+ <tbody>
<tr>
- <td> method </td>
+ <td>method</td>
<td>
-
- <p>A <a href="#valuespec">VALUE</a> 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.</p>
-
- <p>The special method <b>ws</b> 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.</p>
+ <p>
+ A <a href="#valuespec">VALUE</a> 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.
+ </p>
+
+ <p>
+ The special method <b>ws</b> 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.
+ </p>
</td>
</tr>
<tr>
- <td> b<a href="#valuespec">VALUE</a> </td>
+ <td>h<a href="#valuespec">VALUE</a>=<a href="#valuespec">VALUE</a></td>
<td>
- Set the body. The appropriate Content-Length header is
- added automatically unless the "r" flag is set.
+ Set a header.
</td>
</tr>
<tr>
- <td> c<a href="#valuespec">VALUE</a> </td>
+ <td>r</td>
<td>
- 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.
</td>
</tr>
<tr>
- <td> d<a href="#offsetspec">OFFSET</a> </td>
+ <td>c<a href="#valuespec">VALUE</a></td>
<td>
- Disconnect after OFFSET bytes.
+ A shortcut for setting the Content-Type header. Equivalent to h"Content-Type"=VALUE
</td>
</tr>
<tr>
- <td> h<a href="#valuespec">VALUE</a>=<a href="#valuespec">VALUE</a> </td>
+ <td>u<a href="#valuespec">VALUE</a>
+ <br> uSHORTCUT
+ </td>
+
<td>
- Set a header.
+ Set a User-Agent header on this request. You can specify either a complete
+ <a href="#valuespec">VALUE</a>, or a User-Agent shortcut:
+
+ <table class="table table-condensed">
+ {% for i in uastrings %}
+ <tr>
+ <td><b>{{ i[1] }}</b></td>
+ <td>{{ i[0] }}</td>
+ </tr>
+ {% endfor %}
+ </table>
</td>
</tr>
<tr>
- <td> i<a href="#offsetspec">OFFSET</a>,<a href="#valuespec">VALUE</a> </td>
+ <td>b<a href="#valuespec">VALUE</a></td>
<td>
- Inject the specified value at the offset.
+ Set the body. The appropriate Content-Length header is added automatically unless
+ the "r" flag is set.
</td>
</tr>
<tr>
- <td> p<a href="#offsetspec">OFFSET</a>,SECONDS </td>
+ <td>s<a href="#valuespec">VALUE</a></td>
<td>
- 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.
</td>
</tr>
<tr>
- <td> r </td>
+ <td>x<a href="#valuespec">INTEGER</a></td>
<td>
- 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.
</td>
</tr>
<tr>
- <td> s<a href="#valuespec">VALUE</a> </td>
+ <td>d<a href="#offsetspec">OFFSET</a></td>
<td>
- An embedded Response specification, appended to the path
- of the request.
+ <span class="badge badge-info">HTTP/1 only</span> Disconnect after
+ OFFSET bytes.
</td>
</tr>
<tr>
- <td> u<a href="#valuespec">VALUE</a> <br> uSHORTCUT </td>
-
+ <td>i<a href="#offsetspec">OFFSET</a>,<a href="#valuespec">VALUE</a></td>
<td>
-
- Set a User-Agent header on this request. You can
- specify either a complete <a
- href="#valuespec">VALUE</a>, or a User-Agent shortcut:
-
- <table class="table table-condensed">
- {% for i in uastrings %}
- <tr>
- <td><b>{{ i[1] }}</b></td>
- <td>{{ i[0] }}</td>
- </tr>
- {% endfor %}
- </table>
-
+ <span class="badge badge-info">HTTP/1 only</span> Inject the specified
+ value at the offset.
</td>
</tr>
-
+
<tr>
- <td> x<a href="#valuespec">INTEGER</a> </td>
+ <td>p<a href="#offsetspec">OFFSET</a>,SECONDS</td>
<td>
- Repeat this message N times.
+ <span class="badge badge-info">HTTP/1 only</span> Pause for SECONDS
+ seconds after OFFSET bytes. SECONDS can be an integer or "f" to pause
+ forever.
</td>
</tr>
</tbody>
diff --git a/libpathod/templates/docs_lang_responses.html b/libpathod/templates/docs_lang_responses.html
index e8590add..9a85ff1a 100644
--- a/libpathod/templates/docs_lang_responses.html
+++ b/libpathod/templates/docs_lang_responses.html
@@ -1,89 +1,87 @@
-
-<pre class="example">code:[colon-separated list of features]</pre></p>
+<pre class="example">code:[colon-separated list of features]</pre>
<table class="table table-bordered">
- <tbody >
+ <tbody>
<tr>
- <td> code </td>
+ <td>code</td>
<td>
<p>An integer specifying the HTTP response code.</p>
-
- <p>The special method <b>ws</b> 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.</p>
+ <p>
+ The special method <b>ws</b> 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.
+ </p>
</td>
</tr>
<tr>
- <td> b<a href="#valuespec">VALUE</a> </td>
+ <td>m<a href="#valuespec">VALUE</a></td>
<td>
- Set the body. The appropriate Content-Length header is
- added automatically unless the "r" flag is set.
+ <span class="badge badge-info">HTTP/1 only</span> HTTP Reason message.
+ Automatically chosen according to the response code if not specified.
</td>
</tr>
<tr>
- <td> c<a href="#valuespec">VALUE</a> </td>
+ <td>h<a href="#valuespec">VALUE</a>=<a href="#valuespec">VALUE</a></td>
<td>
- A shortcut for setting the Content-Type header. Equivalent to
- h"Content-Type"=VALUE
+ Set a header.
</td>
</tr>
<tr>
- <td> d<a href="#offsetspec">OFFSET</a> </td>
+ <td>r</td>
<td>
- 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.
</td>
</tr>
<tr>
- <td> h<a href="#valuespec">VALUE</a>=<a href="#valuespec">VALUE</a> </td>
+ <td>l<a href="#valuespec">VALUE</a></td>
<td>
- Set a header.
+ A shortcut for setting the Location header. Equivalent to h"Location"=VALUE
</td>
</tr>
-
<tr>
- <td> i<a href="#offsetspec">OFFSET</a>,<a href="#valuespec">VALUE</a> </td>
+ <td>c<a href="#valuespec">VALUE</a></td>
<td>
- Inject the specified value at the offset.
+ A shortcut for setting the Content-Type header. Equivalent to h"Content-Type"=VALUE
</td>
</tr>
<tr>
- <td> l<a href="#valuespec">VALUE</a> </td>
+ <td>b<a href="#valuespec">VALUE</a></td>
<td>
- 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.
</td>
</tr>
<tr>
- <td> m<a href="#valuespec">VALUE</a> </td>
+ <td>d<a href="#offsetspec">OFFSET</a></td>
<td>
- HTTP Reason message. Automatically chosen according to
- the response code if not specified.
+ <span class="badge badge-info">HTTP/1 only</span> Disconnect after
+ OFFSET bytes.
</td>
</tr>
<tr>
- <td> p<a href="#offsetspec">OFFSET</a>,SECONDS </td>
+ <td>i<a href="#offsetspec">OFFSET</a>,<a href="#valuespec">VALUE</a></td>
<td>
- Pause for SECONDS seconds after OFFSET bytes. SECONDS can
- be an integer or "f" to pause forever.
+ <span class="badge badge-info">HTTP/1 only</span> Inject the specified
+ value at the offset.
</td>
</tr>
<tr>
- <td> r </td>
+ <td>p<a href="#offsetspec">OFFSET</a>,SECONDS</td>
<td>
- 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.
+ <span class="badge badge-info">HTTP/1 only</span> Pause for SECONDS
+ seconds after OFFSET bytes. SECONDS can be an integer or "f" to pause
+ forever.
</td>
</tr>
</tbody>
diff --git a/libpathod/templates/docs_lang_websockets.html b/libpathod/templates/docs_lang_websockets.html
index 32bd71f9..dd318e0b 100644
--- a/libpathod/templates/docs_lang_websockets.html
+++ b/libpathod/templates/docs_lang_websockets.html
@@ -1,13 +1,13 @@
-<pre class="example">wf:[colon-separated list of features]</pre></p>
+<pre class="example">wf:[colon-separated list of features]</pre>
+</p>
<table class="table table-bordered">
- <tbody >
+ <tbody>
<tr>
<td> b<a href="#valuespec">VALUE</a> </td>
<td>
- 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.
</td>
</tr>
@@ -15,8 +15,8 @@
<td> c<a href="#valuespec">INTEGER</a> </td>
<td>
- Set the op code. This can either be an integer from 0-15, or be
- one of the following opcode names: <b>text</b> (the default),
+ Set the op code. This can either be an integer from 0-15, or be one of the following
+ opcode names: <b>text</b> (the default),
<b>continue</b>, <b>binary</b>, <b>close</b>, <b>ping</b>,
<b>pong</b>.
@@ -47,17 +47,17 @@
<tr>
<td> k<a href="#valuespec">VALUE</a> </td>
<td>
- Set the masking key. The resulting value must be exactly 4
- bytes long. The special form <b>knone</b> 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
+ <b>knone</b> specifies that no key should be set, even if the mask
+ bit is on.
</td>
</tr>
<tr>
<td> l<a href="#valuespec">INTEGER</a> </td>
<td>
- 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.
</td>
</tr>
@@ -71,16 +71,15 @@
<tr>
<td> p<a href="#offsetspec">OFFSET</a>,SECONDS </td>
<td>
- 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.
</td>
</tr>
<tr>
<td> r<a href="#valuespec">VALUE</a> </td>
<td>
- 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.
</td>
</tr>
diff --git a/libpathod/templates/docs_libpathod.html b/libpathod/templates/docs_libpathod.html
index 3e18c1d9..6d504fe5 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 %}
<div class="page-header">
- <h1>
+ <h1>
libpathod
<small>Using pathod and pathoc in code.</small>
</h1>
@@ -10,18 +8,16 @@
<div class="row">
<div class="span6">
-
- <p> Behind the pathod and pathoc command-line tools lurks
- <b>libpathod</b>, 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.</p>
-
+ <p>
+ Behind the pathod and pathoc command-line tools lurks <b>libpathod</b>,
+ 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.
+ </p>
</div>
<div class="span6">
- <h1> pathoc </h1>
-
+ <h1>pathoc</h1>
{% include "libpathod_pathoc.html" %}
</div>
</div>
-
-{% endblock %}
+{% endblock %}
diff --git a/libpathod/templates/docs_pathoc.html b/libpathod/templates/docs_pathoc.html
index 76018530..d38c3a77 100644
--- a/libpathod/templates/docs_pathoc.html
+++ b/libpathod/templates/docs_pathoc.html
@@ -1,191 +1,211 @@
-{% extends "docframe.html" %}
-{% block body %}
+{% extends "docframe.html" %} {% block body %}
<div class="page-header">
- <h1>
+ <h1>
pathoc
<small>A perverse HTTP client.</small>
</h1>
</div>
-<p>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 <a href="/docs/language">small, terse
-language</a>, which pathod shares with its server-side twin <a
-href="/docs/pathod">pathod</a>. To view pathoc's complete range of options, use
-the command-line help:</p>
+<p>
+ 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
+ <a href="/docs/language">small, terse language</a>, which pathod shares with
+ its server-side twin <a href="/docs/pathod">pathod</a>. To view pathoc's complete
+ range of options, use the command-line help:
+</p>
- <pre class="terminal">pathoc --help</pre>
+<pre class="terminal">pathoc --help</pre>
<section>
<div class="page-header">
- <h1>Getting Started</h1>
+ <h1>Getting Started</h1>
</div>
<p>The basic pattern for pathoc commands is as follows: </p>
<pre class="terminal">pathoc hostname request [request ...]</pre>
- <p>That is, we specify the hostname to connect to, followed by one or more
- requests. Lets start with a simple example:</p>
-
- <pre class="terminal">&gt; pathoc google.com get:/
-&lt;&lt; 301 Moved Permanently: 219 bytes</pre>
-
- <p>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 <b>-p</b> command-line
- option):</p>
-
- <pre class="terminal">&gt; pathoc -s google.com get:/
-&lt;&lt; 301 Moved Permanently: 219 bytes</pre>
-
+ <p>
+ That is, we specify the hostname to connect to, followed by one or more requests.
+ Lets start with a simple example:
+ </p>
+
+ <pre class="terminal">
+ &gt; pathoc google.com get:/ &lt;&lt; 301 Moved Permanently: 219 bytes
+ </pre>
+
+ <p>
+ 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 <b>-p</b> command-line option):
+ </p>
+
+ <pre class="terminal">
+ &gt; pathoc -s google.com get:/ &lt;&lt; 301 Moved Permanently: 219 bytes
+ </pre>
</section>
<section>
<div class="page-header">
- <h1>Multiple Requests</h1>
+ <h1>Multiple Requests</h1>
</div>
- <p>There are two ways to tell pathoc to issue multiple requests. The first
- is to specify them on the command-line, like so:</p>
+ <p>
+ There are two ways to tell pathoc to issue multiple requests. The first is to specify
+ them on the command-line, like so:
+ </p>
- <pre class="terminal">&gt; pathoc google.com get:/ get:/
-&lt;&lt; 301 Moved Permanently: 219 bytes
-&lt;&lt; 301 Moved Permanently: 219 bytes</pre>
+ <pre class="terminal">
+ &gt; pathoc google.com get:/ get:/ &lt;&lt; 301 Moved Permanently: 219 bytes &lt;&lt;
+ 301 Moved Permanently: 219 bytes
+ </pre>
- <p> 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 </p>
+ <p>
+ 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
+ </p>
- <p> The other way to issue multiple requets is to use the <b>-n</b> flag:</p>
+ <p>The other way to issue multiple requets is to use the <b>-n</b> flag:</p>
- <pre class="terminal">&gt; pathoc -n 2 google.com get:/
-&lt;&lt; 301 Moved Permanently: 219 bytes
-&lt;&lt; 301 Moved Permanently: 219 bytes</pre>
+ <pre class="terminal">
+ &gt; pathoc -n 2 google.com get:/ &lt;&lt; 301 Moved Permanently: 219 bytes &lt;&lt; 301
+ Moved Permanently: 219 bytes
+ </pre>
- <p> The output is identical, but two separate TCP connections are made to
- the upstream server. These two specification styles can be combined:</p>
+ <p>
+ The output is identical, but two separate TCP connections are made to the upstream
+ server. These two specification styles can be combined:
+ </p>
- <pre class="terminal">&gt; pathoc -n 2 google.com get:/ get:/
-&lt;&lt; 301 Moved Permanently: 219 bytes
-&lt;&lt; 301 Moved Permanently: 219 bytes
-&lt;&lt; 301 Moved Permanently: 219 bytes
-&lt;&lt; 301 Moved Permanently: 219 bytes</pre>
-
- <p> Here, two distinct TCP connections are made, with two requests issued
- over each. </p>
+ <pre class="terminal">
+ &gt; pathoc -n 2 google.com get:/ get:/ &lt;&lt; 301 Moved Permanently: 219 bytes &lt;&lt;
+ 301 Moved Permanently: 219 bytes &lt;&lt; 301 Moved Permanently: 219 bytes &lt;&lt;
+ 301 Moved Permanently: 219 bytes
+ </pre>
+ <p>Here, two distinct TCP connections are made, with two requests issued over each.</p>
</section>
<section>
<div class="page-header">
- <h1>Basic Fuzzing</h1>
+ <h1>Basic Fuzzing</h1>
</div>
- <p>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:</p>
+ <p>
+ 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:
+ </p>
- <pre class="terminal">&gt; pathoc -e -I 200 -t 2 -n 1000 localhost get:/:b@10:ir,@1</pre>
+ <pre class="terminal">
+ &gt; pathoc -e -I 200 -t 2 -n 1000 localhost get:/:b@10:ir,@1
+ </pre>
- <p>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:<p>
+ <p>
+ 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:
+ </p>
<ul>
-
- <li> 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 <b>-t</b> option comes in, which sets a timeout that causes
- pathoc to disconnect after two seconds. </li>
-
- <li> The <b>-n</b> option tells pathoc to repeat the request 1000
- times.</li>
-
- <li> The <b>-I</b> 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.</li>
-
- <li> The <b>-e</b> 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 </li>
-
+ <li>
+ 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
+ <b>-t</b> option comes in, which sets a timeout that causes pathoc to
+ disconnect after two seconds.
+ </li>
+
+ <li>
+ The <b>-n</b> option tells pathoc to repeat the request 1000 times.
+ </li>
+
+ <li>
+ The <b>-I</b> 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.
+ </li>
+
+ <li>
+ The <b>-e</b> 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.
+ </li>
</ul>
-
</section>
<section>
-
<div class="page-header">
- <h1>Interacting with Proxies</h1>
+ <h1>Interacting with Proxies</h1>
</div>
- <p>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::</p>
+ <p>
+ 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:
+ </p>
<pre class="terminal">&gt; pathoc -p 8080 localhost "get:'http://google.com'"</pre>
- <p>Another common use case is to use an HTTP CONNECT request to probe
- remote servers via a proxy. This is done with the <b>-c</b> command-line
- option, which allows you to specify a remote host and port pair:</p>
+ <p>
+ Another common use case is to use an HTTP CONNECT request to probe remote servers
+ via a proxy. This is done with the <b>-c</b> command-line option,
+ which allows you to specify a remote host and port pair:
+ </p>
<pre class="terminal">&gt; pathoc -c google.com:80 -p 8080 localhost get:/</pre>
- <p>Note that pathoc does <b>not</b> 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 <b>-s</b> flag:</p>
+ <p>
+ Note that pathoc does <b>not</b> 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 <b>-s</b> flag:
+ </p>
<pre class="terminal">&gt; pathoc -sc google.com:443 -p 8080 localhost get:/</pre>
-
</section>
<section>
<div class="page-header">
- <h1>Embedded response specification</h1>
+ <h1>Embedded response specification</h1>
</div>
- <p>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:</p>
-
- <pre class="terminal">&gt; pathoc localhost:9999 "get:/p/:s'401:ir,@1'" </pre>
-
- <p> 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 <b>-e</b> flag to show the expanded request:
-
- <pre class="terminal">&gt; > 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 </pre>
-
- <p> Note that the embedded response has been resolved <i>before</i> 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.</p>
-
+ <p>
+ 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:
+ </p>
+
+ <pre class="terminal">&gt; pathoc localhost:9999 "get:/p/:s'401:ir,@1'"</pre>
+
+ <p>
+ 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 <b>-e</b> flag to show the expanded request:
+ </p>
+
+ <pre class="terminal">
+ &gt; > 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 </pre>
+
+ <p>
+ Note that the embedded response has been resolved <i>before</i> 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.
+ </p>
</section>
-
-
-
-
-
-
-
-
{% endblock %}
diff --git a/libpathod/templates/docs_pathod.html b/libpathod/templates/docs_pathod.html
index 3ad4dac9..0d0ae933 100644
--- a/libpathod/templates/docs_pathod.html
+++ b/libpathod/templates/docs_pathod.html
@@ -1,131 +1,142 @@
-{% extends "docframe.html" %}
-{% block body %}
-
+{% extends "docframe.html" %} {% block body %}
<div class="page-header">
- <h1>
+ <h1>
pathod
<small>A pathological web daemon.</small>
</h1>
</div>
-<p>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 <a href="/docs/language">small,
-terse language</a>, which pathod shares with its evil twin <a
-href="/docs/pathoc">pathoc</a>. </p>
+<p>
+ 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
+ <a href="/docs/language">small, terse language</a>, which pathod shares with
+ its evil twin <a href="/docs/pathoc">pathoc</a>.
+</p>
<section>
<div class="page-header">
- <h1>Getting started</h1>
+ <h1>Getting started</h1>
</div>
-<p> To start playing with pathod, simply fire up the daemon: </p>
+ <p>To start playing with pathod, simply fire up the daemon:</p>
-<pre class="terminal">./pathod</pre>
+ <pre class="terminal">./pathod</pre>
-<p>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:</p>
+ <p>
+ 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:
+ </p>
-<pre class="example">http://localhost:9999</pre>
+ <pre class="example">http://localhost:9999</pre>
-<p>The default crafting anchor point is the path <b>/p/</b>. 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:</p>
+ <p>
+ The default crafting anchor point is the path <b>/p/</b>. 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:
+ </p>
-<pre class="example">http://localhost:9999/p/200:b@100</pre>
+ <pre class="example">http://localhost:9999/p/200:b@100</pre>
-<p>See the <a href="/docs/language">language documentation</a> to get (much)
-fancier. The pathod daemon also takes a range of configuration options. To view
-those, use the command-line help:</p>
+ <p>
+ See the <a href="/docs/language">language documentation</a> to get (much)
+ fancier. The pathod daemon also takes a range of configuration options. To
+ view those, use the command-line help:
+ </p>
-<pre class="terminal">./pathod --help</pre>
+ <pre class="terminal">./pathod --help</pre>
</section>
<section>
<div class="page-header">
- <h1>Acting as a proxy</h1>
+ <h1>Acting as a proxy</h1>
</div>
-<p>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.</p>
-
-<p>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.</p>
-
+ <p>
+ 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.
+ </p>
+
+ <p>
+ 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.
+ </p>
</section>
<section>
<div class="page-header">
- <h1>Anchors</h1>
+ <h1>Anchors</h1>
</div>
-<p>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.</p>
+ <p>
+ 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.
+ </p>
-<pre class="terminal">./pathod -a "/foo=200"</pre>
-
-<p>Here, "/foo" is the regex specifying the anchor path, and the part after
-the "=" is a response specifier.</p>
+ <pre class="terminal">./pathod -a "/foo=200"</pre>
+ <p>
+ Here, "/foo" is the regex specifying the anchor path, and the part after the "="
+ is a response specifier.
+ </p>
</section>
<section>
<div class="page-header">
- <h1>File Access</h1>
+ <h1>File Access</h1>
</div>
-<p>There are two operators in the <a href="/docs/language">language</a> that
-load contents from file - the <b>+</b> operator to load an entire request
-specification from file, and the <b>&gt;</b> value specifier. In pathod, both
-of these operators are restricted to a directory specified at startup, or
-disabled if no directory is specified:</p>
-
-<pre class="terminal">./pathod -d ~/staticdir"</pre>
-
+ <p>
+ There are two operators in the <a href="/docs/language">language</a> that
+ load contents from file - the <b>+</b> operator to load an entire request
+ specification from file, and the <b>&gt;</b> value specifier. In pathod,
+ both of these operators are restricted to a directory specified at startup,
+ or disabled if no directory is specified:</p>
+ <pre class="terminal">./pathod -d ~/staticdir"</pre>
</section>
<section>
<div class="page-header">
- <h1>Internal Error Responses</h1>
+ <h1>Internal Error Responses</h1>
</div>
- <p>Pathod uses the non-standard 800 response code to indicate internal
- errors, to distinguish them from crafted responses. For example, a request
- to:</p>
+ <p>
+ Pathod uses the non-standard 800 response code to indicate internal errors, to distinguish
+ them from crafted responses. For example, a request to:
+ </p>
<pre class="example">http://localhost:9999/p/foo</pre>
- <p>... will return an 800 response because "foo" is not a valid page
- specifier.</p>
-
+ <p>
+ ... will return an 800 response because "foo" is not a valid page specifier.
+ </p>
</section>
<section>
<div class="page-header">
- <h1>API</h1>
+ <h1>API</h1>
</div>
- <p>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. </p>
-
+ <p>
+ 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.
+ </p>
<table class="table table-bordered">
- <tbody >
+ <tbody>
<tr>
<td>
/api/clear_log
@@ -147,18 +158,15 @@ disabled if no directory is specified:</p>
/api/log
</td>
<td>
- 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:
- <pre>{ 'log': [ ENTRIES ] } </pre>
-
- You can preview the JSON data returned for a log entry through the built-in web
- interface.
+ <pre>{ 'log': [ ENTRIES ] } </pre> You can preview the JSON data
+ returned for a log entry through the built-in web interface.
</td>
</tr>
</tbody>
</table>
</section>
-
{% endblock %}
diff --git a/libpathod/templates/docs_test.html b/libpathod/templates/docs_test.html
index 25205d41..0502c984 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 %}
<div class="page-header">
- <h1>
+ <h1>
libpathod.test
- <small>Using pathod and pathoc in your unit tests.</small>
+ <small>Using libpathod in unit tests.</small>
</h1>
</div>
-<div class="row">
- <div class="span6">
+<p>The <b>libpathod.test</b> 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.
+</p>
- <p> The <b>libpathod.test</b> 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. </p>
+<p>The canonical docs can be accessed using pydoc: </p>
- <p> The canonical docs can be accessed using pydoc: </p>
+<pre class="terminal">pydoc libpathod.test</pre>
- <pre class="terminal">pydoc libpathod.test</pre>
+<p>
+ The remainder of this page demonstrates some common interaction patterns using
+ <a href="http://nose.readthedocs.org/en/latest/">nose</a>. These examples are
+ also applicable with only minor modification to most commonly used Python testing
+ engines.
+</p>
- <p> The remainder of this page demonstrates some common interaction
- patterns using <a
- href="http://nose.readthedocs.org/en/latest/">nose</a>. These examples
- are also applicable with only minor modification to most commonly used
- Python testing engines.</p>
-
- </div>
- <div class="span6">
- <h1> Context Manager </h1>
-
- {% include "examples_context.html" %}
+<section>
+ <div class="page-header">
+ <h1>Context Manager</h1>
</div>
-</div>
-<div class="row">
- <div class="span6">
- <h1> One instance per test </h1>
+ {% include "examples_context.html" %}
+</section>
- {% include "examples_setup.html" %}
+<section>
+ <div class="page-header">
+ <h1>One instance per test</h1>
</div>
- <div class="span6">
- <h1> One instance per suite </h1>
- {% include "examples_setupall.html" %}
- </div>
-</div>
+ {% include "examples_setup.html" %}
+</section>
+<section>
+ <div class="page-header">
+ <h1>One instance per suite</h1>
+ </div>
-{% endblock %}
+ {% include "examples_setupall.html" %}
+</section>
+{% endblock %}
diff --git a/libpathod/templates/download.html b/libpathod/templates/download.html
index 2f6ed287..bd8950e8 100644
--- a/libpathod/templates/download.html
+++ b/libpathod/templates/download.html
@@ -1,53 +1,39 @@
-{% extends "frame.html" %}
-{% block body %}
-
+{% extends "frame.html" %} {% block body %}
<section>
<div class="page-header">
- <h1>
- pip
- </h1>
+ <h1>pip</h1>
</div>
<p>The easiest way to install pathod is to use pip:</p>
<pre>pip install pathod</pre>
- <p> This will automatically pull in all the dependencies, and you should be
- good to go.</p>
-
+ <p>
+ This will automatically pull in all the dependencies, and you should be good to go.
+ </p>
</section>
-
<section>
<div class="page-header">
- <h1>
- github
- </h1>
+ <h1>github</h1>
</div>
- <p> You can find the project source on GitHub: </p>
+ <p>You can find the project source on GitHub:</p>
<div style="margin-top: 20px; margin-bottom: 20px">
- <a class="btn btn-primary btn-large" href="https://github.com/mitmproxy/pathod">github.com/mitmproxy/pathod</a>
+ <a class="btn btn-primary btn-large" href="https://github.com/mitmproxy/pathod">github.com/mitmproxy/pathod</a>
</div>
- <p>Please also use the <a
- href="https://github.com/mitmproxy/pathod/issues">github issue tracker</a> to
- report bugs. </p>
+ <p>Please also use the <a href="https://github.com/mitmproxy/pathod/issues">github issue tracker</a> to report bugs.</p>
</section>
-
<section>
<div class="page-header">
- <h1>
- tarball
- </h1>
+ <h1>tarball</h1>
</div>
<div style="margin-top: 20px; margin-bottom: 20px">
- <a class="btn btn-primary btn-large" href="https://github.com/downloads/mitmproxy/pathod/pathod-{{version}}.tar.gz">pathod-{{version}}.tar.gz</a>
+ <a class="btn btn-primary btn-large" href="https://github.com/downloads/mitmproxy/pathod/pathod-{{version}}.tar.gz">pathod-{{version}}.tar.gz</a>
</div>
</section>
-
-
{% 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 @@
<div class="highlight"><pre><span class="kn">import</span> <span class="nn">requests</span>
<span class="kn">from</span> <span class="nn">libpathod</span> <span class="kn">import</span> <span class="n">test</span>
+
<span class="k">def</span> <span class="nf">test_simple</span><span class="p">():</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Testing the requests module with</span>
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 @@
<div class="highlight"><pre><span class="kn">import</span> <span class="nn">requests</span>
<span class="kn">from</span> <span class="nn">libpathod</span> <span class="kn">import</span> <span class="n">test</span>
+
<span class="k">class</span> <span class="nc">Test</span><span class="p">:</span>
+
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Testing the requests module with</span>
<span class="sd"> a pathod instance started for</span>
<span class="sd"> each test.</span>
<span class="sd"> &quot;&quot;&quot;</span>
+
<span class="k">def</span> <span class="nf">setUp</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">d</span> <span class="o">=</span> <span class="n">test</span><span class="o">.</span><span class="n">Daemon</span><span class="p">()</span>
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 @@
<div class="highlight"><pre><span class="kn">import</span> <span class="nn">requests</span>
<span class="kn">from</span> <span class="nn">libpathod</span> <span class="kn">import</span> <span class="n">test</span>
+
<span class="k">class</span> <span class="nc">Test</span><span class="p">:</span>
+
<span class="sd">&quot;&quot;&quot;</span>
-<span class="sd"> Testing the requests module with </span>
-<span class="sd"> a single pathod instance started </span>
+<span class="sd"> Testing the requests module with</span>
+<span class="sd"> a single pathod instance started</span>
<span class="sd"> for the test suite.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="nd">@classmethod</span>
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 %}
<div class="row">
<div class="span12">
- {% block body %}
- {% endblock %}
+ {% block body %} {% endblock %}
</div>
</div>
-{% 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 %}
<div class="masthead">
<div class="container">
<h1>pathod: pathological HTTP</h1>
@@ -12,58 +9,52 @@
</div>
</div>
-
<div class="row">
<div class="span6">
<div>
- <h2> <a href="/docs/pathod">pathod</a> </h2>
+ <h2><a href="/docs/pathod">pathod</a></h2>
<p>A pathological web daemon.</p>
{% include "response_previewform.html" %}
-
<br>
-
</div>
</div>
+
<div class="span6">
<div>
- <h2> <a href="/docs/pathoc">pathoc</a> </h2>
+ <h2><a href="/docs/pathoc">pathoc</a></h2>
<p>A perverse HTTP client.</p>
{% include "request_previewform.html" %}
-
</div>
</div>
</div>
<section>
-<div class="page-header">
- <h1>Install</h1>
-</div>
-<div class="row">
- <div class="span6">
- <div>
- <h2>pip</h2>
-
- <pre>pip install pathod</pre>
+ <div class="page-header">
+ <h1>Install</h1>
+ </div>
+ <div class="row">
+ <div class="span6">
+ <div>
+ <h2>pip</h2>
+ <pre>pip install pathod</pre>
+ </div>
</div>
- </div>
- <div class="span6">
- <div>
- <h2>source</h2>
- <ul>
- <li>Current release: <a href="http://mitmproxy.org/download/pathod-{{version}}.tar.gz">pathod {{version}}</a></li>
+ <div class="span6">
+ <div>
+ <h2>source</h2>
- <li>GitHub: <a href="https://github.com/mitmproxy/pathod">github.com/mitmproxy/pathod</a></li>
- </li>
+ <ul>
+ <li>Current release: <a href="http://mitmproxy.org/download/pathod-{{version}}.tar.gz">pathod {{version}}</a></li>
+ <li>GitHub: <a href="https://github.com/mitmproxy/pathod">github.com/mitmproxy/pathod</a></li>
+ </ul>
+ </div>
</div>
</div>
-</div>
</section>
-
-
{% endblock %}
diff --git a/libpathod/templates/layout.html b/libpathod/templates/layout.html
index 5278e5aa..af2857b1 100644
--- a/libpathod/templates/layout.html
+++ b/libpathod/templates/layout.html
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<html lang="en">
- <head>
+
+<head>
<meta charset="utf-8">
<title>pathod</title>
<link href="/static/bootstrap.min.css" rel="stylesheet">
@@ -14,60 +15,61 @@
<meta name="description" content="">
<meta name="author" content="">
<style type="text/css">
- body {
- padding-top: 60px;
- padding-bottom: 40px;
- }
+ body {
+ padding-top: 60px;
+ padding-bottom: 40px;
+ }
+
</style>
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
- </head>
-
- <body>
+</head>
+<body>
<div class="navbar navbar-fixed-top">
- <div class="navbar-inner">
- <div class="container">
- <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
- <span class="icon-bar"></span>
- <span class="icon-bar"></span>
- <span class="icon-bar"></span>
- </a>
- <a class="brand" href="/index.html">pathod</a>
- <div class="nav-collapse">
- <ul class="nav">
- <li {% if section== "main" %} class="active" {% endif %}><a href="/">home</a></li>
- {% if not noapi %}
- <li {% if section== "log" %} class="active" {% endif %}><a href="/log">log</a></li>
- {% endif %}
- <li {% if section== "docs" %} class="active" {% endif %}><a href="/docs/pathod">docs</a></li>
- <li {% if section== "about" %} class="active" {% endif %}><a href="/about">about</a></li>
- </ul>
- </div>
+ <div class="navbar-inner">
+ <div class="container">
+ <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </a>
+ <a class="brand" href="/index.html">pathod</a>
+ <div class="nav-collapse">
+ <ul class="nav">
+ <li {% if section=="main" %} class="active" {% endif %}><a href="/">home</a></li>
+ {% if not noapi %}
+ <li {% if section=="log" %} class="active" {% endif %}><a href="/log">log</a></li>
+ {% endif %}
+ <li {% if section=="docs" %} class="active" {% endif %}><a href="/docs/pathod">docs</a></li>
+ <li {% if section=="about" %} class="active" {% endif %}><a href="/about">about</a></li>
+ </ul>
+ </div>
+ </div>
</div>
- </div>
</div>
<div class="container">
- {% block content %}
- {% endblock %}
- <hr>
- <footer>
- <span>&copy; Aldo Cortesi 2015</span>
- <span class="pull-right">[served with pathod]</span>
- </footer>
+ {% block content %} {% endblock %}
+ <hr>
+ <footer>
+ <span>&copy; Aldo Cortesi 2015</span>
+ <span class="pull-right">[served with pathod]</span>
+ </footer>
</div>
- </body>
- <script>
- $(function(){
- $.localScroll(
- {
- duration: 300,
- offset: {top: -45}
+</body>
+<script>
+ $(function() {
+ $.localScroll({
+ duration: 300,
+ offset: {
+ top: -45
}
- );
+ });
});
- </script>
+
+</script>
+
</html>
diff --git a/libpathod/templates/libpathod_pathoc.html b/libpathod/templates/libpathod_pathoc.html
index f2737c01..f5871b16 100644
--- a/libpathod/templates/libpathod_pathoc.html
+++ b/libpathod/templates/libpathod_pathoc.html
@@ -1,7 +1,8 @@
<div class="highlight"><pre><span class="c">#!/usr/bin/env python</span>
<span class="kn">from</span> <span class="nn">libpathod</span> <span class="kn">import</span> <span class="n">pathoc</span>
-<span class="n">p</span> <span class="o">=</span> <span class="n">pathoc</span><span class="o">.</span><span class="n">Pathoc</span><span class="p">(</span><span class="s">&quot;google.com&quot;</span><span class="p">,</span> <span class="mi">80</span><span class="p">)</span>
+<span class="n">p</span> <span class="o">=</span> <span class="n">pathoc</span><span class="o">.</span><span class="n">Pathoc</span><span class="p">((</span><span class="s">&quot;google.com&quot;</span><span class="p">,</span> <span class="mi">80</span><span class="p">))</span>
<span class="n">p</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span>
<span class="k">print</span> <span class="n">p</span><span class="o">.</span><span class="n">request</span><span class="p">(</span><span class="s">&quot;get:/&quot;</span><span class="p">)</span>
+<span class="k">print</span> <span class="n">p</span><span class="o">.</span><span class="n">request</span><span class="p">(</span><span class="s">&quot;get:/foo&quot;</span><span class="p">)</span>
</pre></div>
diff --git a/libpathod/templates/log.html b/libpathod/templates/log.html
index 19468d66..b0484cb8 100644
--- a/libpathod/templates/log.html
+++ b/libpathod/templates/log.html
@@ -1,32 +1,31 @@
-{% extends "frame.html" %}
-{% block body %}
- <form style="float: right" method="POST" action="/log/clear">
- <button type="submit" class="btn">clear</button>
- </form>
- <h1> Logs </h1>
- <hr>
+{% extends "frame.html" %} {% block body %}
+<form style="float: right" method="POST" action="/log/clear">
+ <button type="submit" class="btn">clear</button>
+</form>
- <table class="table table-striped table-condensed">
- <thead>
- <tr>
- <th>id</th>
- <th>method</th>
- <th>path</th>
- </tr>
- </thead>
- <tbody>
- {% for i in log %}
- <tr>
- {% if i["type"] == 'error' %}
- <td colspan="3">ERROR: {{ i["msg"] }}</td>
- {% else %}
- <td>{{ i["id"] }}</td>
- <td>{{ i["request"]["method"] }}</td>
- <td><a href="/log/{{ i["id"] }}">{{ i["request"]["path"] }}</a></td>
- {% endif %}
- </tr>
- {% endfor %}
- </tbody>
- </table>
-{% endblock %}
+<h1>Logs</h1>
+<hr>
+<table class="table table-striped table-condensed">
+ <thead>
+ <tr>
+ <th>id</th>
+ <th>method</th>
+ <th>path</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for i in log %}
+ <tr>
+ {% if i["type"] == 'error' %}
+ <td colspan="3">ERROR: {{ i["msg"] }}</td>
+ {% else %}
+ <td>{{ i["id"] }}</td>
+ <td>{{ i["request"]["method"] }}</td>
+ <td><a href="/log/{{ i[" id "] }}">{{ i["request"]["path"] }}</a></td>
+ {% endif %}
+ </tr>
+ {% endfor %}
+ </tbody>
+</table>
+{% endblock %}
diff --git a/libpathod/templates/onelog.html b/libpathod/templates/onelog.html
index a94f443a..c222ad60 100644
--- a/libpathod/templates/onelog.html
+++ b/libpathod/templates/onelog.html
@@ -1,10 +1,8 @@
-{% extends "frame.html" %}
-{% block body %}
- <h2> Log entry {{ lid }} </h2>
- <hr>
+{% extends "frame.html" %} {% block body %}
+<h2>Log entry {{ lid }}</h2>
+<hr>
+
<pre>
-{{ alog }}
+ {{ alog }}
</pre>
-
-{% endblock %}
-
+{% endblock %}
diff --git a/libpathod/templates/request_preview.html b/libpathod/templates/request_preview.html
index 2717a9b8..25d73679 100644
--- a/libpathod/templates/request_preview.html
+++ b/libpathod/templates/request_preview.html
@@ -1,6 +1,4 @@
-{% extends "frame.html" %}
-{% block body %}
-
+{% extends "frame.html" %} {% block body %}
<div class="page-header">
<h1>pathoc preview</h1>
</div>
@@ -15,36 +13,32 @@
</div>
{% if syntaxerror %}
- <div class="row">
- <div class="span2 header">
- Error:
- </div>
- <div class="span10">
- <p style="color: #ff0000">{{ syntaxerror }}</p>
- <pre>{{ marked }}</pre>
- </div>
+<div class="row">
+ <div class="span2 header">
+ Error:
</div>
+ <div class="span10">
+ <p style="color: #ff0000">{{ syntaxerror }}</p>
+ <pre>{{ marked }}</pre>
+ </div>
+</div>
{% elif error %}
- <div class="row">
- <div class="span2 header">
- Error:
- </div>
- <div class="span10">
- <p style="color: #ff0000">{{ error }}</p>
- </div>
+<div class="row">
+ <div class="span2 header">
+ Error:
+ </div>
+ <div class="span10">
+ <p style="color: #ff0000">{{ error }}</p>
</div>
+</div>
{% else %}
- <div class="row">
- <div class="span2 header">
- Request:
- </div>
- <div class="span10">
- <pre>{{ output }}</pre>
- <p>Note: pauses are skipped when generating previews!</p>
- </div>
- </div>
-{% endif %}
-
-{% endblock %}
-
-
+<div class="row">
+ <div class="span2 header">
+ Request:
+ </div>
+ <div class="span10">
+ <pre>{{ output }}</pre>
+ <p>Note: pauses are skipped when generating previews!</p>
+ </div>
+</div>
+{% endif %} {% endblock %}
diff --git a/libpathod/templates/request_previewform.html b/libpathod/templates/request_previewform.html
index d3083735..91b5598a 100644
--- a/libpathod/templates/request_previewform.html
+++ b/libpathod/templates/request_previewform.html
@@ -1,23 +1,19 @@
<form style="margin-bottom: 0" class="form-inline" method="GET" action="/request_preview">
- <input
- style="width: 18em"
- id="spec"
- name="spec"
- class="input-medium"
- value="{{spec}}"
- placeholder="method:path:[features]"
- >
+ <input style="width: 18em" id="spec" name="spec" class="input-medium" value="{{spec}}"
+ placeholder="method:path:[features]">
<input type="submit" class="btn" value="preview">
</form>
<a class="innerlink" data-toggle="collapse" data-target="#requestexamples">examples</a>
<div id="requestexamples" class="collapse">
- <p>Check out the <a href="/docs/language">complete language docs</a>. Here
- are some examples to get you started:</p>
+ <p>
+ Check out the <a href="/docs/language">complete language docs</a>. Here are
+ some examples to get you started:
+ </p>
<table class="table table-bordered">
- <tbody >
+ <tbody>
<tr>
<td><a href="/request_preview?spec=get:/">get:/</a></td>
<td>Get path /</td>
@@ -39,7 +35,9 @@
<td>Drop the connection randomly</td>
</tr>
<tr>
- <td><a href="/request_preview?spec="></a></td>
+ <td>
+ <a href="/request_preview?spec="></a>
+ </td>
<td></td>
</tr>
<tr>
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 %}
<div class="page-header">
<h1>pathod preview</h1>
</div>
@@ -15,34 +13,32 @@
</div>
{% if syntaxerror %}
- <div class="row">
- <div class="span2 header">
- Error:
- </div>
- <div class="span10">
- <p style="color: #ff0000">{{ syntaxerror }}</p>
- <pre>{{ marked }}</pre>
- </div>
+<div class="row">
+ <div class="span2 header">
+ Error:
+ </div>
+ <div class="span10">
+ <p style="color: #ff0000">{{ syntaxerror }}</p>
+ <pre>{{ marked }}</pre>
</div>
+</div>
{% elif error %}
- <div class="row">
- <div class="span2 header">
- Error:
- </div>
- <div class="span10">
- <p style="color: #ff0000">{{ error }}</p>
- </div>
+<div class="row">
+ <div class="span2 header">
+ Error:
+ </div>
+ <div class="span10">
+ <p style="color: #ff0000">{{ error }}</p>
</div>
+</div>
{% else %}
- <div class="row">
- <div class="span2 header">
- Response:
- </div>
- <div class="span10">
- <pre>{{ output }}</pre>
- <p>Note: pauses are skipped when generating previews!</p>
- </div>
- </div>
-{% endif %}
-
-{% endblock %}
+<div class="row">
+ <div class="span2 header">
+ Response:
+ </div>
+ <div class="span10">
+ <pre>{{ output }}</pre>
+ <p>Note: pauses are skipped when generating previews!</p>
+ </div>
+</div>
+{% endif %} {% endblock %}
diff --git a/libpathod/templates/response_previewform.html b/libpathod/templates/response_previewform.html
index d91a2a67..d46043f3 100644
--- a/libpathod/templates/response_previewform.html
+++ b/libpathod/templates/response_previewform.html
@@ -1,12 +1,6 @@
<form style="margin-bottom: 0" class="form-inline" method="GET" action="/response_preview">
- <input
- style="width: 18em"
- id="spec"
- name="spec"
- class="input-medium"
- value="{{spec}}"
- placeholder="code:[features]"
- >
+ <input style="width: 18em" id="spec" name="spec" class="input-medium" value="{{spec}}"
+ placeholder="code:[features]">
<input type="submit" class="btn" value="preview">
{% if not nocraft %}
<a href="#" id="submitspec" class="btn">go</a>
@@ -16,18 +10,22 @@
<a class="innerlink" data-toggle="collapse" data-target="#responseexamples">examples</a>
<div id="responseexamples" class="collapse">
- <p>Check out the <a href="/docs/language">complete language docs</a>. Here
- are some examples to get you started:</p>
+ <p>
+ Check out the <a href="/docs/language">complete language docs</a>. Here are
+ some examples to get you started:
+ </p>
<table class="table table-bordered">
- <tbody >
+ <tbody>
<tr>
<td><a href="/response_preview?spec=200">200</a></td>
<td>A basic HTTP 200 response.</td>
</tr>
<tr>
<td><a href="/response_preview?spec=200:r">200:r</a></td>
- <td>A basic HTTP 200 response with no Content-Length header. This will hang.</td>
+ <td>A basic HTTP 200 response with no Content-Length header. This will
+ hang.
+ </td>
</tr>
<tr>
<td><a href="/response_preview?spec=200:da">200:da</a></td>
@@ -35,8 +33,10 @@
</tr>
<tr>
<td><a href="/response_preview?spec=200:b@100">200:b@100</a></td>
- <td>100 random bytes as the body. A Content-Lenght header is
- added, so the disconnect is no longer needed.</td>
+ <td>
+ 100 random bytes as the body. A Content-Lenght header is added, so the disconnect
+ is no longer needed.
+ </td>
</tr>
<tr>
<td><a href='/response_preview?spec=200:b@100:h"Server"="&apos;;drop table servers;"'>200:b@100:h"Etag"="';drop table servers;"</a></td>
@@ -66,18 +66,22 @@
<td>
<a href="/response_preview?spec=200:b@100:h@1k,ascii_letters='foo'">200:b@100:h@1k,ascii_letters='foo'</a>
</td>
- <td>100 ASCII bytes as the body, randomly generated 100k header name, with the value 'foo'.</td>
+ <td>
+ 100 ASCII bytes as the body, randomly generated 100k header name, with the value
+ 'foo'.
+ </td>
</tr>
</tbody>
</table>
</div>
+{% if not nocraft %}
<script>
- $(function(){
- {% if not nocraft %}
- $("#submitspec").click(function(){
+ $(function() {
+ $("#submitspec").click(function() {
document.location = "{{craftanchor}}" + $("#spec").val()
});
- {% endif %}
});
+
</script>
+{% endif %}
diff --git a/test/test_language_http2.py b/test/test_language_http2.py
index a78c2bee..3b36c01b 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"')
@@ -99,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")
@@ -129,18 +170,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")