Initial import to Tizen
[profile/ivi/python-twisted.git] / twisted / web / http_headers.py
1 # -*- test-case-name: twisted.web.test.test_http_headers
2 # Copyright (c) Twisted Matrix Laboratories.
3 # See LICENSE for details.
4
5 """
6 An API for storing HTTP header names and values.
7 """
8
9
10 from UserDict import DictMixin
11
12
13 def _dashCapitalize(name):
14     """
15     Return a string which is capitalized using '-' as a word separator.
16
17     @param name: The name of the header to capitalize.
18     @type name: str
19
20     @return: The given header capitalized using '-' as a word separator.
21     @rtype: str
22     """
23     return '-'.join([word.capitalize() for word in name.split('-')])
24
25
26
27 class _DictHeaders(DictMixin):
28     """
29     A C{dict}-like wrapper around L{Headers} to provide backwards compatibility
30     for L{Request.received_headers} and L{Request.headers} which used to be
31     plain C{dict} instances.
32
33     @type _headers: L{Headers}
34     @ivar _headers: The real header storage object.
35     """
36     def __init__(self, headers):
37         self._headers = headers
38
39
40     def __getitem__(self, key):
41         """
42         Return the last value for header of C{key}.
43         """
44         if self._headers.hasHeader(key):
45             return self._headers.getRawHeaders(key)[-1]
46         raise KeyError(key)
47
48
49     def __setitem__(self, key, value):
50         """
51         Set the given header.
52         """
53         self._headers.setRawHeaders(key, [value])
54
55
56     def __delitem__(self, key):
57         """
58         Delete the given header.
59         """
60         if self._headers.hasHeader(key):
61             self._headers.removeHeader(key)
62         else:
63             raise KeyError(key)
64
65
66     def keys(self):
67         """
68         Return a list of all header names.
69         """
70         return [k.lower() for k, v in self._headers.getAllRawHeaders()]
71
72
73     def copy(self):
74         """
75         Return a C{dict} mapping each header name to the last corresponding
76         header value.
77         """
78         return dict(self.items())
79
80
81     # Python 2.3 DictMixin.setdefault is defined so as not to have a default
82     # for the value parameter.  This is necessary to make this setdefault look
83     # like dict.setdefault on Python 2.3. -exarkun
84     def setdefault(self, name, value=None):
85         """
86         Retrieve the last value for the given header name.  If there are no
87         values present for that header, set the value to C{value} and return
88         that instead.  Note that C{None} is the default for C{value} for
89         backwards compatibility, but header values may only be of type C{str}.
90         """
91         return DictMixin.setdefault(self, name, value)
92
93
94     # The remaining methods are only for efficiency.  The same behavior
95     # should remain even if they are removed.  For details, see
96     # <http://docs.python.org/lib/module-UserDict.html>.
97     # -exarkun
98     def __contains__(self, name):
99         """
100         Return C{True} if the named header is present, C{False} otherwise.
101         """
102         return self._headers.getRawHeaders(name) is not None
103
104
105     def __iter__(self):
106         """
107         Return an iterator of the lowercase name of each header present.
108         """
109         for k, v in self._headers.getAllRawHeaders():
110             yield k.lower()
111
112
113     def iteritems(self):
114         """
115         Return an iterable of two-tuples of each lower-case header name and the
116         last value for that header.
117         """
118         for k, v in self._headers.getAllRawHeaders():
119             yield k.lower(), v[-1]
120
121
122
123 class Headers(object):
124     """
125     This class stores the HTTP headers as both a parsed representation
126     and the raw string representation. It converts between the two on
127     demand.
128
129     @cvar _caseMappings: A C{dict} that maps lowercase header names
130         to their canonicalized representation.
131
132     @ivar _rawHeaders: A C{dict} mapping header names as C{str} to C{lists} of
133         header values as C{str}.
134     """
135     _caseMappings = {
136         'content-md5': 'Content-MD5',
137         'dnt': 'DNT',
138         'etag': 'ETag',
139         'p3p': 'P3P',
140         'te': 'TE',
141         'www-authenticate': 'WWW-Authenticate',
142         'x-xss-protection': 'X-XSS-Protection'}
143
144     def __init__(self, rawHeaders=None):
145         self._rawHeaders = {}
146         if rawHeaders is not None:
147             for name, values in rawHeaders.iteritems():
148                 self.setRawHeaders(name, values[:])
149
150
151     def __repr__(self):
152         """
153         Return a string fully describing the headers set on this object.
154         """
155         return '%s(%r)' % (self.__class__.__name__, self._rawHeaders,)
156
157
158     def __cmp__(self, other):
159         """
160         Define L{Headers} instances as being equal to each other if they have
161         the same raw headers.
162         """
163         if isinstance(other, Headers):
164             return cmp(self._rawHeaders, other._rawHeaders)
165         return NotImplemented
166
167
168     def copy(self):
169         """
170         Return a copy of itself with the same headers set.
171         """
172         return self.__class__(self._rawHeaders)
173
174
175     def hasHeader(self, name):
176         """
177         Check for the existence of a given header.
178
179         @type name: C{str}
180         @param name: The name of the HTTP header to check for.
181
182         @rtype: C{bool}
183         @return: C{True} if the header exists, otherwise C{False}.
184         """
185         return name.lower() in self._rawHeaders
186
187
188     def removeHeader(self, name):
189         """
190         Remove the named header from this header object.
191
192         @type name: C{str}
193         @param name: The name of the HTTP header to remove.
194
195         @return: C{None}
196         """
197         self._rawHeaders.pop(name.lower(), None)
198
199
200     def setRawHeaders(self, name, values):
201         """
202         Sets the raw representation of the given header.
203
204         @type name: C{str}
205         @param name: The name of the HTTP header to set the values for.
206
207         @type values: C{list}
208         @param values: A list of strings each one being a header value of
209             the given name.
210
211         @return: C{None}
212         """
213         if not isinstance(values, list):
214             raise TypeError("Header entry %r should be list but found "
215                             "instance of %r instead" % (name, type(values)))
216         self._rawHeaders[name.lower()] = values
217
218
219     def addRawHeader(self, name, value):
220         """
221         Add a new raw value for the given header.
222
223         @type name: C{str}
224         @param name: The name of the header for which to set the value.
225
226         @type value: C{str}
227         @param value: The value to set for the named header.
228         """
229         values = self.getRawHeaders(name)
230         if values is None:
231             self.setRawHeaders(name, [value])
232         else:
233             values.append(value)
234
235
236     def getRawHeaders(self, name, default=None):
237         """
238         Returns a list of headers matching the given name as the raw string
239         given.
240
241         @type name: C{str}
242         @param name: The name of the HTTP header to get the values of.
243
244         @param default: The value to return if no header with the given C{name}
245             exists.
246
247         @rtype: C{list}
248         @return: A C{list} of values for the given header.
249         """
250         return self._rawHeaders.get(name.lower(), default)
251
252
253     def getAllRawHeaders(self):
254         """
255         Return an iterator of key, value pairs of all headers contained in this
256         object, as strings.  The keys are capitalized in canonical
257         capitalization.
258         """
259         for k, v in self._rawHeaders.iteritems():
260             yield self._canonicalNameCaps(k), v
261
262
263     def _canonicalNameCaps(self, name):
264         """
265         Return the canonical name for the given header.
266
267         @type name: C{str}
268         @param name: The all-lowercase header name to capitalize in its
269             canonical form.
270
271         @rtype: C{str}
272         @return: The canonical name of the header.
273         """
274         return self._caseMappings.get(name, _dashCapitalize(name))
275
276
277 __all__ = ['Headers']