| 188 | | def encode_TEXT(value): |
|---|
| 189 | | """Encode RFC-2047 TEXT (e.g. u"\u8200" -> "=?utf-8?b?6IiA?="). |
|---|
| 190 | | |
|---|
| 191 | | Note that HTTP/1.0 says, "Words of *TEXT may contain octets from |
|---|
| 192 | | character sets other than US-ASCII." and "Recipients of header |
|---|
| 193 | | field TEXT containing octets outside the US-ASCII character |
|---|
| 194 | | set may assume that they represent ISO-8859-1 characters." |
|---|
| 195 | | So don't use this function for encoding HTTP/1.0 values. |
|---|
| 196 | | """ |
|---|
| 197 | | |
|---|
| 198 | | try: |
|---|
| 199 | | value = value.encode("iso-8859-1") |
|---|
| 200 | | except UnicodeEncodeError: |
|---|
| 201 | | value = value.encode("utf-8") |
|---|
| 202 | | value = Header(value, 'utf-8').encode() |
|---|
| 203 | | return value |
|---|
| 204 | | |
|---|
| 388 | | general_fields = ["Cache-Control", "Connection", "Date", "Pragma", |
|---|
| 389 | | "Trailer", "Transfer-Encoding", "Upgrade", "Via", |
|---|
| 390 | | "Warning"] |
|---|
| 391 | | response_fields = ["Accept-Ranges", "Age", "ETag", "Location", |
|---|
| 392 | | "Proxy-Authenticate", "Retry-After", "Server", |
|---|
| 393 | | "Vary", "WWW-Authenticate"] |
|---|
| 394 | | entity_fields = ["Allow", "Content-Encoding", "Content-Language", |
|---|
| 395 | | "Content-Length", "Content-Location", "Content-MD5", |
|---|
| 396 | | "Content-Range", "Content-Type", "Expires", |
|---|
| 397 | | "Last-Modified"] |
|---|
| 398 | | |
|---|
| 399 | | order_map = {} |
|---|
| 400 | | for _ in general_fields: |
|---|
| 401 | | order_map[_] = 0 |
|---|
| 402 | | for _ in response_fields: |
|---|
| 403 | | order_map[_] = 1 |
|---|
| 404 | | for _ in entity_fields: |
|---|
| 405 | | order_map[_] = 2 |
|---|
| 406 | | |
|---|
| 407 | | def sorted_list(self): |
|---|
| 408 | | """Transform self into a sorted list of (name, value) tuples. |
|---|
| 409 | | |
|---|
| 410 | | From http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 |
|---|
| 411 | | '... it is "good practice" to send general-header fields first, |
|---|
| 412 | | followed by request-header or response-header fields, and ending |
|---|
| 413 | | with the entity-header fields.' |
|---|
| 414 | | """ |
|---|
| 415 | | |
|---|
| | 371 | def output(self, version=(1, 1)): |
|---|
| | 372 | """Transform self into a list of (name, value) tuples.""" |
|---|
| 417 | | for key, valueList in self.iteritems(): |
|---|
| 418 | | order = self.order_map.get(key, 3) |
|---|
| 419 | | if not isinstance(valueList, list): |
|---|
| 420 | | valueList = [valueList] |
|---|
| 421 | | for value in valueList: |
|---|
| 422 | | header_list.append((order, (key, unicode(value)))) |
|---|
| 423 | | header_list.sort() |
|---|
| 424 | | return [item[1] for item in header_list] |
|---|
| | 374 | for key, value in self.iteritems(): |
|---|
| | 375 | if not isinstance(value, list): |
|---|
| | 376 | value = [value] |
|---|
| | 377 | for v in value: |
|---|
| | 378 | if isinstance(v, unicode): |
|---|
| | 379 | # Encode RFC-2047 TEXT (e.g. u"\u8200" -> "=?utf-8?b?6IiA?="). |
|---|
| | 380 | try: |
|---|
| | 381 | v = v.encode("iso-8859-1") |
|---|
| | 382 | except UnicodeEncodeError: |
|---|
| | 383 | # HTTP/1.0 says, "Words of *TEXT may contain octets |
|---|
| | 384 | # from character sets other than US-ASCII." and |
|---|
| | 385 | # "Recipients of header field TEXT containing octets |
|---|
| | 386 | # outside the US-ASCII character set may assume that |
|---|
| | 387 | # they represent ISO-8859-1 characters." |
|---|
| | 388 | if version >= (1, 1): |
|---|
| | 389 | v = v.encode("utf-8") |
|---|
| | 390 | v = Header(v, 'utf-8').encode() |
|---|
| | 391 | else: |
|---|
| | 392 | raise |
|---|
| | 393 | else: |
|---|
| | 394 | # This coercion should not take any time at all |
|---|
| | 395 | # if value is already of type "str". |
|---|
| | 396 | v = str(v) |
|---|
| | 397 | header_list.append((key, v)) |
|---|
| | 398 | return header_list |
|---|