blob: 4e0076c2cfdedf800d6abad176cebd6c8d604365 [file] [log] [blame]
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001"""Manage HTTP Response Headers
2
3Much of this module is red-handedly pilfered from email.Message in the stdlib,
4so 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
9# existance of which force quoting of the parameter value.
10import 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
28
29
30
31
32
33
34
35
36
37
38
39
40class Headers:
41
42 """Manage a collection of HTTP response headers"""
43
44 def __init__(self,headers):
Guido van Rossum13257902007-06-07 23:15:56 +000045 if not isinstance(headers, list):
Thomas Wouters0e3f5912006-08-11 14:57:12 +000046 raise TypeError("Headers must be a list of name/value tuples")
Antoine Pitrou38a66ad2009-01-03 18:41:49 +000047 self._headers = []
48 for k, v in headers:
49 k = self._convert_string_type(k)
50 v = self._convert_string_type(v)
51 self._headers.append((k, v))
52
53 def _convert_string_type(self, value):
54 """Convert/check value type."""
55 if isinstance(value, str):
56 return value
57 assert isinstance(value, bytes), ("Header names/values must be"
58 " a string or bytes object (not {0})".format(value))
59 return str(value, "iso-8859-1")
Thomas Wouters0e3f5912006-08-11 14:57:12 +000060
61 def __len__(self):
62 """Return the total number of headers, including duplicates."""
63 return len(self._headers)
64
65 def __setitem__(self, name, val):
66 """Set the value of a header."""
67 del self[name]
Antoine Pitrou38a66ad2009-01-03 18:41:49 +000068 self._headers.append(
69 (self._convert_string_type(name), self._convert_string_type(val)))
Thomas Wouters0e3f5912006-08-11 14:57:12 +000070
71 def __delitem__(self,name):
72 """Delete all occurrences of a header, if present.
73
74 Does *not* raise an exception if the header is missing.
75 """
Antoine Pitroua9ecbda2009-01-03 20:28:05 +000076 name = self._convert_string_type(name.lower())
Guido van Rossumb053cd82006-08-24 03:53:23 +000077 self._headers[:] = [kv for kv in self._headers if kv[0].lower() != name]
Thomas Wouters0e3f5912006-08-11 14:57:12 +000078
79 def __getitem__(self,name):
80 """Get the first header value for 'name'
81
82 Return None if the header is missing instead of raising an exception.
83
84 Note that if the header appeared multiple times, the first exactly which
85 occurrance gets returned is undefined. Use getall() to get all
86 the values matching a header field name.
87 """
88 return self.get(name)
89
90
91
92
93
Guido van Rossume2b70bc2006-08-18 22:13:04 +000094 def __contains__(self, name):
Thomas Wouters0e3f5912006-08-11 14:57:12 +000095 """Return true if the message contains the header."""
96 return self.get(name) is not None
97
Thomas Wouters0e3f5912006-08-11 14:57:12 +000098
99 def get_all(self, name):
100 """Return a list of all the values for the named field.
101
102 These will be sorted in the order they appeared in the original header
103 list or were added to this instance, and may contain duplicates. Any
104 fields deleted and re-inserted are always appended to the header list.
105 If no fields exist with the given name, returns an empty list.
106 """
Antoine Pitroua9ecbda2009-01-03 20:28:05 +0000107 name = self._convert_string_type(name.lower())
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000108 return [kv[1] for kv in self._headers if kv[0].lower()==name]
109
110
111 def get(self,name,default=None):
112 """Get the first header value for 'name', or return 'default'"""
Antoine Pitroua9ecbda2009-01-03 20:28:05 +0000113 name = self._convert_string_type(name.lower())
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000114 for k,v in self._headers:
115 if k.lower()==name:
116 return v
117 return default
118
119
120 def keys(self):
121 """Return a list of all the header field names.
122
123 These will be sorted in the order they appeared in the original header
124 list, or were added to this instance, and may contain duplicates.
125 Any fields deleted and re-inserted are always appended to the header
126 list.
127 """
128 return [k for k, v in self._headers]
129
130
131
132
133 def values(self):
134 """Return a list of all header values.
135
136 These will be sorted in the order they appeared in the original header
137 list, or were added to this instance, and may contain duplicates.
138 Any fields deleted and re-inserted are always appended to the header
139 list.
140 """
141 return [v for k, v in self._headers]
142
143 def items(self):
144 """Get all the header fields and values.
145
146 These will be sorted in the order they were in the original header
147 list, or were added to this instance, and may contain duplicates.
148 Any fields deleted and re-inserted are always appended to the header
149 list.
150 """
151 return self._headers[:]
152
153 def __repr__(self):
Brett Cannon0b70cca2006-08-25 02:59:59 +0000154 return "Headers(%r)" % self._headers
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000155
156 def __str__(self):
157 """str() returns the formatted headers, complete with end line,
158 suitable for direct HTTP transmission."""
159 return '\r\n'.join(["%s: %s" % kv for kv in self._headers]+['',''])
160
161 def setdefault(self,name,value):
162 """Return first matching header value for 'name', or 'value'
163
164 If there is no header named 'name', add a new header with name 'name'
165 and value 'value'."""
166 result = self.get(name)
167 if result is None:
Antoine Pitrou38a66ad2009-01-03 18:41:49 +0000168 self._headers.append((self._convert_string_type(name),
169 self._convert_string_type(value)))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000170 return value
171 else:
172 return result
173
174
175 def add_header(self, _name, _value, **_params):
176 """Extended header setting.
177
178 _name is the header field to add. keyword arguments can be used to set
179 additional parameters for the header field, with underscores converted
180 to dashes. Normally the parameter will be added as key="value" unless
181 value is None, in which case only the key will be added.
182
183 Example:
184
185 h.add_header('content-disposition', 'attachment', filename='bud.gif')
186
187 Note that unlike the corresponding 'email.Message' method, this does
188 *not* handle '(charset, language, value)' tuples: all values must be
189 strings or None.
190 """
191 parts = []
192 if _value is not None:
Antoine Pitrou38a66ad2009-01-03 18:41:49 +0000193 _value = self._convert_string_type(_value)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000194 parts.append(_value)
195 for k, v in _params.items():
Antoine Pitrou38a66ad2009-01-03 18:41:49 +0000196 k = self._convert_string_type(k)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000197 if v is None:
198 parts.append(k.replace('_', '-'))
199 else:
Antoine Pitrou38a66ad2009-01-03 18:41:49 +0000200 v = self._convert_string_type(v)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000201 parts.append(_formatparam(k.replace('_', '-'), v))
Antoine Pitrou38a66ad2009-01-03 18:41:49 +0000202 self._headers.append((self._convert_string_type(_name), "; ".join(parts)))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218#