lib/http.py
changeset 46 185504387370
parent 45 e94ab812c0c8
child 47 3d59c9eeffaa
--- a/lib/http.py	Sun Feb 08 03:13:11 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,227 +0,0 @@
-"""
-    WSGI HTTP utility code
-"""
-
-# for utility functions
-import cgi
-
-# for header handling
-import wsgiref.headers
-
-# for path handling
-import os.path
-
-class Request (object) :
-    """
-        HTTP Request with associated metadata
-    """
-
-    def __init__ (self, env) :
-        """
-            Parse env data
-        """
-
-        # store env
-        self.env = env
-
-        # get the querystring
-        self.arg_str = env.get('QUERY_STRING', '')
-
-        # parse query args
-        self.arg_dict = cgi.parse_qs(self.arg_str, True)
- 
-    @property
-    def site_host (self) :
-        """
-            Returns the site's hostname (DNS name)
-        """
-        
-        return self.env['HTTP_HOST']
-  
-    @property
-    def site_root (self) :
-        """
-            Returns the URL path to the requested script's directory with no trailing slash, i.e.
-
-            /               -> 
-            /foo.cgi        -> 
-            /foo/bar.cgi    -> /foo
-        """
-
-        return os.path.dirname(self.env['SCRIPT_NAME']).rstrip('/')
-    
-    @property
-    def page_prefix (self) :
-        """
-            Returns the URL path root for page URLs, based on REQUEST_URI with PATH_INFO removed
-
-            /                   -> 
-            /foo.cgi            -> /foo.cgi
-            /foo.cgi/index      -> /foo.cgi
-            /foo.cgi/quux/bar   -> /foo.cgi
-            /quux/foo.cgi/bar   -> /quux/foo.cgi
-            /bar                -> 
-        """
-        
-        # XXX: request uri path without the query string
-        request_path = self.env.get('REQUEST_URI', '').split('?', 1)[0].rstrip('/')
-
-        # path info
-        page_name = self.get_page_name()
-
-        # special-case for empty page_name
-        if not page_name :
-            return request_path
-        
-        # sanity-check
-        assert request_path.endswith(page_name)
-        
-        # trim
-        return request_path[:-len(page_name)].rstrip('/')
-    
-    def get_page_name (self) :
-        """
-            Returns the requested page path with no leading slash, i.e.
-
-            /foo.cgi        -> 
-            /foo.cgi/       -> 
-            /foo.cgi/bar    -> bar
-            /foo.cgi/quux/  -> quux/
-        """
-        
-        # the raw PATH_INFO
-        path_info = self.env.get('PATH_INFO')
-        
-        # avoid nasty '.' paths
-        if path_info :
-            return os.path.normpath(path_info).lstrip('/')
-
-        else :
-            return ''
-    
-    def get_args (self) :
-        """
-            Iterate over all available (key, value) pairs from the query string
-        """
-
-        return cgi.parse_qsl(self.arg_str)
-
-class Response (object) :
-    """
-        HTTP Response with headers and data
-    """
-
-    def __init__ (self, data, content_type='text/html', status='200 OK', charset='UTF-8') :
-        """
-            Create the response. The Content-type header is built from the given values. The given \a data must be
-            either a str (which is sent plain), an unicode object (which is encoded with the relevant charset), or
-            None, whereupon an empty response body is sent. The content_type argument can also be forced to None to
-            not send a Content-type header (e.g. for redirects)
-        """
-
-        # store info
-        self.status = status
-        self.data = data
-        self.charset = charset
-
-        # headers
-        self.headers = wsgiref.headers.Headers([])
-        
-        # add Content-type header?
-        if content_type :
-            self.add_header('Content-type', content_type, charset=charset)
-
-    def add_header (self, name, value, **params) :
-        """
-            Add response header with the given name/value, plus option params
-
-            XXX: uses the wsgiref.headers code, not sure how that behaves re multiple headers with the same name, etc
-        """
-        
-        self.headers.add_header(name, value, **params)
-    
-    def get_status (self) :
-        """
-            Returns response status string (XXX Foo)
-        """
-
-        return self.status
-    
-    def get_headers (self) :
-        """
-            Returns the list of header (name, value) pairs
-        """
-
-        return self.headers.items()
-
-    def get_data (self) :
-        """
-            Returns the response data - as an encoded string
-        """
-
-        if self.data :
-            return self.data.encode(self.charset)
-
-        else :
-            return ''
-
-class ErrorResponse (Response) :
-    """
-        A response with an error code / message
-    """
-
-    def __init__ (self, status, message, details=None) :
-        """
-            Build a plain error message response with the given status/message
-
-            @param status HTTP status code
-            @param message short message to describe errors
-            @param details optional details, plaintext
-        """
-
-        data = """\
-<html><head><title>%(title)s</title></head><body>
-<h1>%(title)s</h1>
-<p>%(message)s</p>
-%(details)s
-</body></html>
-""" % dict(
-            title       = status, 
-            message     = message,
-            details     = '<pre>%s</pre>' % details if details else ''
-        )
-            
-        super(ErrorResponse, self).__init__(data, status=status)
-
-class ResponseError (Exception) :
-    """
-        An exception that results in a specfic 4xx ErrorResponse message to the client
-    """
-
-    def __init__ (self, message, status='400 Bad Request', details=None) :
-        self.status = status
-        self.message = message
-        self.details = details
-
-        super(ResponseError, self).__init__(message)
-
-    def get_response (self) :
-        return ErrorResponse(self.status, self.message, self.details)
-
-class Redirect (Response) :
-    """
-        Redirect response
-    """
-
-    def __init__ (self, url) :
-        """
-            Redirect to given *absolute* URL
-        """
-        
-        # no content-type or data
-        super(Redirect, self).__init__(None, content_type=None, status='302 Found')
-
-        # add Location: header
-        self.add_header("Location", url)
-
-