aboutsummaryrefslogtreecommitdiffstats
path: root/libpathod
diff options
context:
space:
mode:
Diffstat (limited to 'libpathod')
-rw-r--r--libpathod/pathod.py21
-rw-r--r--libpathod/templates/docs_pathod.html16
-rw-r--r--libpathod/test.py1
-rw-r--r--libpathod/utils.py13
4 files changed, 46 insertions, 5 deletions
diff --git a/libpathod/pathod.py b/libpathod/pathod.py
index d52af15b..587e51bf 100644
--- a/libpathod/pathod.py
+++ b/libpathod/pathod.py
@@ -1,7 +1,7 @@
import urllib, threading, re, logging, socket, sys, base64
from netlib import tcp, http, odict, wsgi
import netlib.utils
-import version, app, language
+import version, app, language, utils
logger = logging.getLogger('pathod')
@@ -54,13 +54,24 @@ class PathodHandler(tcp.BaseHandler):
# Normal termination
return False, None
- parts = http.parse_init_http(line)
- if not parts:
+ m = utils.MemBool()
+ if m(http.parse_init_connect(line)):
+ self.wfile.write(
+ 'HTTP/1.1 200 Connection established\r\n' +
+ ('Proxy-agent: %s\r\n'%version.NAMEVERSION) +
+ '\r\n'
+ )
+ self.wfile.flush()
+
+ if m(http.parse_init_proxy(line)):
+ method, _, _, _, path, httpversion = m.v
+ elif m(http.parse_init_http(line)):
+ method, path, httpversion = m.v
+ else:
s = "Invalid first line: %s"%repr(line)
self.info(s)
return False, dict(type = "error", msg = s)
- method, path, httpversion = parts
headers = http.read_headers(self.rfile)
if headers is None:
s = "Invalid headers"
@@ -133,7 +144,7 @@ class PathodHandler(tcp.BaseHandler):
self.info("\n".join(s))
def handle(self):
- if self.server.ssloptions:
+ if self.server.ssloptions and not self.server.ssloptions["ssl_after_connect"]:
try:
self.convert_to_ssl(
self.server.ssloptions["certfile"],
diff --git a/libpathod/templates/docs_pathod.html b/libpathod/templates/docs_pathod.html
index 8b345d71..42459352 100644
--- a/libpathod/templates/docs_pathod.html
+++ b/libpathod/templates/docs_pathod.html
@@ -45,6 +45,22 @@ those, use the command-line help:</p>
</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>Proxy mode operates even when Pathod is run in SSL mode, but we do not
+support nested SSL connections. This means that CONNECT requests will cause an
+error response.</p>
+
+</section>
+
<section>
<div class="page-header">
diff --git a/libpathod/test.py b/libpathod/test.py
index ed0ee26a..22dc035d 100644
--- a/libpathod/test.py
+++ b/libpathod/test.py
@@ -75,6 +75,7 @@ class _PaThread(threading.Thread):
ssloptions = dict(
keyfile = utils.data.path("resources/server.key"),
certfile = utils.data.path("resources/server.crt"),
+ ssl_after_connect = False
)
else:
ssloptions = self.ssl
diff --git a/libpathod/utils.py b/libpathod/utils.py
index 70a97cff..26e9427d 100644
--- a/libpathod/utils.py
+++ b/libpathod/utils.py
@@ -8,6 +8,19 @@ SIZE_UNITS = dict(
t = 1024**4,
)
+
+class MemBool:
+ """
+ Truth-checking with a memory, for use in chained if statements.
+ """
+ def __init__(self):
+ self.v = None
+
+ def __call__(self, v):
+ self.v = v
+ return bool(v)
+
+
def parse_size(s):
try:
return int(s)