1*cda5da8dSAndroid Build Coastguard Worker"""Manage HTTP Response Headers 2*cda5da8dSAndroid Build Coastguard Worker 3*cda5da8dSAndroid Build Coastguard WorkerMuch of this module is red-handedly pilfered from email.message in the stdlib, 4*cda5da8dSAndroid Build Coastguard Workerso portions are Copyright (C) 2001,2002 Python Software Foundation, and were 5*cda5da8dSAndroid Build Coastguard Workerwritten by Barry Warsaw. 6*cda5da8dSAndroid Build Coastguard Worker""" 7*cda5da8dSAndroid Build Coastguard Worker 8*cda5da8dSAndroid Build Coastguard Worker# Regular expression that matches `special' characters in parameters, the 9*cda5da8dSAndroid Build Coastguard Worker# existence of which force quoting of the parameter value. 10*cda5da8dSAndroid Build Coastguard Workerimport re 11*cda5da8dSAndroid Build Coastguard Workertspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]') 12*cda5da8dSAndroid Build Coastguard Worker 13*cda5da8dSAndroid Build Coastguard Workerdef _formatparam(param, value=None, quote=1): 14*cda5da8dSAndroid Build Coastguard Worker """Convenience function to format and return a key=value pair. 15*cda5da8dSAndroid Build Coastguard Worker 16*cda5da8dSAndroid Build Coastguard Worker This will quote the value if needed or if quote is true. 17*cda5da8dSAndroid Build Coastguard Worker """ 18*cda5da8dSAndroid Build Coastguard Worker if value is not None and len(value) > 0: 19*cda5da8dSAndroid Build Coastguard Worker if quote or tspecials.search(value): 20*cda5da8dSAndroid Build Coastguard Worker value = value.replace('\\', '\\\\').replace('"', r'\"') 21*cda5da8dSAndroid Build Coastguard Worker return '%s="%s"' % (param, value) 22*cda5da8dSAndroid Build Coastguard Worker else: 23*cda5da8dSAndroid Build Coastguard Worker return '%s=%s' % (param, value) 24*cda5da8dSAndroid Build Coastguard Worker else: 25*cda5da8dSAndroid Build Coastguard Worker return param 26*cda5da8dSAndroid Build Coastguard Worker 27*cda5da8dSAndroid Build Coastguard Worker 28*cda5da8dSAndroid Build Coastguard Workerclass Headers: 29*cda5da8dSAndroid Build Coastguard Worker """Manage a collection of HTTP response headers""" 30*cda5da8dSAndroid Build Coastguard Worker 31*cda5da8dSAndroid Build Coastguard Worker def __init__(self, headers=None): 32*cda5da8dSAndroid Build Coastguard Worker headers = headers if headers is not None else [] 33*cda5da8dSAndroid Build Coastguard Worker if type(headers) is not list: 34*cda5da8dSAndroid Build Coastguard Worker raise TypeError("Headers must be a list of name/value tuples") 35*cda5da8dSAndroid Build Coastguard Worker self._headers = headers 36*cda5da8dSAndroid Build Coastguard Worker if __debug__: 37*cda5da8dSAndroid Build Coastguard Worker for k, v in headers: 38*cda5da8dSAndroid Build Coastguard Worker self._convert_string_type(k) 39*cda5da8dSAndroid Build Coastguard Worker self._convert_string_type(v) 40*cda5da8dSAndroid Build Coastguard Worker 41*cda5da8dSAndroid Build Coastguard Worker def _convert_string_type(self, value): 42*cda5da8dSAndroid Build Coastguard Worker """Convert/check value type.""" 43*cda5da8dSAndroid Build Coastguard Worker if type(value) is str: 44*cda5da8dSAndroid Build Coastguard Worker return value 45*cda5da8dSAndroid Build Coastguard Worker raise AssertionError("Header names/values must be" 46*cda5da8dSAndroid Build Coastguard Worker " of type str (got {0})".format(repr(value))) 47*cda5da8dSAndroid Build Coastguard Worker 48*cda5da8dSAndroid Build Coastguard Worker def __len__(self): 49*cda5da8dSAndroid Build Coastguard Worker """Return the total number of headers, including duplicates.""" 50*cda5da8dSAndroid Build Coastguard Worker return len(self._headers) 51*cda5da8dSAndroid Build Coastguard Worker 52*cda5da8dSAndroid Build Coastguard Worker def __setitem__(self, name, val): 53*cda5da8dSAndroid Build Coastguard Worker """Set the value of a header.""" 54*cda5da8dSAndroid Build Coastguard Worker del self[name] 55*cda5da8dSAndroid Build Coastguard Worker self._headers.append( 56*cda5da8dSAndroid Build Coastguard Worker (self._convert_string_type(name), self._convert_string_type(val))) 57*cda5da8dSAndroid Build Coastguard Worker 58*cda5da8dSAndroid Build Coastguard Worker def __delitem__(self,name): 59*cda5da8dSAndroid Build Coastguard Worker """Delete all occurrences of a header, if present. 60*cda5da8dSAndroid Build Coastguard Worker 61*cda5da8dSAndroid Build Coastguard Worker Does *not* raise an exception if the header is missing. 62*cda5da8dSAndroid Build Coastguard Worker """ 63*cda5da8dSAndroid Build Coastguard Worker name = self._convert_string_type(name.lower()) 64*cda5da8dSAndroid Build Coastguard Worker self._headers[:] = [kv for kv in self._headers if kv[0].lower() != name] 65*cda5da8dSAndroid Build Coastguard Worker 66*cda5da8dSAndroid Build Coastguard Worker def __getitem__(self,name): 67*cda5da8dSAndroid Build Coastguard Worker """Get the first header value for 'name' 68*cda5da8dSAndroid Build Coastguard Worker 69*cda5da8dSAndroid Build Coastguard Worker Return None if the header is missing instead of raising an exception. 70*cda5da8dSAndroid Build Coastguard Worker 71*cda5da8dSAndroid Build Coastguard Worker Note that if the header appeared multiple times, the first exactly which 72*cda5da8dSAndroid Build Coastguard Worker occurrence gets returned is undefined. Use getall() to get all 73*cda5da8dSAndroid Build Coastguard Worker the values matching a header field name. 74*cda5da8dSAndroid Build Coastguard Worker """ 75*cda5da8dSAndroid Build Coastguard Worker return self.get(name) 76*cda5da8dSAndroid Build Coastguard Worker 77*cda5da8dSAndroid Build Coastguard Worker def __contains__(self, name): 78*cda5da8dSAndroid Build Coastguard Worker """Return true if the message contains the header.""" 79*cda5da8dSAndroid Build Coastguard Worker return self.get(name) is not None 80*cda5da8dSAndroid Build Coastguard Worker 81*cda5da8dSAndroid Build Coastguard Worker 82*cda5da8dSAndroid Build Coastguard Worker def get_all(self, name): 83*cda5da8dSAndroid Build Coastguard Worker """Return a list of all the values for the named field. 84*cda5da8dSAndroid Build Coastguard Worker 85*cda5da8dSAndroid Build Coastguard Worker These will be sorted in the order they appeared in the original header 86*cda5da8dSAndroid Build Coastguard Worker list or were added to this instance, and may contain duplicates. Any 87*cda5da8dSAndroid Build Coastguard Worker fields deleted and re-inserted are always appended to the header list. 88*cda5da8dSAndroid Build Coastguard Worker If no fields exist with the given name, returns an empty list. 89*cda5da8dSAndroid Build Coastguard Worker """ 90*cda5da8dSAndroid Build Coastguard Worker name = self._convert_string_type(name.lower()) 91*cda5da8dSAndroid Build Coastguard Worker return [kv[1] for kv in self._headers if kv[0].lower()==name] 92*cda5da8dSAndroid Build Coastguard Worker 93*cda5da8dSAndroid Build Coastguard Worker 94*cda5da8dSAndroid Build Coastguard Worker def get(self,name,default=None): 95*cda5da8dSAndroid Build Coastguard Worker """Get the first header value for 'name', or return 'default'""" 96*cda5da8dSAndroid Build Coastguard Worker name = self._convert_string_type(name.lower()) 97*cda5da8dSAndroid Build Coastguard Worker for k,v in self._headers: 98*cda5da8dSAndroid Build Coastguard Worker if k.lower()==name: 99*cda5da8dSAndroid Build Coastguard Worker return v 100*cda5da8dSAndroid Build Coastguard Worker return default 101*cda5da8dSAndroid Build Coastguard Worker 102*cda5da8dSAndroid Build Coastguard Worker 103*cda5da8dSAndroid Build Coastguard Worker def keys(self): 104*cda5da8dSAndroid Build Coastguard Worker """Return a list of all the header field names. 105*cda5da8dSAndroid Build Coastguard Worker 106*cda5da8dSAndroid Build Coastguard Worker These will be sorted in the order they appeared in the original header 107*cda5da8dSAndroid Build Coastguard Worker list, or were added to this instance, and may contain duplicates. 108*cda5da8dSAndroid Build Coastguard Worker Any fields deleted and re-inserted are always appended to the header 109*cda5da8dSAndroid Build Coastguard Worker list. 110*cda5da8dSAndroid Build Coastguard Worker """ 111*cda5da8dSAndroid Build Coastguard Worker return [k for k, v in self._headers] 112*cda5da8dSAndroid Build Coastguard Worker 113*cda5da8dSAndroid Build Coastguard Worker def values(self): 114*cda5da8dSAndroid Build Coastguard Worker """Return a list of all header values. 115*cda5da8dSAndroid Build Coastguard Worker 116*cda5da8dSAndroid Build Coastguard Worker These will be sorted in the order they appeared in the original header 117*cda5da8dSAndroid Build Coastguard Worker list, or were added to this instance, and may contain duplicates. 118*cda5da8dSAndroid Build Coastguard Worker Any fields deleted and re-inserted are always appended to the header 119*cda5da8dSAndroid Build Coastguard Worker list. 120*cda5da8dSAndroid Build Coastguard Worker """ 121*cda5da8dSAndroid Build Coastguard Worker return [v for k, v in self._headers] 122*cda5da8dSAndroid Build Coastguard Worker 123*cda5da8dSAndroid Build Coastguard Worker def items(self): 124*cda5da8dSAndroid Build Coastguard Worker """Get all the header fields and values. 125*cda5da8dSAndroid Build Coastguard Worker 126*cda5da8dSAndroid Build Coastguard Worker These will be sorted in the order they were in the original header 127*cda5da8dSAndroid Build Coastguard Worker list, or were added to this instance, and may contain duplicates. 128*cda5da8dSAndroid Build Coastguard Worker Any fields deleted and re-inserted are always appended to the header 129*cda5da8dSAndroid Build Coastguard Worker list. 130*cda5da8dSAndroid Build Coastguard Worker """ 131*cda5da8dSAndroid Build Coastguard Worker return self._headers[:] 132*cda5da8dSAndroid Build Coastguard Worker 133*cda5da8dSAndroid Build Coastguard Worker def __repr__(self): 134*cda5da8dSAndroid Build Coastguard Worker return "%s(%r)" % (self.__class__.__name__, self._headers) 135*cda5da8dSAndroid Build Coastguard Worker 136*cda5da8dSAndroid Build Coastguard Worker def __str__(self): 137*cda5da8dSAndroid Build Coastguard Worker """str() returns the formatted headers, complete with end line, 138*cda5da8dSAndroid Build Coastguard Worker suitable for direct HTTP transmission.""" 139*cda5da8dSAndroid Build Coastguard Worker return '\r\n'.join(["%s: %s" % kv for kv in self._headers]+['','']) 140*cda5da8dSAndroid Build Coastguard Worker 141*cda5da8dSAndroid Build Coastguard Worker def __bytes__(self): 142*cda5da8dSAndroid Build Coastguard Worker return str(self).encode('iso-8859-1') 143*cda5da8dSAndroid Build Coastguard Worker 144*cda5da8dSAndroid Build Coastguard Worker def setdefault(self,name,value): 145*cda5da8dSAndroid Build Coastguard Worker """Return first matching header value for 'name', or 'value' 146*cda5da8dSAndroid Build Coastguard Worker 147*cda5da8dSAndroid Build Coastguard Worker If there is no header named 'name', add a new header with name 'name' 148*cda5da8dSAndroid Build Coastguard Worker and value 'value'.""" 149*cda5da8dSAndroid Build Coastguard Worker result = self.get(name) 150*cda5da8dSAndroid Build Coastguard Worker if result is None: 151*cda5da8dSAndroid Build Coastguard Worker self._headers.append((self._convert_string_type(name), 152*cda5da8dSAndroid Build Coastguard Worker self._convert_string_type(value))) 153*cda5da8dSAndroid Build Coastguard Worker return value 154*cda5da8dSAndroid Build Coastguard Worker else: 155*cda5da8dSAndroid Build Coastguard Worker return result 156*cda5da8dSAndroid Build Coastguard Worker 157*cda5da8dSAndroid Build Coastguard Worker def add_header(self, _name, _value, **_params): 158*cda5da8dSAndroid Build Coastguard Worker """Extended header setting. 159*cda5da8dSAndroid Build Coastguard Worker 160*cda5da8dSAndroid Build Coastguard Worker _name is the header field to add. keyword arguments can be used to set 161*cda5da8dSAndroid Build Coastguard Worker additional parameters for the header field, with underscores converted 162*cda5da8dSAndroid Build Coastguard Worker to dashes. Normally the parameter will be added as key="value" unless 163*cda5da8dSAndroid Build Coastguard Worker value is None, in which case only the key will be added. 164*cda5da8dSAndroid Build Coastguard Worker 165*cda5da8dSAndroid Build Coastguard Worker Example: 166*cda5da8dSAndroid Build Coastguard Worker 167*cda5da8dSAndroid Build Coastguard Worker h.add_header('content-disposition', 'attachment', filename='bud.gif') 168*cda5da8dSAndroid Build Coastguard Worker 169*cda5da8dSAndroid Build Coastguard Worker Note that unlike the corresponding 'email.message' method, this does 170*cda5da8dSAndroid Build Coastguard Worker *not* handle '(charset, language, value)' tuples: all values must be 171*cda5da8dSAndroid Build Coastguard Worker strings or None. 172*cda5da8dSAndroid Build Coastguard Worker """ 173*cda5da8dSAndroid Build Coastguard Worker parts = [] 174*cda5da8dSAndroid Build Coastguard Worker if _value is not None: 175*cda5da8dSAndroid Build Coastguard Worker _value = self._convert_string_type(_value) 176*cda5da8dSAndroid Build Coastguard Worker parts.append(_value) 177*cda5da8dSAndroid Build Coastguard Worker for k, v in _params.items(): 178*cda5da8dSAndroid Build Coastguard Worker k = self._convert_string_type(k) 179*cda5da8dSAndroid Build Coastguard Worker if v is None: 180*cda5da8dSAndroid Build Coastguard Worker parts.append(k.replace('_', '-')) 181*cda5da8dSAndroid Build Coastguard Worker else: 182*cda5da8dSAndroid Build Coastguard Worker v = self._convert_string_type(v) 183*cda5da8dSAndroid Build Coastguard Worker parts.append(_formatparam(k.replace('_', '-'), v)) 184*cda5da8dSAndroid Build Coastguard Worker self._headers.append((self._convert_string_type(_name), "; ".join(parts))) 185