1 #!/usr/bin/env python 2 3 """ 4 BaseHTTPRequestHandler classes. 5 """ 6 7 import Generic 8 from cgi import FieldStorage 9 from StringIO import StringIO 10 11 class Transaction(Generic.Transaction): 12 13 """ 14 BaseHTTPRequestHandler transaction interface. 15 """ 16 17 def __init__(self, trans): 18 19 """ 20 Initialise the transaction using the BaseHTTPRequestHandler instance 21 'trans'. 22 """ 23 24 self.trans = trans 25 26 # Other attributes of interest in instances of this class. 27 28 self.content_type = None 29 self.response_code = 100 30 self.content = StringIO() 31 32 def commit(self): 33 34 """ 35 A special method, synchronising the transaction with framework-specific 36 objects. 37 """ 38 39 self.trans.send_response(self.response_code) 40 self.trans.send_header("Content-Type", self.format_content_type(self.content_type)) 41 self.trans.end_headers() 42 self.content.seek(0) 43 self.trans.wfile.write(self.content.read()) 44 45 # Request-related methods. 46 47 def get_request_stream(self): 48 49 """ 50 A framework-specific method which returns the request stream for 51 the transaction. 52 """ 53 54 return self.trans.rfile 55 56 def get_request_method(self): 57 58 """ 59 A framework-specific method which gets the request method. 60 """ 61 62 return self.trans.command 63 64 def get_headers(self): 65 66 """ 67 A framework-specific method which returns the request headers. 68 NOTE: Experimental, since framework support varies somewhat. 69 """ 70 71 return self.trans.headers 72 73 def get_content_type(self): 74 75 """ 76 A framework-specific method which gets the content type specified on the 77 request, along with the charset employed. 78 """ 79 80 return self.parse_content_type(self.trans.headers.get("Content-type") or 81 self.trans.headers.get("Content-Type")) 82 83 def get_content_charsets(self): 84 85 """ 86 Returns the character set preferences. 87 """ 88 89 return self.parse_content_preferences(self.trans.headers["Accept-Charset"]) 90 91 def get_content_languages(self): 92 93 """ 94 A framework-specific method which extracts language information from 95 the transaction. 96 """ 97 98 return self.parse_content_preferences(self.trans.headers["Accept-Language"]) 99 100 def get_path(self): 101 102 """ 103 A framework-specific method which gets the entire path from the request. 104 """ 105 106 return self.trans.path 107 108 def get_path_info(self): 109 110 """ 111 A framework-specific method which gets the "path info" (the part of the 112 URL after the resource name handling the current request) from the 113 request. 114 """ 115 116 # NOTE: No attempt is made to deduce the "path info". 117 118 return self.trans.path 119 120 # Higher level request-related methods. 121 122 def get_fields(self): 123 124 """ 125 A framework-specific method which extracts the form fields from the 126 transaction. 127 """ 128 129 return FieldStorage(self.trans.rfile, keep_blank_values=1) 130 131 def get_agent_information(self): 132 133 """ 134 A framework-specific method which extracts agent information from 135 the transaction. 136 """ 137 138 return None 139 140 # Response-related methods. 141 142 def get_response_stream(self): 143 144 """ 145 A framework-specific method which returns the response stream for 146 the transaction. 147 """ 148 149 # Return a stream which is later emptied into the real stream. 150 151 return self.content 152 153 def get_response_code(self): 154 155 """ 156 Get the response code associated with the transaction. If no response 157 code is defined, None is returned. 158 """ 159 160 return self.response_code 161 162 def set_response_code(self, response_code): 163 164 """ 165 Set the 'response_code' using a numeric constant defined in the HTTP 166 specification. 167 """ 168 169 self.response_code = response_code 170 171 def set_content_type(self, content_type): 172 173 """ 174 A framework-specific method which sets the 'content_type' for the 175 response. 176 """ 177 178 # The content type has to be written as a header, before actual content, 179 # but after the response line. This means that some kind of buffering is 180 # required. Hence, we don't write the header out immediately. 181 182 self.content_type = content_type 183 184 # vim: tabstop=4 expandtab shiftwidth=4