diff options
30 files changed, 643 insertions, 1564 deletions
diff --git a/docs/_static/theme_overrides.css b/docs/_static/theme_overrides.css new file mode 100644 index 00000000..63c7cc78 --- /dev/null +++ b/docs/_static/theme_overrides.css @@ -0,0 +1,11 @@ + +/* override table width restrictions */ +.wy-table-responsive table td, .wy-table-responsive table th { + white-space: normal; +} + +.wy-table-responsive { + margin-bottom: 24px; + max-width: 100%; + overflow: visible; +} diff --git a/docs/conf.py b/docs/conf.py index 01bcce1b..bd51c4c5 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -153,7 +153,7 @@ html_favicon = "favicon.ico" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -# html_static_path = ['_static'] +html_static_path = ['_static'] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied @@ -216,4 +216,10 @@ html_favicon = "favicon.ico" #html_search_scorer = 'scorer.js' # Output file base name for HTML help builder. -htmlhelp_basename = 'mitmproxydoc'
\ No newline at end of file +htmlhelp_basename = 'mitmproxydoc' + +html_context = { + 'css_files': [ + '_static/theme_overrides.css', # overrides for wide tables in RTD theme + ], +} diff --git a/docs/index.rst b/docs/index.rst index d3b6f434..28c0c66f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -64,6 +64,17 @@ tutorials/gamecenter tutorials/transparent-dhcp + +.. toctree:: + :hidden: + :caption: Pathod & Pathoc + + pathod/intro + pathod/language + pathod/library + pathod/test + + .. toctree:: :hidden: :caption: Hacking @@ -80,4 +91,3 @@ * :ref:`genindex` * :ref:`modindex` - diff --git a/docs/pathod/intro.rst b/docs/pathod/intro.rst new file mode 100644 index 00000000..f4c8b974 --- /dev/null +++ b/docs/pathod/intro.rst @@ -0,0 +1,307 @@ +.. _intro: + +Pathology 101 +============= + + +pathod +------ + +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 :ref:`small, terse language +<language>` which pathod shares with its evil twin :ref:`pathoc`. To start +playing with pathod, fire up the daemon: + +>>> pathod + +By default, the service listens on port 9999 of localhost, and 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 :ref:`language documentation <language>` to get (much) fancier. The +pathod daemon also takes a range of configuration options. To view those, use +the command-line help: + +>>> pathod --help + +Mimicing a proxy +^^^^^^^^^^^^^^^^ + +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. + +Anchors +^^^^^^^ + +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. + + +File Access +^^^^^^^^^^^ + +There are two operators in the :ref:`language <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" + + +Internal Error Responses +^^^^^^^^^^^^^^^^^^^^^^^^ + +Pathod uses the non-standard 800 response code to indicate internal errors, to +distinguish them from crafted responses. For example, a request to: + + http://localhost:9999/p/foo + +... will return an 800 response because "foo" is not a valid page specifier. + + + + + +.. _pathoc: + + +pathoc +------ + +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 :ref:`small, terse language <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 + + +Getting Started +^^^^^^^^^^^^^^^ + +The basic pattern for pathoc commands is as follows: + + 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:: + + > pathoc google.com get:/ + 07-06-16 12:13:43: >> 'GET':/ + << 302 Found: 261 bytes + +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 302 redirection. 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):: + + > pathoc -s www.google.com get:/ + 07-06-16 12:14:56: >> 'GET':/ + << 302 Found: 262 bytes + + +Multiple Requests +^^^^^^^^^^^^^^^^^ + +There are two ways to tell pathoc to issue multiple requests. The first is to specify +them on the command-line, like so:: + + > pathoc google.com get:/ get:/ + 07-06-16 12:21:04: >> 'GET':/ + << 302 Found: 261 bytes + 07-06-16 12:21:04: >> 'GET':/ + << 302 Found: 261 bytes + +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 requests is to use the **-n** flag:: + + > pathoc -n 2 google.com get:/ + 07-06-16 12:21:04: >> 'GET':/ + << 302 Found: 261 bytes + 07-06-16 12:21:04: >> 'GET':/ + << 302 Found: 261 bytes + +The output is identical, but two separate TCP connections are made to the +upstream server. These two specification styles can be combined:: + + pathoc -n 2 google.com get:/ get:/ + + +Here, two distinct TCP connections are made, with two requests issued over +each. + + + +Basic Fuzzing +^^^^^^^^^^^^^ + +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:: + + pathoc -e -I 200 -t 2 -n 1000 localhost get:/:b@10:ir,@1 + +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. +- The **-n** option tells pathoc to repeat the request 1000 times. +- 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. + + +Interacting with Proxies +^^^^^^^^^^^^^^^^^^^^^^^^ + +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: + +>>> 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: + +>>> 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: + +>>> pathoc -sc google.com:443 -p 8080 localhost get:/ + + + +Embedded response specification +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +One interesting feature of the Request specification language is that you can +embed a response specification 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:: + + 07-06-16 12:32:01: >> 'GET':/p/:s'401:i35,\x27\\x1b\x27:h\x27Content-Length\x27=\x270\x27:h\x27Content-Length\x27=\x270\x27':h'Host'='localhost' + << 401 Unauthorized: 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 reproducible, even with random +components. This feature comes in terribly handy when testing a proxy, since +you can now drive the server response completely from the client, and have a +complete log of reproducible requests to analyze afterwards. + + +Request Examples +---------------- + +.. list-table:: + :widths: 50 50 + :header-rows: 0 + + * - get:/ + - Get path / + + * - get:/:b@100 + - 100 random bytes as the body + + * - get:/:h"Etag"="&;drop table browsers;" + - Add a header + + * - get:/:u"&;drop table browsers;" + - Add a User-Agent header + + * - get:/:b@100:dr + - Drop the connection randomly + + * - get:/:b@100,ascii:ir,@1 + - 100 ASCII bytes as the body, and randomly inject a random byte + + * - ws:/ + - Initiate a websocket handshake. + + +Response Examples +----------------- + +.. list-table:: + :widths: 50 50 + :header-rows: 0 + + + * - 200 + - A basic HTTP 200 response. + + * - 200:r + - A basic HTTP 200 response with no Content-Length header. This will hang. + + * - 200:da + - Server-side disconnect after all content has been sent. + + * - 200:b\@100 + - 100 random bytes as the body. A Content-Length header is added, so the disconnect + is no longer needed. + + * - 200:b\@100:h"Etag"="';drop table servers;" + - Add a Server header + + * - 200:b\@100:dr + - Drop the connection randomly + + * - 200:b\@100,ascii:ir,@1 + - 100 ASCII bytes as the body, and randomly inject a random byte + + * - 200:b\@1k:c"text/json" + - 1k of random bytes, with a text/json content type + + * - 200:b\@1k:p50,120 + - 1k of random bytes, pause for 120 seconds after 50 bytes + + * - 200:b\@1k:pr,f + - 1k of random bytes, but hang forever at a random location + + * - 200:b\@100:h\@1k,ascii_letters='foo' + - 100 ASCII bytes as the body, randomly generated 100k header name, with the value + 'foo'. diff --git a/docs/pathod/language.rst b/docs/pathod/language.rst new file mode 100644 index 00000000..672e21b6 --- /dev/null +++ b/docs/pathod/language.rst @@ -0,0 +1,257 @@ +.. _language: + +language spec +============= + +************ +HTTP Request +************ + + **method:path:[colon-separated list of features]** + +.. list-table:: + :widths: 20 80 + :header-rows: 0 + + * - method + - A :ref:`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. + * - h\:\ :ref:`VALUE`\ =\ :ref:`VALUE`\ + - Set a header. + * - r + - Set the **raw** flag on this response. Pathod will not calculate a + *Content-Length* header if a body is set. + * - c\ :ref:`VALUE` + - A shortcut for setting the Content-Type header. Equivalent to + ``h"Content-Type"=VALUE`` + * - u\ :ref:`VALUE` + uSHORTCUT + - Set a User-Agent header on this request. You can specify either a + complete :ref:`VALUE`, or a User-Agent shortcut: **android**, + **blackberry**, **bingbot**, **chrome**, **firefox**, **googlebot**, + **ie9**, **ipad**, **iphone**, **safari**. + * - b\ :ref:`VALUE` + - Set the body. The appropriate Content-Length header is added + automatically unless the **r** flag is set. + * - s\ :ref:`VALUE` + - An embedded Response specification, appended to the path of the request. + * - x\ :ref:`INTEGER` + - Repeat this message N times. + * - d\ :ref:`OFFSET` + - Disconnect after OFFSET bytes (HTTP/1 only). + * - i\ :ref:`OFFSET`,\ :ref:`VALUE` + - Inject the specified value at the offset (HTTP/1 only) + * - p\ :ref:`OFFSET`,SECONDS + - Pause for SECONDS seconds after OFFSET bytes. SECONDS can be an integer + or "f" to pause forever (HTTP/1 only) + + +************* +HTTP Response +************* + + **code:[colon-separated list of features]** + +.. list-table:: + :widths: 20 80 + :header-rows: 0 + + * - 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. + * - m\ :ref:`VALUE` + - HTTP Reason message. Automatically chosen according to the response + code if not specified. (HTTP/1 only) + * - h\:\ :ref:`VALUE`\ =\ :ref:`VALUE`\ + - Set a header. + * - r + - Set the **raw** flag on this response. Pathod will not calculate a + *Content-Length* header if a body is set. + * - l\ :ref:`VALUE` + - A shortcut for setting the Location header. Equivalent to + ``h"Location"=VALUE`` + * - c\ :ref:`VALUE` + - A shortcut for setting the Content-Type header. Equivalent to + ``h"Content-Type"=VALUE`` + * - b\ :ref:`VALUE` + - Set the body. The appropriate Content-Length header is added + automatically unless the **r** flag is set. + * - d\ :ref:`OFFSET` + - Disconnect after OFFSET bytes (HTTP/1 only). + * - i\ :ref:`OFFSET`,\ :ref:`VALUE` + - Inject the specified value at the offset (HTTP/1 only) + * - p\ :ref:`OFFSET`,SECONDS + - Pause for SECONDS seconds after OFFSET bytes. SECONDS can be an integer + or "f" to pause forever (HTTP/1 only) + +*************** +Websocket Frame +*************** + + **wf:[colon-separated list of features]** + +.. list-table:: + :widths: 20 80 + :header-rows: 0 + + * - b\ :ref:`VALUE` + - Set the frame payload. If a masking key is present, the value is + encoded automatically. + * - c\ :ref:`INTEGER` + - 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**. + * - d\ :ref:`OFFSET` + - Disconnect after OFFSET bytes + * - i\ :ref:`OFFSET`,\ :ref:`VALUE` + - Inject the specified value at the offset + * - p\ :ref:`OFFSET`,SECONDS + - Pause for SECONDS seconds after OFFSET bytes. SECONDS can be an integer + or "f" to pause forever + * - x\ :ref:`INTEGER` + - Repeat this message N times. + * - [-]fin + - Set or un-set the **fin** bit. + * - k\ :ref:`VALUE` + - 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. + * - l\ :ref:`INTEGER` + - Set the payload length in the frame header, regardless of the actual + body length. + * - [-]mask + - Set or un-set the <b>mask</b> bit. + * - r\ :ref:`VALUE` + - Set the raw frame payload. This disables masking, even if the key is present. + * - [-]rsv1 + - Set or un-set the **rsv1** bit. + * - [-]rsv2 + - Set or un-set the **rsv2** bit. + * - [-]rsv2 + - Set or un-set the **rsv2** bit. + + + +********** +Data types +********** + +.. _INTEGER: + +INTEGER +^^^^^^^ + +.. _OFFSET: + +OFFSET +^^^^^^ + +Offsets are calculated relative to the base message, before any injections or +other transforms are applied. They have 3 flavors: + +======= ========================== +integer An integer byte offset +**r** A random location +**a** The end of the message +======= ========================== + + +.. _VALUE: + +VALUE +^^^^^ + +Literals +"""""""" + +Literal values are specified as a quoted strings:: + + "foo" + +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' + + + +Generated +""""""""" + +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: + +========== ==================== +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: + +================= ============================================== +ascii All ASCII characters +ascii_letters A-Za-z +ascii_lowercase a-z +ascii_uppercase A-Z +bytes All 256 byte values +digits 0-9 +hexdigits 0-f +octdigits 0-7 +punctuation !"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ and space +whitespace \\t \\n \\x0b \\x0c \\r and space +================= ============================================== + + + +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" diff --git a/docs/pathod/library.rst b/docs/pathod/library.rst new file mode 100644 index 00000000..b055d089 --- /dev/null +++ b/docs/pathod/library.rst @@ -0,0 +1,14 @@ +.. _library: + +pathod library +============== + +Behind the pathod and pathoc command-line tools lurks the **pathod** library, a +powerful way to manipulate and serve HTTP requests and responses from code. The +canonical documentation for the library is in the code, and can be accessed +using pydoc. + + +.. literalinclude:: ../../examples/pathod/libpathod_pathoc.py + :caption: examples/pathod/libpathod_pathoc.py + :language: python diff --git a/docs/pathod/test.rst b/docs/pathod/test.rst new file mode 100644 index 00000000..cd6e8a29 --- /dev/null +++ b/docs/pathod/test.rst @@ -0,0 +1,35 @@ +.. _test: + +pathod.test +=========== + +The **pathod.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: + +>>> pydoc pathod.test + +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. + + +Context Manager +--------------- + +.. literalinclude:: ../../examples/pathod/test_context.py + :caption: examples/pathod/test_context.py + :language: python + + +One instance per test +--------------------- + +.. literalinclude:: ../../examples/pathod/test_setup.py + :caption: examples/pathod/test_setup.py + :language: python diff --git a/pathod/templates/about.html b/pathod/templates/about.html deleted file mode 100644 index 340dc386..00000000 --- a/pathod/templates/about.html +++ /dev/null @@ -1,22 +0,0 @@ -{% 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> - <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> -</section> -{% endblock %} diff --git a/pathod/templates/docframe.html b/pathod/templates/docframe.html deleted file mode 100644 index 797de20a..00000000 --- a/pathod/templates/docframe.html +++ /dev/null @@ -1,26 +0,0 @@ -{% extends "layout.html" %} - -{% macro subs(s) %} - {% if subsection == s %} - class="active" - {% endif %} -{% endmacro %} - -{% 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( "pathod")}}><a href="/docs/pathod">pathod</a></li> - <li {{subs( "test")}}><a href="/docs/test">pathod.test</a></li> - </ul> - </div> - </div> - <div class="span9"> - {% block body %} {% endblock %} - </div> -</div> -{% endblock %} diff --git a/pathod/templates/docs_lang.html b/pathod/templates/docs_lang.html deleted file mode 100644 index a1d22aef..00000000 --- a/pathod/templates/docs_lang.html +++ /dev/null @@ -1,196 +0,0 @@ -{% extends "docframe.html" %} {% block body %} -<div class="page-header"> - <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> -</ul> - -<div class="tab-content"> - <div class="tab-pane" id="specifying_responses"> - {% include "docs_lang_responses.html" %} - </div> - <div class="tab-pane active" id="specifying_requests"> - {% include "docs_lang_requests.html" %} - </div> - <div class="tab-pane" id="websockets"> - {% include "docs_lang_websockets.html" %} - </div> -</div> - -<section id="features"> - <div class="page-header"> - <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> - - <h3>Literals</h3> - - <p>Literal values are specified as a quoted strings: </p> - - <pre class="example">"foo"</pre> - - <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"><my/path</pre> - - <p>The path value can also be a quoted string, with the same syntax as literals:</p> - - <pre class="example"><"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/pathod/templates/docs_lang_requests.html b/pathod/templates/docs_lang_requests.html deleted file mode 100644 index 81aff535..00000000 --- a/pathod/templates/docs_lang_requests.html +++ /dev/null @@ -1,114 +0,0 @@ -<pre class="example">method:path:[colon-separated list of features]</pre> -</p> - -<table class="table table-bordered"> - <tbody> - <tr> - <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> - </td> - </tr> - - <tr> - <td>h<a href="#valuespec">VALUE</a>=<a href="#valuespec">VALUE</a></td> - <td> - Set a header. - </td> - </tr> - - <tr> - <td>r</td> - <td> - Set the "raw" flag on this response. Pathod will not calculate a Content-Length header - if a body is set. - </td> - </tr> - - <tr> - <td>c<a href="#valuespec">VALUE</a></td> - <td> - A shortcut for setting the Content-Type header. Equivalent to h"Content-Type"=VALUE - </td> - </tr> - - <tr> - <td>u<a href="#valuespec">VALUE</a> - <br> uSHORTCUT - </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> - </td> - </tr> - - <tr> - <td>b<a href="#valuespec">VALUE</a></td> - <td> - Set the body. The appropriate Content-Length header is added automatically unless - the "r" flag is set. - </td> - </tr> - - <tr> - <td>s<a href="#valuespec">VALUE</a></td> - <td> - An embedded Response specification, appended to the path of the request. - </td> - </tr> - - <tr> - <td>x<a href="#valuespec">INTEGER</a></td> - <td> - Repeat this message N times. - </td> - </tr> - - <tr> - <td>d<a href="#offsetspec">OFFSET</a></td> - <td> - <span class="badge badge-info">HTTP/1 only</span> Disconnect after - OFFSET bytes. - </td> - </tr> - - <tr> - <td>i<a href="#offsetspec">OFFSET</a>,<a href="#valuespec">VALUE</a></td> - <td> - <span class="badge badge-info">HTTP/1 only</span> Inject the specified - value at the offset. - </td> - </tr> - - <tr> - <td>p<a href="#offsetspec">OFFSET</a>,SECONDS</td> - <td> - <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> -</table> diff --git a/pathod/templates/docs_lang_responses.html b/pathod/templates/docs_lang_responses.html deleted file mode 100644 index 9a85ff1a..00000000 --- a/pathod/templates/docs_lang_responses.html +++ /dev/null @@ -1,88 +0,0 @@ -<pre class="example">code:[colon-separated list of features]</pre> - -<table class="table table-bordered"> - <tbody> - <tr> - <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> - </td> - </tr> - - <tr> - <td>m<a href="#valuespec">VALUE</a></td> - <td> - <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>h<a href="#valuespec">VALUE</a>=<a href="#valuespec">VALUE</a></td> - <td> - Set a header. - </td> - </tr> - - <tr> - <td>r</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. - </td> - </tr> - - <tr> - <td>l<a href="#valuespec">VALUE</a></td> - <td> - A shortcut for setting the Location header. Equivalent to h"Location"=VALUE - </td> - </tr> - - <tr> - <td>c<a href="#valuespec">VALUE</a></td> - <td> - A shortcut for setting the Content-Type header. Equivalent to h"Content-Type"=VALUE - </td> - </tr> - - <tr> - <td>b<a href="#valuespec">VALUE</a></td> - <td> - Set the body. The appropriate Content-Length header is added automatically unless - the "r" flag is set. - </td> - </tr> - - <tr> - <td>d<a href="#offsetspec">OFFSET</a></td> - <td> - <span class="badge badge-info">HTTP/1 only</span> Disconnect after - OFFSET bytes. - </td> - </tr> - - <tr> - <td>i<a href="#offsetspec">OFFSET</a>,<a href="#valuespec">VALUE</a></td> - <td> - <span class="badge badge-info">HTTP/1 only</span> Inject the specified - value at the offset. - </td> - </tr> - - <tr> - <td>p<a href="#offsetspec">OFFSET</a>,SECONDS</td> - <td> - <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> -</table> diff --git a/pathod/templates/docs_lang_websockets.html b/pathod/templates/docs_lang_websockets.html deleted file mode 100644 index dd318e0b..00000000 --- a/pathod/templates/docs_lang_websockets.html +++ /dev/null @@ -1,115 +0,0 @@ -<pre class="example">wf:[colon-separated list of features]</pre> -</p> - -<table class="table table-bordered"> - <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. - </td> - </tr> - - <tr> - <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), - <b>continue</b>, <b>binary</b>, <b>close</b>, <b>ping</b>, - <b>pong</b>. - - </td> - </tr> - - <tr> - <td> d<a href="#offsetspec">OFFSET</a> </td> - <td> - Disconnect after OFFSET bytes. - </td> - </tr> - - <tr> - <td> [-]fin </td> - <td> - Set or un-set the <b>fin</b> bit. - </td> - </tr> - - <tr> - <td> i<a href="#offsetspec">OFFSET</a>,<a href="#valuespec">VALUE</a> </td> - <td> - Inject the specified value at the offset. - </td> - </tr> - - <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. - </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. - </td> - </tr> - - <tr> - <td> [-]mask </td> - <td> - Set or un-set the <b>mask</b> bit. - </td> - </tr> - - <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. - </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. - </td> - </tr> - - <tr> - <td> [-]rsv1 </td> - <td> - Set or un-set the <b>rsv1</b> bit. - </td> - </tr> - - <tr> - <td> [-]rsv2 </td> - <td> - Set or un-set the <b>rsv2</b> bit. - </td> - </tr> - - <tr> - <td> [-]rsv3 </td> - <td> - Set or un-set the <b>rsv3</b> bit. - </td> - </tr> - - <tr> - <td> x<a href="#valuespec">INTEGER</a> </td> - <td> - Repeat this message N times. - </td> - </tr> - - </tbody> -</table> diff --git a/pathod/templates/docs_libpathod.html b/pathod/templates/docs_libpathod.html deleted file mode 100644 index 8eb6846a..00000000 --- a/pathod/templates/docs_libpathod.html +++ /dev/null @@ -1,23 +0,0 @@ -{% extends "docframe.html" %} {% block body %} -<div class="page-header"> - <h1> - pathod - <small>Using pathod and pathoc in code.</small> - </h1> -</div> - -<div class="row"> - <div class="span6"> - <p> - Behind the pathod and pathoc command-line tools lurks <b>pathod</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> - {% include "pathod_pathoc.html" %} - </div> -</div> -{% endblock %} diff --git a/pathod/templates/docs_pathoc.html b/pathod/templates/docs_pathoc.html deleted file mode 100644 index d38c3a77..00000000 --- a/pathod/templates/docs_pathoc.html +++ /dev/null @@ -1,211 +0,0 @@ -{% extends "docframe.html" %} {% block body %} -<div class="page-header"> - <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> - -<pre class="terminal">pathoc --help</pre> - -<section> - <div class="page-header"> - <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"> - > pathoc google.com get:/ << 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"> - > pathoc -s google.com get:/ << 301 Moved Permanently: 219 bytes - </pre> -</section> - - -<section> - <div class="page-header"> - <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> - - <pre class="terminal"> - > pathoc google.com get:/ get:/ << 301 Moved Permanently: 219 bytes << - 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>The other way to issue multiple requets is to use the <b>-n</b> flag:</p> - - <pre class="terminal"> - > pathoc -n 2 google.com get:/ << 301 Moved Permanently: 219 bytes << 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> - - <pre class="terminal"> - > pathoc -n 2 google.com get:/ get:/ << 301 Moved Permanently: 219 bytes << - 301 Moved Permanently: 219 bytes << 301 Moved Permanently: 219 bytes << - 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> - </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> - - <pre class="terminal"> - > 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> - - <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> - </ul> -</section> - - -<section> - <div class="page-header"> - <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> - - <pre class="terminal">> 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> - - <pre class="terminal">> 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> - - <pre class="terminal">> pathoc -sc google.com:443 -p 8080 localhost get:/</pre> -</section> - - -<section> - <div class="page-header"> - <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">> 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"> - > > 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/pathod/templates/docs_pathod.html b/pathod/templates/docs_pathod.html deleted file mode 100644 index 0d0ae933..00000000 --- a/pathod/templates/docs_pathod.html +++ /dev/null @@ -1,172 +0,0 @@ -{% extends "docframe.html" %} {% block body %} -<div class="page-header"> - <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> - -<section> - <div class="page-header"> - <h1>Getting started</h1> - </div> - - <p>To start playing with pathod, simply fire up the daemon:</p> - - <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> - - <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> - - <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> - - <pre class="terminal">./pathod --help</pre> - -</section> - -<section> - <div class="page-header"> - <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> -</section> - - -<section> - <div class="page-header"> - <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> - - <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> - </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>></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> - </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> - - <pre class="example">http://localhost:9999/p/foo</pre> - - <p> - ... will return an 800 response because "foo" is not a valid page specifier. - </p> -</section> - - -<section> - <div class="page-header"> - <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> - - <table class="table table-bordered"> - <tbody> - <tr> - <td> - /api/clear_log - </td> - <td> - A POST to this URL clears the log buffer. - </td> - </tr> - <tr> - <td> - /api/info - </td> - <td> - Basic version and configuration info. - </td> - </tr> - <tr> - <td> - /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: - - <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/pathod/templates/docs_test.html b/pathod/templates/docs_test.html deleted file mode 100644 index ecd84bc7..00000000 --- a/pathod/templates/docs_test.html +++ /dev/null @@ -1,50 +0,0 @@ -{% extends "docframe.html" %} {% block body %} -<div class="page-header"> - <h1> - pathod.test - <small>Using pathod in unit tests.</small> - </h1> -</div> - -<p>The <b>pathod.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> - -<pre class="terminal">pydoc pathod.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> - -<section> - <div class="page-header"> - <h1>Context Manager</h1> - </div> - - {% include "examples_context.html" %} -</section> - -<section> - <div class="page-header"> - <h1>One instance per test</h1> - </div> - - {% include "examples_setup.html" %} -</section> - -<section> - <div class="page-header"> - <h1>One instance per suite</h1> - </div> - - {% include "examples_setupall.html" %} -</section> -{% endblock %} diff --git a/pathod/templates/download.html b/pathod/templates/download.html deleted file mode 100644 index bd8950e8..00000000 --- a/pathod/templates/download.html +++ /dev/null @@ -1,39 +0,0 @@ -{% extends "frame.html" %} {% block body %} -<section> - <div class="page-header"> - <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> -</section> - -<section> - <div class="page-header"> - <h1>github</h1> - </div> - - <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> - </div> - - <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> - </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> - </div> -</section> -{% endblock %} diff --git a/pathod/templates/examples_context.html b/pathod/templates/examples_context.html deleted file mode 100644 index 20b02c39..00000000 --- a/pathod/templates/examples_context.html +++ /dev/null @@ -1,24 +0,0 @@ -<div class="highlight"><pre><span class="kn">import</span> <span class="nn">requests</span> -<span class="kn">from</span> <span class="nn">pathod</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">"""</span> -<span class="sd"> Testing the requests module with</span> -<span class="sd"> a pathod context manager.</span> -<span class="sd"> """</span> - <span class="c"># Start pathod in a separate thread</span> - <span class="k">with</span> <span class="n">test</span><span class="o">.</span><span class="n">Daemon</span><span class="p">()</span> <span class="k">as</span> <span class="n">d</span><span class="p">:</span> - <span class="c"># Get a URL for a pathod spec</span> - <span class="n">url</span> <span class="o">=</span> <span class="n">d</span><span class="o">.</span><span class="n">p</span><span class="p">(</span><span class="s">"200:b@100"</span><span class="p">)</span> - <span class="c"># ... and request it</span> - <span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="n">url</span><span class="p">)</span> - - <span class="c"># Check the returned data</span> - <span class="k">assert</span> <span class="n">r</span><span class="o">.</span><span class="n">status_code</span> <span class="o">==</span> <span class="mi">200</span> - <span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">r</span><span class="o">.</span><span class="n">content</span><span class="p">)</span> <span class="o">==</span> <span class="mi">100</span> - - <span class="c"># Check pathod's internal log</span> - <span class="n">log</span> <span class="o">=</span> <span class="n">d</span><span class="o">.</span><span class="n">last_log</span><span class="p">()[</span><span class="s">"request"</span><span class="p">]</span> - <span class="k">assert</span> <span class="n">log</span><span class="p">[</span><span class="s">"method"</span><span class="p">]</span> <span class="o">==</span> <span class="s">"PUT"</span> -</pre></div> diff --git a/pathod/templates/examples_setup.html b/pathod/templates/examples_setup.html deleted file mode 100644 index b8419171..00000000 --- a/pathod/templates/examples_setup.html +++ /dev/null @@ -1,32 +0,0 @@ -<div class="highlight"><pre><span class="kn">import</span> <span class="nn">requests</span> -<span class="kn">from</span> <span class="nn">pathod</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">"""</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"> """</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> - - <span class="k">def</span> <span class="nf">tearDown</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">shutdown</span><span class="p">()</span> - - <span class="k">def</span> <span class="nf">test_simple</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> - <span class="c"># Get a URL for a pathod spec</span> - <span class="n">url</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">d</span><span class="o">.</span><span class="n">p</span><span class="p">(</span><span class="s">"200:b@100"</span><span class="p">)</span> - <span class="c"># ... and request it</span> - <span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="n">url</span><span class="p">)</span> - - <span class="c"># Check the returned data</span> - <span class="k">assert</span> <span class="n">r</span><span class="o">.</span><span class="n">status_code</span> <span class="o">==</span> <span class="mi">200</span> - <span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">r</span><span class="o">.</span><span class="n">content</span><span class="p">)</span> <span class="o">==</span> <span class="mi">100</span> - - <span class="c"># Check pathod's internal log</span> - <span class="n">log</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">d</span><span class="o">.</span><span class="n">last_log</span><span class="p">()[</span><span class="s">"request"</span><span class="p">]</span> - <span class="k">assert</span> <span class="n">log</span><span class="p">[</span><span class="s">"method"</span><span class="p">]</span> <span class="o">==</span> <span class="s">"PUT"</span> -</pre></div> diff --git a/pathod/templates/examples_setupall.html b/pathod/templates/examples_setupall.html deleted file mode 100644 index 3308f6cb..00000000 --- a/pathod/templates/examples_setupall.html +++ /dev/null @@ -1,40 +0,0 @@ -<div class="highlight"><pre><span class="kn">import</span> <span class="nn">requests</span> -<span class="kn">from</span> <span class="nn">pathod</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">"""</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"> """</span> - <span class="nd">@classmethod</span> - <span class="k">def</span> <span class="nf">setUpAll</span><span class="p">(</span><span class="n">cls</span><span class="p">):</span> - <span class="n">cls</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> - - <span class="nd">@classmethod</span> - <span class="k">def</span> <span class="nf">tearDownAll</span><span class="p">(</span><span class="n">cls</span><span class="p">):</span> - <span class="n">cls</span><span class="o">.</span><span class="n">d</span><span class="o">.</span><span class="n">shutdown</span><span class="p">()</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="c"># Clear the pathod logs between tests</span> - <span class="bp">self</span><span class="o">.</span><span class="n">d</span><span class="o">.</span><span class="n">clear_log</span><span class="p">()</span> - - <span class="k">def</span> <span class="nf">test_simple</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> - <span class="c"># Get a URL for a pathod spec</span> - <span class="n">url</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">d</span><span class="o">.</span><span class="n">p</span><span class="p">(</span><span class="s">"200:b@100"</span><span class="p">)</span> - <span class="c"># ... and request it</span> - <span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="n">url</span><span class="p">)</span> - - <span class="c"># Check the returned data</span> - <span class="k">assert</span> <span class="n">r</span><span class="o">.</span><span class="n">status_code</span> <span class="o">==</span> <span class="mi">200</span> - <span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">r</span><span class="o">.</span><span class="n">content</span><span class="p">)</span> <span class="o">==</span> <span class="mi">100</span> - - <span class="c"># Check pathod's internal log</span> - <span class="n">log</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">d</span><span class="o">.</span><span class="n">last_log</span><span class="p">()[</span><span class="s">"request"</span><span class="p">]</span> - <span class="k">assert</span> <span class="n">log</span><span class="p">[</span><span class="s">"method"</span><span class="p">]</span> <span class="o">==</span> <span class="s">"PUT"</span> - - <span class="k">def</span> <span class="nf">test_two</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> - <span class="k">assert</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">d</span><span class="o">.</span><span class="n">log</span><span class="p">()</span> -</pre></div> diff --git a/pathod/templates/frame.html b/pathod/templates/frame.html deleted file mode 100644 index 4223458d..00000000 --- a/pathod/templates/frame.html +++ /dev/null @@ -1,7 +0,0 @@ -{% extends "layout.html" %} {% block content %} -<div class="row"> - <div class="span12"> - {% block body %} {% endblock %} - </div> -</div> -{% endblock %} diff --git a/pathod/templates/index.html b/pathod/templates/index.html deleted file mode 100644 index a85a4040..00000000 --- a/pathod/templates/index.html +++ /dev/null @@ -1,60 +0,0 @@ -{% extends "frame.html" %} {% block body %} -<div class="masthead"> - <div class="container"> - <h1>pathod: pathological HTTP</h1> - - <p>Crafted malice for tormenting HTTP clients and servers</p> - - <img src="/static/torture.png"> - </div> -</div> - -<div class="row"> - <div class="span6"> - <div> - <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> - - <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> - </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> - <li>GitHub: <a href="https://github.com/mitmproxy/pathod">github.com/mitmproxy/pathod</a></li> - </ul> - </div> - </div> - </div> -</section> -{% endblock %} diff --git a/pathod/templates/layout.html b/pathod/templates/layout.html deleted file mode 100644 index af2857b1..00000000 --- a/pathod/templates/layout.html +++ /dev/null @@ -1,75 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - -<head> - <meta charset="utf-8"> - <title>pathod</title> - <link href="/static/bootstrap.min.css" rel="stylesheet"> - <link href="/static/pathod.css" rel="stylesheet"> - <link href="/static/syntax.css" rel="stylesheet"> - <script src="/static/jquery-1.7.2.min.js"></script> - <script src="/static/jquery.scrollTo-min.js"></script> - <script src="/static/jquery.localscroll-min.js"></script> - <script src="/static/bootstrap.min.js"></script> - <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <meta name="description" content=""> - <meta name="author" content=""> - <style type="text/css"> - 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> - <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> - </div> - </div> - - <div class="container"> - {% block content %} {% endblock %} - <hr> - <footer> - <span>© Aldo Cortesi 2015</span> - <span class="pull-right">[served with pathod]</span> - </footer> - </div> -</body> -<script> - $(function() { - $.localScroll({ - duration: 300, - offset: { - top: -45 - } - }); - }); - -</script> - -</html> diff --git a/pathod/templates/log.html b/pathod/templates/log.html deleted file mode 100644 index b0484cb8..00000000 --- a/pathod/templates/log.html +++ /dev/null @@ -1,31 +0,0 @@ -{% 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> - -<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/pathod/templates/onelog.html b/pathod/templates/onelog.html deleted file mode 100644 index c222ad60..00000000 --- a/pathod/templates/onelog.html +++ /dev/null @@ -1,8 +0,0 @@ -{% extends "frame.html" %} {% block body %} -<h2>Log entry {{ lid }}</h2> -<hr> - -<pre> - {{ alog }} -</pre> -{% endblock %} diff --git a/pathod/templates/request_preview.html b/pathod/templates/request_preview.html deleted file mode 100644 index 25d73679..00000000 --- a/pathod/templates/request_preview.html +++ /dev/null @@ -1,44 +0,0 @@ -{% extends "frame.html" %} {% block body %} -<div class="page-header"> - <h1>pathoc preview</h1> -</div> - -<div style="margin-bottom: 20px" class="row"> - <div class="span2 header"> - Specification: - </div> - <div class="span10"> - {% include "request_previewform.html" %} - </div> -</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> -{% elif error %} -<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 %} diff --git a/pathod/templates/request_previewform.html b/pathod/templates/request_previewform.html deleted file mode 100644 index 91b5598a..00000000 --- a/pathod/templates/request_previewform.html +++ /dev/null @@ -1,53 +0,0 @@ -<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 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> - - <table class="table table-bordered"> - <tbody> - <tr> - <td><a href="/request_preview?spec=get:/">get:/</a></td> - <td>Get path /</td> - </tr> - <tr> - <td><a href="/request_preview?spec=get:/:b@100">get:/:b@100</a></td> - <td>100 random bytes as the body</td> - </tr> - <tr> - <td><a href='/request_preview?spec=get:/:h"Etag"="';drop table browsers;"'>get:/:h"Etag"="';drop table browsers;"</a></td> - <td>Add a header</td> - </tr> - <tr> - <td><a href='/request_preview?spec=get:/:u"';drop table browsers;"'>get:/:u"';drop table browsers;"</a></td> - <td>Add a User-Agent header</td> - </tr> - <tr> - <td><a href="/request_preview?spec=get:/:b@100:dr">get:/:b@100:dr</a></td> - <td>Drop the connection randomly</td> - </tr> - <tr> - <td> - <a href="/request_preview?spec="></a> - </td> - <td></td> - </tr> - <tr> - <td><a href="/request_preview?spec=get:/:b@100,ascii:ir,@1">get:/:b@100,ascii:ir,@1</a></td> - <td>100 ASCII bytes as the body, and randomly inject a random byte</td> - </tr> - <tr> - <td><a href="/request_preview?spec=ws:/">ws:/</a></td> - <td>Initiate a websocket handshake.</td> - </tr> - </tbody> - </table> -</div> diff --git a/pathod/templates/response_preview.html b/pathod/templates/response_preview.html deleted file mode 100644 index bbce6d6c..00000000 --- a/pathod/templates/response_preview.html +++ /dev/null @@ -1,44 +0,0 @@ -{% extends "frame.html" %} {% block body %} -<div class="page-header"> - <h1>pathod preview</h1> -</div> - -<div style="margin-bottom: 20px" class="row"> - <div class="span2 header"> - Specification: - </div> - <div class="span10"> - {% include "response_previewform.html" %} - </div> -</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> -{% elif error %} -<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 %} diff --git a/pathod/templates/response_previewform.html b/pathod/templates/response_previewform.html deleted file mode 100644 index d46043f3..00000000 --- a/pathod/templates/response_previewform.html +++ /dev/null @@ -1,87 +0,0 @@ -<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 type="submit" class="btn" value="preview"> - {% if not nocraft %} - <a href="#" id="submitspec" class="btn">go</a> - {% endif %} -</form> - -<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> - - <table class="table table-bordered"> - <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> - </tr> - <tr> - <td><a href="/response_preview?spec=200:da">200:da</a></td> - <td>Server-side disconnect after all content has been sent.</td> - </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> - </tr> - <tr> - <td><a href='/response_preview?spec=200:b@100:h"Server"="';drop table servers;"'>200:b@100:h"Etag"="';drop table servers;"</a></td> - <td>Add a Server header</td> - </tr> - <tr> - <td><a href="/response_preview?spec=200:b@100:dr">200:b@100:dr</a></td> - <td>Drop the connection randomly</td> - </tr> - <tr> - <td><a href="/response_preview?spec=200:b@100,ascii:ir,@1">200:b@100,ascii:ir,@1</a></td> - <td>100 ASCII bytes as the body, and randomly inject a random byte</td> - </tr> - <tr> - <td><a href='/response_preview?spec=200:b@1k:c"text/json"'>200:b@1k:c"text/json"</a></td> - <td>1k of random bytes, with a text/json content type</td> - </tr> - <tr> - <td><a href='/response_preview?spec=200:b@1k:p50,120'>200:b@1k:p50,120</a></td> - <td>1k of random bytes, pause for 120 seconds after 50 bytes</td> - </tr> - <tr> - <td><a href='/response_preview?spec=200:b@1k:pr,f'>200:b@1k:pr,f</a></td> - <td>1k of random bytes, but hang forever at a random location</td> - </tr> - <tr> - <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> - </tr> - </tbody> - </table> -</div> - -{% if not nocraft %} -<script> - $(function() { - $("#submitspec").click(function() { - document.location = "{{craftanchor}}" + $("#spec").val() - }); - }); - -</script> -{% endif %} |