summaryrefslogtreecommitdiffstats
path: root/lib/python/web_support.py
diff options
context:
space:
mode:
authorFlorian Weimer <fw@deneb.enyo.de>2009-10-11 12:02:02 +0000
committerFlorian Weimer <fw@deneb.enyo.de>2009-10-11 12:02:02 +0000
commita28bf55d5e2ad8d7b6c3c63cb707f49c47c86f11 (patch)
treebc0ffc125ce8b2d3e461581dcccdf8bc8812dbce /lib/python/web_support.py
parent48f5d929f223e62304640fd8eff34a40f52c8440 (diff)
lib/python/web_support.py (WebServiceHttp): implement HTTP invocation
Introduces flatten_later helper methods in Result objects. git-svn-id: svn+ssh://svn.debian.org/svn/secure-testing@12984 e39458fd-73e7-0310-bf30-c45bca0a0e42
Diffstat (limited to 'lib/python/web_support.py')
-rw-r--r--lib/python/web_support.py111
1 files changed, 111 insertions, 0 deletions
diff --git a/lib/python/web_support.py b/lib/python/web_support.py
index 4c07cbf2ba..065f93bccc 100644
--- a/lib/python/web_support.py
+++ b/lib/python/web_support.py
@@ -26,6 +26,9 @@ import grp
import traceback
import types
import urllib
+import threading
+import SocketServer
+import BaseHTTPServer
class ServinvokeError(Exception):
pass
@@ -556,6 +559,13 @@ class Result:
def flatten(self, write):
pass
+ def flatten_later(self):
+ """Flattens this result.
+
+ Returns a closure which sends the result using a
+ BaseHTTPRequestHandler object passed as argument."""
+ pass
+
class RedirectResult(Result):
"""Permanently redirects the browser to a new URL."""
def __init__(self, url, permanent=True):
@@ -568,6 +578,13 @@ class RedirectResult(Result):
def flatten(self, write):
write("Status: %d\nLocation: %s\n\n" % (self.status, self.url))
+ def flatten_later(self):
+ def later(req):
+ req.send_response(self.status)
+ req.send_header('Location', self.url)
+ req.end_headers()
+ return later
+
class HTMLResult(Result):
"""An object of this class combines a status code with HTML contents."""
def __init__(self, contents, status=200, doctype=''):
@@ -584,6 +601,19 @@ class HTMLResult(Result):
write("Content-Type: text/html\n\n%s\n" % self.doctype)
self.contents.flatten(write)
+ def flatten_later(self):
+ buf = cStringIO.StringIO()
+ buf.write(self.doctype)
+ buf.write('\n')
+ self.contents.flatten(buf.write)
+ buf = buf.getvalue()
+ def later(req):
+ req.send_response(self.status)
+ req.send_header('Content-Type', 'text/html; charset=UTF-8')
+ req.end_headers()
+ req.wfile.write(buf)
+ return later
+
class BinaryResult(Result):
"""An object of this class combines a status code with HTML contents."""
def __init__(self, contents, status=200,
@@ -599,6 +629,13 @@ class BinaryResult(Result):
write("Content-Type: %s\n\n" % self.mimetype)
write(self.contents)
+ def flatten_later(self):
+ def later(req):
+ req.send_response(self.status)
+ req.send_header('Content-Type', self.mimetype)
+ req.wfile.write(self.contents)
+ return later
+
class WebServiceBase:
def __init__(self):
self.router = PathRouter()
@@ -679,6 +716,80 @@ class WebService(Service, WebServiceBase):
assert isinstance(r, Result), `r`
r.flatten(result.write)
+class ThreadingHTTPServer(BaseHTTPServer.HTTPServer,
+ SocketServer.ThreadingMixIn):
+ pass
+
+RE_BASE_URL = re.compile(r'^http://([^/]+)(.*)')
+
+class WebServiceHTTP(WebServiceBase):
+ def __init__(self, socket_name):
+ WebServiceBase.__init__(self)
+ (base_url, address, port) = socket_name
+ self.lock = threading.Lock()
+
+ self.__parse_base_url(base_url)
+
+ service_self = self
+ class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
+ def do_GET(self):
+ (method, path, remaining, params) = self.route()
+ if path is None:
+ return
+
+ url = URLFactory(service_self.server_name,
+ service_self.script_name,
+ path, params)
+
+ service_self.lock.acquire()
+ try:
+ service_self.pre_dispatch()
+ r = method(remaining, params, url)
+ assert isinstance(r, Result), `r`
+ result = r.flatten_later()
+ finally:
+ service_self.lock.release()
+ result(self)
+
+ def __parse_path(self):
+ pos = self.path.find('?')
+ if pos < 0:
+ return (self.path, {})
+ path = self.path[:pos]
+ if path[:1] != '/':
+ path = '/' + path
+ params = cgi.parse_qs(self.path[pos + 1:])
+ return (path, params)
+
+ def route(self):
+ (path, params) = self.__parse_path()
+ prefix_len = len(service_self.script_name)
+ prefix = path[0:prefix_len]
+ result = None
+ if prefix == service_self.script_name:
+ suffix = path[prefix_len:]
+ try:
+ (method, remaining) = \
+ service_self.router.get(suffix)
+ return (method, suffix, remaining, params)
+ except InvalidPath:
+ pass
+ self.send_error(404, "page not found")
+ return (None, None, None, None)
+
+ self.server = ThreadingHTTPServer((address, port), Handler)
+
+ def run(self):
+ self.server.serve_forever()
+
+ def __parse_base_url(self, url):
+ m = RE_BASE_URL.match(url)
+ if m is None:
+ raise ValueError("invalid base URL: " + url)
+ self.server_name = m.group(1)
+ self.script_name = m.group(2)
+
+
def __test():
assert str(URL("")) == ""
assert str(URL("abc")) == "abc"

© 2014-2024 Faster IT GmbH | imprint | privacy policy