# HG changeset patch # User paulb # Date 1075939859 0 # Node ID 980473b735d083b45524c15abc6197a2b1497997 # Parent 9d5566eb4ad041ccae9b622f974c0614bbd174b4 [project @ 2004-02-05 00:10:59 by paulb] Added support for BaseHTTPRequestHandler transactions. Added a commit method for transactions, since some frameworks do not provide support for ad-hoc definition of response information; WebStack must therefore make sure that responses are defined correctly after potentially receiving response information in an order unsuitable for the underlying framework. diff -r 9d5566eb4ad0 -r 980473b735d0 WebStack/BaseHTTPRequestHandler.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebStack/BaseHTTPRequestHandler.py Thu Feb 05 00:10:59 2004 +0000 @@ -0,0 +1,166 @@ +#!/usr/bin/env python + +""" +BaseHTTPRequestHandler classes. +""" + +import Generic +from cgi import FieldStorage +from StringIO import StringIO + +class Transaction(Generic.Transaction): + + """ + BaseHTTPRequestHandler transaction interface. + """ + + def __init__(self, trans): + + """ + Initialise the transaction using the BaseHTTPRequestHandler instance + 'trans'. + """ + + self.trans = trans + + # Other attributes of interest in instances of this class. + + self.content_type = None + self.response_code = 100 + self.content = StringIO() + + def commit(self): + + """ + A special method, synchronising the transaction with framework-specific + objects. + """ + + self.trans.send_response(self.response_code) + self.trans.send_header("Content-Type", self.format_content_type(self.content_type)) + self.trans.end_headers() + self.content.seek(0) + self.trans.wfile.write(self.content.read()) + + # Request-related methods. + + def get_request_stream(self): + + """ + A framework-specific method which returns the request stream for + the transaction. + """ + + return self.trans.rfile + + def get_request_method(self): + + """ + A framework-specific method which gets the request method. + """ + + return self.trans.command + + def get_headers(self): + + """ + A framework-specific method which returns the request headers. + NOTE: Experimental, since framework support varies somewhat. + """ + + return self.trans.headers + + def get_content_type(self): + + """ + A framework-specific method which gets the content type specified on the + request, along with the charset employed. + """ + + return self.parse_content_type(self.trans.headers.get("Content-type") or + self.trans.headers.get("Content-Type")) + + def get_content_charsets(self): + + """ + Returns the character set preferences. + """ + + return self.parse_content_preferences(self.trans.headers["Accept-Charset"]) + + def get_content_languages(self): + + """ + A framework-specific method which extracts language information from + the transaction. + """ + + return self.parse_content_preferences(self.trans.headers["Accept-Language"]) + + def get_path(self): + + """ + A framework-specific method which gets the entire path from the request. + """ + + return self.trans.path + + def get_path_info(self): + + """ + A framework-specific method which gets the "path info" (the part of the + URL after the resource name handling the current request) from the + request. + """ + + # NOTE: No attempt is made to deduce the "path info". + + return self.trans.path + + # Higher level request-related methods. + + def get_fields(self): + + """ + A framework-specific method which extracts the form fields from the + transaction. + """ + + return FieldStorage(self.trans.rfile, keep_blank_values=1) + + def get_agent_information(self): + + """ + A framework-specific method which extracts agent information from + the transaction. + """ + + return None + + # Response-related methods. + + def get_response_stream(self): + + """ + A framework-specific method which returns the response stream for + the transaction. + """ + + # Return a stream which is later emptied into the real stream. + + return self.content + + def set_content_type(self, content_type): + + """ + A framework-specific method which sets the 'content_type' for the + response. + """ + + # The content type has to be written as a header, before actual content, + # but after the response line. This means that some kind of buffering is + # required. Hence, we don't write the header out immediately. + + self.content_type = content_type + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r 9d5566eb4ad0 -r 980473b735d0 WebStack/Generic.py --- a/WebStack/Generic.py Sun Feb 01 23:17:11 2004 +0000 +++ b/WebStack/Generic.py Thu Feb 05 00:10:59 2004 +0000 @@ -30,6 +30,15 @@ overridden. """ + def commit(self): + + """ + A special method, synchronising the transaction with framework-specific + objects. + """ + + pass + # Utility methods. def parse_content_type(self, content_type_field):