1 #!/usr/bin/env python 2 3 """ 4 mod_python classes. 5 """ 6 7 import Generic 8 from mod_python.util import parse_qs, FieldStorage 9 from mod_python import apache 10 try: 11 from mod_python import Cookie 12 except ImportError: 13 # NOTE: Should provide an alternative implementation. 14 Cookie = None 15 16 class Transaction(Generic.Transaction): 17 18 """ 19 mod_python transaction interface. 20 """ 21 22 def __init__(self, trans): 23 24 "Initialise the transaction using the mod_python transaction 'trans'." 25 26 self.trans = trans 27 self.response_code = apache.OK 28 29 # Request-related methods. 30 31 def get_request_stream(self): 32 33 """ 34 A framework-specific method which returns the request stream for 35 the transaction. 36 """ 37 38 return self.trans 39 40 def get_request_method(self): 41 42 """ 43 A framework-specific method which gets the request method. 44 """ 45 46 return self.trans.method 47 48 def get_headers(self): 49 50 """ 51 A framework-specific method which returns all request headers. 52 NOTE: If duplicate header names are permitted, then this interface will 53 NOTE: need to change. 54 """ 55 56 return self.trans.headers_in 57 58 def get_header_values(self, key): 59 60 """ 61 A framework-specific method which returns a list of all request header 62 values associated with the given 'key'. Note that according to RFC 2616, 63 'key' is treated as a case-insensitive string. 64 """ 65 66 return self.convert_to_list(self.trans.headers_in.get(key)) 67 68 def get_content_type(self): 69 70 """ 71 A framework-specific method which gets the content type specified on the 72 request, along with the charset employed. 73 """ 74 75 return self.parse_content_type(self.trans.content_type) 76 77 def get_content_charsets(self): 78 79 """ 80 Returns the character set preferences. 81 """ 82 83 return self.parse_content_preferences(self.trans.headers_in["Accept-Charset"]) 84 85 def get_content_languages(self): 86 87 """ 88 A framework-specific method which extracts language information from 89 the transaction. 90 """ 91 92 return self.parse_content_preferences(self.trans.headers_in["Accept-Language"]) 93 94 def get_path(self): 95 96 """ 97 A framework-specific method which gets the entire path from the request. 98 """ 99 100 return self.trans.uri 101 102 def get_path_info(self): 103 104 """ 105 A framework-specific method which gets the "path info" (the part of the 106 URL after the resource name handling the current request) from the 107 request. 108 """ 109 110 return self.trans.path_info 111 112 def get_query_string(self): 113 114 """ 115 A framework-specific method which gets the query string from the path in 116 the request. 117 """ 118 119 return self.trans.args or "" 120 121 # Higher level request-related methods. 122 123 def get_fields_from_path(self): 124 125 """ 126 A framework-specific method which extracts the form fields from the 127 path specified in the transaction. The underlying framework may refuse 128 to supply fields from the path if handling a POST transaction. 129 130 Returns a dictionary mapping field names to lists of values (even if a 131 single value is associated with any given field name). 132 """ 133 134 return parse_qs(self.get_query_string(), 1) # keep_blank_values=1 135 136 def get_fields_from_body(self): 137 138 """ 139 A framework-specific method which extracts the form fields from the 140 message body in the transaction. 141 142 Returns a dictionary mapping field names to lists of values (even if a 143 single value is associated with any given field name). 144 145 The mod_python.util.FieldStorage class may augment the fields from the 146 body with fields found in the path. 147 """ 148 149 storage = FieldStorage(self.trans, keep_blank_values=1) 150 151 # Traverse the storage, finding each field value. 152 153 fields = {} 154 for field in storage.list: 155 if not fields.has_key(field.name): 156 fields[field.name] = [] 157 fields[field.name].append(field.value) 158 return fields 159 160 def get_user(self): 161 162 """ 163 A framework-specific method which extracts user information from the 164 transaction. 165 """ 166 167 return self.trans.user 168 169 def get_cookies(self): 170 171 """ 172 A framework-specific method which obtains cookie information from the 173 request. 174 175 Returns a dictionary mapping cookie names to cookie objects. 176 177 NOTE: No additional information is passed to the underlying API despite 178 NOTE: support for enhanced cookies in mod_python. 179 """ 180 181 return Cookie.get_cookies(self.trans) 182 183 # Response-related methods. 184 185 def get_response_stream(self): 186 187 """ 188 A framework-specific method which returns the response stream for 189 the transaction. 190 """ 191 192 return self.trans 193 194 def get_response_code(self): 195 196 """ 197 Get the response code associated with the transaction. If no response 198 code is defined, None is returned. 199 """ 200 201 return self.response_code 202 203 def set_response_code(self, response_code): 204 205 """ 206 Set the 'response_code' using a numeric constant defined in the HTTP 207 specification. 208 """ 209 210 self.response_code = response_code 211 212 def set_header_value(self, header, value): 213 214 """ 215 Set the HTTP 'header' with the given 'value'. 216 """ 217 218 self.trans.headers_out[self.format_header_value(header)] = self.format_header_value(value) 219 220 def set_content_type(self, content_type): 221 222 """ 223 A framework-specific method which sets the 'content_type' for the 224 response. 225 """ 226 227 self.trans.content_type = self.format_content_type(content_type) 228 229 def set_cookie(self, cookie): 230 231 """ 232 A framework-specific method which stores the given 'cookie' object in 233 the response. 234 """ 235 236 if Cookie: 237 Cookie.add_cookie(self.trans, cookie) 238 else: 239 # NOTE: Should raise an exception or provide an implementation. 240 pass 241 242 def set_cookie_value(self, name, value, path=None, expires=None): 243 244 """ 245 A framework-specific method which stores a cookie with the given 'name' 246 and 'value' in the response. 247 248 The optional 'path' is a string which specifies the scope of the cookie, 249 and the optional 'expires' parameter is a value compatible with the 250 time.time function, and indicates the expiry date/time of the cookie. 251 """ 252 253 if Cookie: 254 cookie = Cookie.Cookie(name, value) 255 if expires is not None: 256 cookie.expires = expires 257 if path is not None: 258 cookie.path = path 259 Cookie.add_cookie(self.trans, cookie) 260 else: 261 # NOTE: Should raise an exception or provide an implementation. 262 pass 263 264 def delete_cookie(self, cookie_name): 265 266 """ 267 A framework-specific method which adds to the response a request that 268 the cookie with the given 'cookie_name' be deleted/discarded by the 269 client. 270 """ 271 272 # Create a special cookie, given that we do not know whether the browser 273 # has been sent the cookie or not. 274 # NOTE: Magic discovered in Webware. 275 276 if Cookie: 277 cookie = Cookie.Cookie(cookie_name, "") 278 cookie.path = "/" 279 cookie.expires = 0 280 cookie.max_age = 0 281 Cookie.add_cookie(self.trans, cookie) 282 else: 283 # NOTE: Should raise an exception or provide an implementation. 284 pass 285 286 # vim: tabstop=4 expandtab shiftwidth=4