1 #!/usr/bin/env python 2 3 """ 4 Webware classes. 5 """ 6 7 import Generic 8 from cgi import parse_qs 9 import StringIO 10 11 class Transaction(Generic.Transaction): 12 13 """ 14 Webware transaction interface. 15 """ 16 17 def __init__(self, trans): 18 19 "Initialise the transaction using the Webware transaction 'trans'." 20 21 self.trans = trans 22 23 # Request-related methods. 24 25 def get_request_stream(self): 26 27 """ 28 A framework-specific method which returns the request stream for 29 the transaction. 30 """ 31 32 request = self.trans.request() 33 try: 34 stream = request.rawInput(rewind=1) 35 if stream is None: 36 return StringIO.StringIO("") 37 38 # NOTE: Dubious catch-all situation, but it is difficult to control 39 # NOTE: cases where Webware's internals themselves fail. 40 41 except: 42 return StringIO.StringIO("") 43 44 return stream 45 46 def get_request_method(self): 47 48 """ 49 A framework-specific method which gets the request method. 50 """ 51 52 return self.trans.request().method() 53 54 def get_headers(self): 55 56 """ 57 A framework-specific method which returns all request headers. 58 """ 59 60 # NOTE: Webware doesn't really provide access to headers in the request. 61 62 return {} 63 64 def get_header_values(self, key): 65 66 """ 67 A framework-specific method which returns a list of all request header 68 values associated with the given 'key'. Note that according to RFC 2616, 69 'key' is treated as a case-insensitive string. 70 """ 71 72 # NOTE: Webware doesn't really provide access to headers in the request. 73 74 return [] 75 76 def get_content_type(self): 77 78 """ 79 A framework-specific method which gets the content type specified on the 80 request, along with the charset employed. 81 """ 82 83 return self.parse_content_type(self.trans.request().contentType()) 84 85 def get_content_charsets(self): 86 87 """ 88 Returns the character set preferences. 89 NOTE: Requires enhancements to HTTPRequest. 90 """ 91 92 return self.trans.request().contentCharsets() 93 94 def get_content_languages(self): 95 96 """ 97 A framework-specific method which extracts language information from 98 the transaction. 99 NOTE: Requires enhancements to HTTPRequest. 100 """ 101 102 return self.trans.request().contentLanguages() 103 104 def get_path(self): 105 106 """ 107 A framework-specific method which gets the entire path from the request. 108 """ 109 110 return self.trans.request().uri() 111 112 def get_path_info(self): 113 114 """ 115 A framework-specific method which gets the "path info" (the part of the 116 URL after the resource name handling the current request) from the 117 request. 118 """ 119 120 # NOTE: Webware does not seem to prefix the "path info" in a way 121 # NOTE: consistent with the other frameworks. 122 123 return "/" + self.trans.request().pathInfo() 124 125 def get_query_string(self): 126 127 """ 128 A framework-specific method which gets the query string from the path in 129 the request. 130 """ 131 132 return self.trans.request().queryString() 133 134 # Higher level request-related methods. 135 136 def get_fields_from_path(self): 137 138 """ 139 A framework-specific method which extracts the form fields from the 140 path specified in the transaction. The underlying framework may refuse 141 to supply fields from the path if handling a POST transaction. 142 143 Returns a dictionary mapping field names to lists of values (even if a 144 single value is associated with any given field name). 145 """ 146 147 return parse_qs(self.get_query_string(), keep_blank_values=1) 148 149 def get_fields_from_body(self): 150 151 """ 152 A framework-specific method which extracts the form fields from the 153 message body in the transaction. 154 155 Returns a dictionary mapping field names to lists of values (even if a 156 single value is associated with any given field name). 157 """ 158 159 # Fix the non-list results. 160 161 fields = {} 162 for field_name, field_value in self.trans.request().fields().items(): 163 if type(field_value) == type([]): 164 fields[field_name] = field_value 165 else: 166 fields[field_name] = [field_value] 167 return fields 168 169 def get_user(self): 170 171 """ 172 A framework-specific method which extracts user information from the 173 transaction. 174 """ 175 176 # NOTE: Webware relies entirely on a CGI-style environment where the 177 # NOTE: actual headers are not available. Therefore, the Web server must 178 # NOTE: itself be set up to provide user support. 179 180 try: 181 return self.trans.request().remoteUser() 182 except KeyError, exc: 183 return None 184 185 # Response-related methods. 186 187 def get_response_stream(self): 188 189 """ 190 A framework-specific method which returns the response stream for 191 the transaction. 192 """ 193 194 return self.trans.response() 195 196 def get_response_code(self): 197 198 """ 199 Get the response code associated with the transaction. If no response 200 code is defined, None is returned. 201 """ 202 203 # NOTE: Webware treats the response code as just another header. 204 205 status = self.trans.response().header("Status", None) 206 try: 207 if status is not None: 208 return int(status) 209 else: 210 return None 211 except ValueError: 212 return None 213 214 def set_response_code(self, response_code): 215 216 """ 217 Set the 'response_code' using a numeric constant defined in the HTTP 218 specification. 219 """ 220 221 self.trans.response().setStatus(response_code) 222 223 def set_header_value(self, header, value): 224 225 """ 226 Set the HTTP 'header' with the given 'value'. 227 """ 228 229 self.trans.response().setHeader(self.format_header_value(header), self.format_header_value(value)) 230 231 def set_content_type(self, content_type): 232 233 """ 234 A framework-specific method which sets the 'content_type' for the 235 response. 236 """ 237 238 return self.trans.response().setHeader("Content-Type", self.format_content_type(content_type)) 239 240 # vim: tabstop=4 expandtab shiftwidth=4