blob: cc01f5f3293c68b770e67a3479344a096b84bf16 [file] [log] [blame]
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001"""Manage HTTP Response Headers
2
Amaury Forgeot d'Arc1c25de62009-07-12 16:43:19 +00003Much of this module is red-handedly pilfered from email.message in the stdlib,
Thomas Wouters0e3f5912006-08-11 14:57:12 +00004so portions are Copyright (C) 2001,2002 Python Software Foundation, and were
5written by Barry Warsaw.
6"""
7
Thomas Wouters0e3f5912006-08-11 14:57:12 +00008# Regular expression that matches `special' characters in parameters, the
Mark Dickinson934896d2009-02-21 20:59:32 +00009# existence of which force quoting of the parameter value.
Thomas Wouters0e3f5912006-08-11 14:57:12 +000010import re
11tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]')
12
13def _formatparam(param, value=None, quote=1):
14 """Convenience function to format and return a key=value pair.
15
16 This will quote the value if needed or if quote is true.
17 """
18 if value is not None and len(value) > 0:
19 if quote or tspecials.search(value):
20 value = value.replace('\\', '\\\\').replace('"', r'\"')
21 return '%s="%s"' % (param, value)
22 else:
23 return '%s=%s' % (param, value)
24 else:
25 return param
26
27
Thomas Wouters0e3f5912006-08-11 14:57:12 +000028class Headers:
29
30 """Manage a collection of HTTP response headers"""
31
32 def __init__(self,headers):
Guido van Rossum13257902007-06-07 23:15:56 +000033 if not isinstance(headers, list):
Thomas Wouters0e3f5912006-08-11 14:57:12 +000034 raise TypeError("Headers must be a list of name/value tuples")
Antoine Pitrou38a66ad2009-01-03 18:41:49 +000035 self._headers = []
36 for k, v in headers:
37 k = self._convert_string_type(k)
38 v = self._convert_string_type(v)
39 self._headers.append((k, v))
40
41 def _convert_string_type(self, value):
42 """Convert/check value type."""
43 if isinstance(value, str):
44 return value
45 assert isinstance(value, bytes), ("Header names/values must be"
46 " a string or bytes object (not {0})".format(value))
47 return str(value, "iso-8859-1")
Thomas Wouters0e3f5912006-08-11 14:57:12 +000048
49 def __len__(self):
50 """Return the total number of headers, including duplicates."""
51 return len(self._headers)
52
53 def __setitem__(self, name, val):
54 """Set the value of a header."""
55 del self[name]
Antoine Pitrou38a66ad2009-01-03 18:41:49 +000056 self._headers.append(
57 (self._convert_string_type(name), self._convert_string_type(val)))
Thomas Wouters0e3f5912006-08-11 14:57:12 +000058
59 def __delitem__(self,name):
60 """Delete all occurrences of a header, if present.
61
62 Does *not* raise an exception if the header is missing.
63 """
Antoine Pitroua9ecbda2009-01-03 20:28:05 +000064 name = self._convert_string_type(name.lower())
Guido van Rossumb053cd82006-08-24 03:53:23 +000065 self._headers[:] = [kv for kv in self._headers if kv[0].lower() != name]
Thomas Wouters0e3f5912006-08-11 14:57:12 +000066
67 def __getitem__(self,name):
68 """Get the first header value for 'name'
69
70 Return None if the header is missing instead of raising an exception.
71
72 Note that if the header appeared multiple times, the first exactly which
73 occurrance gets returned is undefined. Use getall() to get all
74 the values matching a header field name.
75 """
76 return self.get(name)
77
Guido van Rossume2b70bc2006-08-18 22:13:04 +000078 def __contains__(self, name):
Thomas Wouters0e3f5912006-08-11 14:57:12 +000079 """Return true if the message contains the header."""
80 return self.get(name) is not None
81
Thomas Wouters0e3f5912006-08-11 14:57:12 +000082
83 def get_all(self, name):
84 """Return a list of all the values for the named field.
85
86 These will be sorted in the order they appeared in the original header
87 list or were added to this instance, and may contain duplicates. Any
88 fields deleted and re-inserted are always appended to the header list.
89 If no fields exist with the given name, returns an empty list.
90 """
Antoine Pitroua9ecbda2009-01-03 20:28:05 +000091 name = self._convert_string_type(name.lower())
Thomas Wouters0e3f5912006-08-11 14:57:12 +000092 return [kv[1] for kv in self._headers if kv[0].lower()==name]
93
94
95 def get(self,name,default=None):
96 """Get the first header value for 'name', or return 'default'"""
Antoine Pitroua9ecbda2009-01-03 20:28:05 +000097 name = self._convert_string_type(name.lower())
Thomas Wouters0e3f5912006-08-11 14:57:12 +000098 for k,v in self._headers:
99 if k.lower()==name:
100 return v
101 return default
102
103
104 def keys(self):
105 """Return a list of all the header field names.
106
107 These will be sorted in the order they appeared in the original header
108 list, or were added to this instance, and may contain duplicates.
109 Any fields deleted and re-inserted are always appended to the header
110 list.
111 """
112 return [k for k, v in self._headers]
113
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000114 def values(self):
115 """Return a list of all header values.
116
117 These will be sorted in the order they appeared in the original header
118 list, or were added to this instance, and may contain duplicates.
119 Any fields deleted and re-inserted are always appended to the header
120 list.
121 """
122 return [v for k, v in self._headers]
123
124 def items(self):
125 """Get all the header fields and values.
126
127 These will be sorted in the order they were in the original header
128 list, or were added to this instance, and may contain duplicates.
129 Any fields deleted and re-inserted are always appended to the header
130 list.
131 """
132 return self._headers[:]
133
134 def __repr__(self):
Brett Cannon0b70cca2006-08-25 02:59:59 +0000135 return "Headers(%r)" % self._headers
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000136
137 def __str__(self):
138 """str() returns the formatted headers, complete with end line,
139 suitable for direct HTTP transmission."""
140 return '\r\n'.join(["%s: %s" % kv for kv in self._headers]+['',''])
141
142 def setdefault(self,name,value):
143 """Return first matching header value for 'name', or 'value'
144
145 If there is no header named 'name', add a new header with name 'name'
146 and value 'value'."""
147 result = self.get(name)
148 if result is None:
Antoine Pitrou38a66ad2009-01-03 18:41:49 +0000149 self._headers.append((self._convert_string_type(name),
150 self._convert_string_type(value)))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000151 return value
152 else:
153 return result
154
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000155 def add_header(self, _name, _value, **_params):
156 """Extended header setting.
157
158 _name is the header field to add. keyword arguments can be used to set
159 additional parameters for the header field, with underscores converted
160 to dashes. Normally the parameter will be added as key="value" unless
161 value is None, in which case only the key will be added.
162
163 Example:
164
165 h.add_header('content-disposition', 'attachment', filename='bud.gif')
166
Amaury Forgeot d'Arc1c25de62009-07-12 16:43:19 +0000167 Note that unlike the corresponding 'email.message' method, this does
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000168 *not* handle '(charset, language, value)' tuples: all values must be
169 strings or None.
170 """
171 parts = []
172 if _value is not None:
Antoine Pitrou38a66ad2009-01-03 18:41:49 +0000173 _value = self._convert_string_type(_value)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000174 parts.append(_value)
175 for k, v in _params.items():
Antoine Pitrou38a66ad2009-01-03 18:41:49 +0000176 k = self._convert_string_type(k)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000177 if v is None:
178 parts.append(k.replace('_', '-'))
179 else:
Antoine Pitrou38a66ad2009-01-03 18:41:49 +0000180 v = self._convert_string_type(v)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000181 parts.append(_formatparam(k.replace('_', '-'), v))
Antoine Pitrou38a66ad2009-01-03 18:41:49 +0000182 self._headers.append((self._convert_string_type(_name), "; ".join(parts)))