1 #!/usr/bin/env python 2 3 """ 4 Twisted classes. 5 """ 6 7 import Generic 8 from Helpers.Auth import UserInfo 9 from cgi import parse_qs 10 11 class Transaction(Generic.Transaction): 12 13 """ 14 Twisted transaction interface. 15 """ 16 17 def __init__(self, trans): 18 19 "Initialise the transaction using the Twisted 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 return self.trans.content 33 34 def get_request_method(self): 35 36 """ 37 A framework-specific method which gets the request method. 38 """ 39 40 return self.trans.method 41 42 def get_headers(self): 43 44 """ 45 A framework-specific method which returns all request headers. 46 """ 47 48 return self.trans.received_headers 49 50 def get_header_values(self, key): 51 52 """ 53 A framework-specific method which returns a list of all request header 54 values associated with the given 'key'. Note that according to RFC 2616, 55 'key' is treated as a case-insensitive string. 56 """ 57 58 # Twisted does not convert the header key to lower case (which is the 59 # stored representation). 60 61 return self.convert_to_list(self.trans.received_headers.get(key.lower())) 62 63 def get_content_type(self): 64 65 """ 66 A framework-specific method which gets the content type specified on the 67 request, along with the charset employed. 68 """ 69 70 return self.parse_content_type(self.trans.getHeader("Content-Type")) 71 72 def get_content_charsets(self): 73 74 """ 75 Returns the character set preferences. 76 """ 77 78 return self.parse_content_preferences(self.trans.getHeader("Accept-Language")) 79 80 def get_content_languages(self): 81 82 """ 83 A framework-specific method which extracts language information from 84 the transaction. 85 """ 86 87 return self.parse_content_preferences(self.trans.getHeader("Accept-Charset")) 88 89 def get_path(self): 90 91 """ 92 A framework-specific method which gets the entire path from the request. 93 """ 94 95 return self.trans.uri 96 97 def get_path_info(self): 98 99 """ 100 A framework-specific method which gets the "path info" (the part of the 101 URL after the resource name handling the current request) from the 102 request. 103 """ 104 105 return "/%s" % "/".join(self.trans.postpath) 106 107 def get_query_string(self): 108 109 """ 110 A framework-specific method which gets the query string from the path in 111 the request. 112 """ 113 114 t = self.get_path().split("?") 115 if len(t) == 1: 116 return "" 117 else: 118 119 # NOTE: Overlook erroneous usage of "?" characters in the path. 120 121 return "?".join(t[1:]) 122 123 # Higher level request-related methods. 124 125 def get_fields_from_path(self): 126 127 """ 128 A framework-specific method which extracts the form fields from the 129 path specified in the transaction. The underlying framework may refuse 130 to supply fields from the path if handling a POST transaction. 131 132 Returns a dictionary mapping field names to lists of values (even if a 133 single value is associated with any given field name). 134 """ 135 136 return parse_qs(self.get_query_string(), keep_blank_values=1) 137 138 def get_fields_from_body(self): 139 140 """ 141 A framework-specific method which extracts the form fields from the 142 message body in the transaction. 143 144 Returns a dictionary mapping field names to lists of values (even if a 145 single value is associated with any given field name). 146 """ 147 148 return self.trans.args 149 150 def get_user(self): 151 152 """ 153 A framework-specific method which extracts user information from the 154 transaction. 155 """ 156 157 # NOTE: Twisted makes headers lower case, for some reason. 158 159 auth_header = self.get_headers().get("authorization") 160 if auth_header: 161 return UserInfo(auth_header).username 162 else: 163 return None 164 165 # Response-related methods. 166 167 def get_response_stream(self): 168 169 """ 170 A framework-specific method which returns the response stream for 171 the transaction. 172 """ 173 174 return self.trans 175 176 def get_response_code(self): 177 178 """ 179 Get the response code associated with the transaction. If no response 180 code is defined, None is returned. 181 """ 182 183 # NOTE: Accessing the request attribute directly. 184 185 return self.trans.code 186 187 def set_response_code(self, response_code): 188 189 """ 190 Set the 'response_code' using a numeric constant defined in the HTTP 191 specification. 192 """ 193 194 self.trans.setResponseCode(response_code) 195 196 def set_header_value(self, header, value): 197 198 """ 199 Set the HTTP 'header' with the given 'value'. 200 """ 201 202 self.trans.setHeader(self.format_header_value(header), self.format_header_value(value)) 203 204 def set_content_type(self, content_type): 205 206 """ 207 A framework-specific method which sets the 'content_type' for the 208 response. 209 """ 210 211 self.trans.setHeader("Content-Type", self.format_content_type(content_type)) 212 213 # vim: tabstop=4 expandtab shiftwidth=4