blob: fab851c5a44430d6cecdade6cd6438a1b471808d [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:
Thomas Wouters0e3f5912006-08-11 14:57:12 +000029 """Manage a collection of HTTP response headers"""
30
Berker Peksag3e887222014-07-02 08:37:22 +030031 def __init__(self, headers=None):
32 headers = headers if headers is not None else []
Phillip J. Ebye1594222010-11-02 22:28:59 +000033 if type(headers) is not list:
Thomas Wouters0e3f5912006-08-11 14:57:12 +000034 raise TypeError("Headers must be a list of name/value tuples")
Phillip J. Ebye1594222010-11-02 22:28:59 +000035 self._headers = headers
36 if __debug__:
37 for k, v in headers:
38 self._convert_string_type(k)
39 self._convert_string_type(v)
Antoine Pitrou38a66ad2009-01-03 18:41:49 +000040
41 def _convert_string_type(self, value):
42 """Convert/check value type."""
Phillip J. Ebye1594222010-11-02 22:28:59 +000043 if type(value) is str:
Antoine Pitrou38a66ad2009-01-03 18:41:49 +000044 return value
Phillip J. Ebye1594222010-11-02 22:28:59 +000045 raise AssertionError("Header names/values must be"
46 " of type str (got {0})".format(repr(value)))
Thomas Wouters0e3f5912006-08-11 14:57:12 +000047
48 def __len__(self):
49 """Return the total number of headers, including duplicates."""
50 return len(self._headers)
51
52 def __setitem__(self, name, val):
53 """Set the value of a header."""
54 del self[name]
Antoine Pitrou38a66ad2009-01-03 18:41:49 +000055 self._headers.append(
56 (self._convert_string_type(name), self._convert_string_type(val)))
Thomas Wouters0e3f5912006-08-11 14:57:12 +000057
58 def __delitem__(self,name):
59 """Delete all occurrences of a header, if present.
60
61 Does *not* raise an exception if the header is missing.
62 """
Antoine Pitroua9ecbda2009-01-03 20:28:05 +000063 name = self._convert_string_type(name.lower())
Guido van Rossumb053cd82006-08-24 03:53:23 +000064 self._headers[:] = [kv for kv in self._headers if kv[0].lower() != name]
Thomas Wouters0e3f5912006-08-11 14:57:12 +000065
66 def __getitem__(self,name):
67 """Get the first header value for 'name'
68
69 Return None if the header is missing instead of raising an exception.
70
71 Note that if the header appeared multiple times, the first exactly which
Martin Panter46f50722016-05-26 05:35:26 +000072 occurrence gets returned is undefined. Use getall() to get all
Thomas Wouters0e3f5912006-08-11 14:57:12 +000073 the values matching a header field name.
74 """
75 return self.get(name)
76
Guido van Rossume2b70bc2006-08-18 22:13:04 +000077 def __contains__(self, name):
Thomas Wouters0e3f5912006-08-11 14:57:12 +000078 """Return true if the message contains the header."""
79 return self.get(name) is not None
80
Thomas Wouters0e3f5912006-08-11 14:57:12 +000081
82 def get_all(self, name):
83 """Return a list of all the values for the named field.
84
85 These will be sorted in the order they appeared in the original header
86 list or were added to this instance, and may contain duplicates. Any
87 fields deleted and re-inserted are always appended to the header list.
88 If no fields exist with the given name, returns an empty list.
89 """
Antoine Pitroua9ecbda2009-01-03 20:28:05 +000090 name = self._convert_string_type(name.lower())
Thomas Wouters0e3f5912006-08-11 14:57:12 +000091 return [kv[1] for kv in self._headers if kv[0].lower()==name]
92
93
94 def get(self,name,default=None):
95 """Get the first header value for 'name', or return 'default'"""
Antoine Pitroua9ecbda2009-01-03 20:28:05 +000096 name = self._convert_string_type(name.lower())
Thomas Wouters0e3f5912006-08-11 14:57:12 +000097 for k,v in self._headers:
98 if k.lower()==name:
99 return v
100 return default
101
102
103 def keys(self):
104 """Return a list of all the header field names.
105
106 These will be sorted in the order they appeared in the original header
107 list, or were added to this instance, and may contain duplicates.
108 Any fields deleted and re-inserted are always appended to the header
109 list.
110 """
111 return [k for k, v in self._headers]
112
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000113 def values(self):
114 """Return a list of all header values.
115
116 These will be sorted in the order they appeared in the original header
117 list, or were added to this instance, and may contain duplicates.
118 Any fields deleted and re-inserted are always appended to the header
119 list.
120 """
121 return [v for k, v in self._headers]
122
123 def items(self):
124 """Get all the header fields and values.
125
126 These will be sorted in the order they were in the original header
127 list, or were added to this instance, and may contain duplicates.
128 Any fields deleted and re-inserted are always appended to the header
129 list.
130 """
131 return self._headers[:]
132
133 def __repr__(self):
Serhiy Storchaka465e60e2014-07-25 23:36:00 +0300134 return "%s(%r)" % (self.__class__.__name__, self._headers)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000135
136 def __str__(self):
137 """str() returns the formatted headers, complete with end line,
138 suitable for direct HTTP transmission."""
139 return '\r\n'.join(["%s: %s" % kv for kv in self._headers]+['',''])
140
Phillip J. Ebye1594222010-11-02 22:28:59 +0000141 def __bytes__(self):
142 return str(self).encode('iso-8859-1')
143
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000144 def setdefault(self,name,value):
145 """Return first matching header value for 'name', or 'value'
146
147 If there is no header named 'name', add a new header with name 'name'
148 and value 'value'."""
149 result = self.get(name)
150 if result is None:
Antoine Pitrou38a66ad2009-01-03 18:41:49 +0000151 self._headers.append((self._convert_string_type(name),
152 self._convert_string_type(value)))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000153 return value
154 else:
155 return result
156
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000157 def add_header(self, _name, _value, **_params):
158 """Extended header setting.
159
160 _name is the header field to add. keyword arguments can be used to set
161 additional parameters for the header field, with underscores converted
162 to dashes. Normally the parameter will be added as key="value" unless
163 value is None, in which case only the key will be added.
164
165 Example:
166
167 h.add_header('content-disposition', 'attachment', filename='bud.gif')
168
Amaury Forgeot d'Arc1c25de62009-07-12 16:43:19 +0000169 Note that unlike the corresponding 'email.message' method, this does
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000170 *not* handle '(charset, language, value)' tuples: all values must be
171 strings or None.
172 """
173 parts = []
174 if _value is not None:
Antoine Pitrou38a66ad2009-01-03 18:41:49 +0000175 _value = self._convert_string_type(_value)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000176 parts.append(_value)
177 for k, v in _params.items():
Antoine Pitrou38a66ad2009-01-03 18:41:49 +0000178 k = self._convert_string_type(k)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000179 if v is None:
180 parts.append(k.replace('_', '-'))
181 else:
Antoine Pitrou38a66ad2009-01-03 18:41:49 +0000182 v = self._convert_string_type(v)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000183 parts.append(_formatparam(k.replace('_', '-'), v))
Antoine Pitrou38a66ad2009-01-03 18:41:49 +0000184 self._headers.append((self._convert_string_type(_name), "; ".join(parts)))