1b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) 2b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php 3b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik"""Routines to generate WSGI responses""" 4b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 5b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik############################################################ 6b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik## Headers 7b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik############################################################ 8b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikimport warnings 9b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 10b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HeaderDict(dict): 11b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 12b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 13b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik This represents response headers. It handles the headers as a 14b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik dictionary, with case-insensitive keys. 15b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 16b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Also there is an ``.add(key, value)`` method, which sets the key, 17b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik or adds the value to the current value (turning it into a list if 18b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik necessary). 19b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 20b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik For passing to WSGI there is a ``.headeritems()`` method which is 21b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik like ``.items()`` but unpacks value that are lists. It also 22b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik handles encoding -- all headers are encoded in ASCII (if they are 23b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik unicode). 24b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 25b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik @@: Should that encoding be ISO-8859-1 or UTF-8? I'm not sure 26b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik what the spec says. 27b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 28b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 29b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __getitem__(self, key): 30b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return dict.__getitem__(self, self.normalize(key)) 31b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 32b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __setitem__(self, key, value): 33b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik dict.__setitem__(self, self.normalize(key), value) 34b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 35b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __delitem__(self, key): 36b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik dict.__delitem__(self, self.normalize(key)) 37b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 38b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __contains__(self, key): 39b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return dict.__contains__(self, self.normalize(key)) 40b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 41b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik has_key = __contains__ 42b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 43b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def get(self, key, failobj=None): 44b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return dict.get(self, self.normalize(key), failobj) 45b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 46b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def setdefault(self, key, failobj=None): 47b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return dict.setdefault(self, self.normalize(key), failobj) 48b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 49b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def pop(self, key, *args): 50b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return dict.pop(self, self.normalize(key), *args) 51b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 52b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def update(self, other): 53b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for key in other: 54b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self[self.normalize(key)] = other[key] 55b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 56b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def normalize(self, key): 57b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return str(key).lower().strip() 58b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 59b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def add(self, key, value): 60b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik key = self.normalize(key) 61b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if key in self: 62b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if isinstance(self[key], list): 63b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self[key].append(value) 64b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 65b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self[key] = [self[key], value] 66b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 67b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self[key] = value 68b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 69b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def headeritems(self): 70b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik result = [] 71b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for key, value in self.items(): 72b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if isinstance(value, list): 73b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for v in value: 74b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik result.append((key, str(v))) 75b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 76b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik result.append((key, str(value))) 77b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return result 78b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 79b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik #@classmethod 80b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def fromlist(cls, seq): 81b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self = cls() 82b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for name, value in seq: 83b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self.add(name, value) 84b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return self 85b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 86b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik fromlist = classmethod(fromlist) 87b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 88b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef has_header(headers, name): 89b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 90b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Is header named ``name`` present in headers? 91b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 92b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik name = name.lower() 93b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for header, value in headers: 94b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if header.lower() == name: 95b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return True 96b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return False 97b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 98b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef header_value(headers, name): 99b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 100b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Returns the header's value, or None if no such header. If a 101b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik header appears more than once, all the values of the headers 102b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik are joined with ','. Note that this is consistent /w RFC 2616 103b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik section 4.2 which states: 104b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 105b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik It MUST be possible to combine the multiple header fields 106b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik into one "field-name: field-value" pair, without changing 107b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik the semantics of the message, by appending each subsequent 108b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik field-value to the first, each separated by a comma. 109b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 110b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik However, note that the original netscape usage of 'Set-Cookie', 111b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik especially in MSIE which contains an 'expires' date will is not 112b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik compatible with this particular concatination method. 113b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 114b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik name = name.lower() 115b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik result = [value for header, value in headers 116b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if header.lower() == name] 117b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if result: 118b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return ','.join(result) 119b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 120b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return None 121b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 122b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef remove_header(headers, name): 123b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 124b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Removes the named header from the list of headers. Returns the 125b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik value of that header, or None if no header found. If multiple 126b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik headers are found, only the last one is returned. 127b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 128b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik name = name.lower() 129b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik i = 0 130b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik result = None 131b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik while i < len(headers): 132b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if headers[i][0].lower() == name: 133b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik result = headers[i][1] 134b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik del headers[i] 135b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik continue 136b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik i += 1 137b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return result 138b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 139b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef replace_header(headers, name, value): 140b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 141b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Updates the headers replacing the first occurance of the given name 142b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik with the value provided; asserting that no further occurances 143b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik happen. Note that this is _not_ the same as remove_header and then 144b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik append, as two distinct operations (del followed by an append) are 145b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik not atomic in a threaded environment. Returns the previous header 146b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik value for the provided name, if any. Clearly one should not use 147b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik this function with ``set-cookie`` or other names that may have more 148b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik than one occurance in the headers. 149b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 150b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik name = name.lower() 151b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik i = 0 152b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik result = None 153b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik while i < len(headers): 154b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if headers[i][0].lower() == name: 155b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik assert not result, "two values for the header '%s' found" % name 156b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik result = headers[i][1] 157b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik headers[i] = (name, value) 158b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik i += 1 159b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if not result: 160b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik headers.append((name, value)) 161b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return result 162b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 163b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 164b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik############################################################ 165b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik## Deprecated methods 166b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik############################################################ 167b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 168b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef error_body_response(error_code, message, __warn=True): 169b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 170b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Returns a standard HTML response page for an HTTP error. 171b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik **Note:** Deprecated 172b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 173b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if __warn: 174b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik warnings.warn( 175b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 'wsgilib.error_body_response is deprecated; use the ' 176b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 'wsgi_application method on an HTTPException object ' 177b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 'instead', DeprecationWarning, 2) 178b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return '''\ 179b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik<html> 180b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik <head> 181b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik <title>%(error_code)s</title> 182b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik </head> 183b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik <body> 184b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik <h1>%(error_code)s</h1> 185b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik %(message)s 186b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik </body> 187b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik</html>''' % { 188b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 'error_code': error_code, 189b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 'message': message, 190b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik } 191b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 192b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 193b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef error_response(environ, error_code, message, 194b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik debug_message=None, __warn=True): 195b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 196b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Returns the status, headers, and body of an error response. 197b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 198b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Use like: 199b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 200b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik .. code-block:: python 201b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 202b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik status, headers, body = wsgilib.error_response( 203b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik '301 Moved Permanently', 'Moved to <a href="%s">%s</a>' 204b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik % (url, url)) 205b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik start_response(status, headers) 206b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return [body] 207b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 208b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik **Note:** Deprecated 209b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 210b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if __warn: 211b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik warnings.warn( 212b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 'wsgilib.error_response is deprecated; use the ' 213b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 'wsgi_application method on an HTTPException object ' 214b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 'instead', DeprecationWarning, 2) 215b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if debug_message and environ.get('paste.config', {}).get('debug'): 216b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik message += '\n\n<!-- %s -->' % debug_message 217b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik body = error_body_response(error_code, message, __warn=False) 218b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik headers = [('content-type', 'text/html'), 219b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik ('content-length', str(len(body)))] 220b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return error_code, headers, body 221b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 222b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef error_response_app(error_code, message, debug_message=None, 223b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik __warn=True): 224b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 225b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik An application that emits the given error response. 226b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 227b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik **Note:** Deprecated 228b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 229b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if __warn: 230b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik warnings.warn( 231b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 'wsgilib.error_response_app is deprecated; use the ' 232b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 'wsgi_application method on an HTTPException object ' 233b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 'instead', DeprecationWarning, 2) 234b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def application(environ, start_response): 235b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik status, headers, body = error_response( 236b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik environ, error_code, message, 237b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik debug_message=debug_message, __warn=False) 238b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik start_response(status, headers) 239b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return [body] 240b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return application 241