def add_cors_headers(status, headers, exc_info=None): headers = Headers(headers) headers.add("Access-Control-Allow-Origin", self.origin(environ)) headers.add("Access-Control-Allow-Headers", "Origin, Content-Type") headers.add("Access-Control-Allow-Credentials", "true") headers.add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE") headers.add("Access-Control-Expose-Headers", "X-Set-Cookie") return start_response(status, headers.to_list(), exc_info)
def add_cors_headers(status, headers, exc_info=None): headers = Headers(headers) headers.add("Access-Control-Allow-Origin", self.origin(environ)) headers.add("Access-Control-Allow-Credentials", "true") headers.add("Access-Control-Allow-Methods", ", ".join(self.methods)) if self.allowed: headers.add("Access-Control-Allow-Headers", ", ".join(self.allowed)) if self.exposed: headers.add("Access-Control-Expose-Headers", ", ".join(self.exposed)) return start_response(status, headers.to_list(), exc_info)
def add_cors_headers(status, headers, exc_info=None): headers = Headers(headers) headers.add("Access-Control-Allow-Origin", get_origin(status, headers)) headers.add("Access-Control-Allow-Headers", cfg.get("cors_headers")) headers.add("Access-Control-Allow-Credentials", cfg.get("cors_credentials")) headers.add("Access-Control-Allow-Methods", cfg.get("cors_methods")) headers.add("Access-Control-Expose-Headers", cfg.get("cors_expose_headers")) return start_response(status, headers.to_list(), exc_info)
def add_cors_headers(status, headers, exc_info=None): for host in self.hosts: if environ.get("HTTP_ORIGIN", None) == host.rstrip("/"): origin = host.rstrip("/") break else: origin = host.rstrip("/") headers = Headers(headers) headers.add("Access-Control-Allow-Origin", origin) headers.add("Access-Control-Allow-Headers", "Origin, Content-Type") headers.add("Access-Control-Allow-Credentials", "true") headers.add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE") headers.add("Access-Control-Expose-Headers", "X-Set-Cookie") return start_response(status, headers.to_list(), exc_info)
class BaseResponse(object): charset = 'utf-8' default_status = 200 default_mimetype = 'text/plain' implicit_sequence_conversion = True def __init__(self, response = None, status = None, headers = None, mimetype = None, content_type = None, direct_passthrough = False): if isinstance(headers, Headers): self.headers = headers elif not headers: self.headers = Headers() else: self.headers = Headers(headers) if content_type is None: if mimetype is None and 'content-type' not in self.headers: mimetype = self.default_mimetype if mimetype is not None: mimetype = get_content_type(mimetype, self.charset) content_type = mimetype if content_type is not None: self.headers['Content-Type'] = content_type if status is None: status = self.default_status if isinstance(status, (int, long)): self.status_code = status else: self.status = status self.direct_passthrough = direct_passthrough self._on_close = [] if response is None: self.response = [] elif isinstance(response, basestring): self.data = response else: self.response = response def call_on_close(self, func): self._on_close.append(func) def __repr__(self): if self.is_sequence: body_info = '%d bytes' % sum(map(len, self.iter_encoded())) else: body_info = self.is_streamed and 'streamed' or 'likely-streamed' return '<%s %s [%s]>' % (self.__class__.__name__, body_info, self.status) @classmethod def force_type(cls, response, environ = None): if not isinstance(response, BaseResponse): if environ is None: raise TypeError('cannot convert WSGI application into response objects without an environ') response = BaseResponse(*_run_wsgi_app(response, environ)) response.__class__ = cls return response @classmethod def from_app(cls, app, environ, buffered = False): return cls(*_run_wsgi_app(app, environ, buffered)) def _get_status_code(self): try: return int(self.status.split(None, 1)[0]) except ValueError: return 0 def _set_status_code(self, code): try: self.status = '%d %s' % (code, HTTP_STATUS_CODES[code].upper()) except KeyError: self.status = '%d UNKNOWN' % code status_code = property(_get_status_code, _set_status_code, 'The HTTP Status code as number') del _get_status_code del _set_status_code def _get_data(self): self._ensure_sequence() return ''.join(self.iter_encoded()) def _set_data(self, value): if isinstance(value, unicode): value = value.encode(self.charset) self.response = [value] data = property(_get_data, _set_data, doc=_get_data.__doc__) del _get_data del _set_data def _ensure_sequence(self, mutable = False): if self.is_sequence: if mutable and not isinstance(self.response, list): self.response = list(self.response) return if not self.implicit_sequence_conversion: raise RuntimeError('The response object required the iterable to be a sequence, but the implicit conversion was disabled. Call make_sequence() yourself.') self.make_sequence() def make_sequence(self): if not self.is_sequence: close = getattr(self.response, 'close', None) self.response = list(self.iter_encoded()) if close is not None: self.call_on_close(close) def iter_encoded(self, charset = None): if __debug__ and charset is not None: from warnings import warn warn(DeprecationWarning('charset was deprecated and is ignored.'), stacklevel=2) charset = self.charset for item in self.response: if isinstance(item, unicode): yield item.encode(charset) else: yield str(item) def set_cookie(self, key, value = '', max_age = None, expires = None, path = '/', domain = None, secure = None, httponly = False): self.headers.add('Set-Cookie', dump_cookie(key, value, max_age, expires, path, domain, secure, httponly, self.charset)) def delete_cookie(self, key, path = '/', domain = None): self.set_cookie(key, expires=0, max_age=0, path=path, domain=domain) @property def header_list(self): return self.headers.to_list(self.charset) @property def is_streamed(self): try: len(self.response) except TypeError: return True return False @property def is_sequence(self): return isinstance(self.response, (tuple, list)) def close(self): if hasattr(self.response, 'close'): self.response.close() for func in self._on_close: func() def freeze(self): self.response = list(self.iter_encoded()) self.headers['Content-Length'] = str(sum(map(len, self.response))) def fix_headers(self, environ): self.headers[:] = self.get_wsgi_headers(environ) def get_wsgi_headers(self, environ): headers = Headers(self.headers) location = headers.get('location') if location is not None: if isinstance(location, unicode): location = iri_to_uri(location) headers['Location'] = urlparse.urljoin(get_current_url(environ, root_only=True), location) content_location = headers.get('content-location') if content_location is not None and isinstance(content_location, unicode): headers['Content-Location'] = iri_to_uri(content_location) if 100 <= self.status_code < 200 or self.status_code == 204: headers['Content-Length'] = '0' elif self.status_code == 304: remove_entity_headers(headers) if self.is_sequence and 'content-length' not in self.headers: try: content_length = sum((len(str(x)) for x in self.response)) except UnicodeError: pass else: headers['Content-Length'] = str(content_length) return headers def get_app_iter(self, environ): if environ['REQUEST_METHOD'] == 'HEAD' or 100 <= self.status_code < 200 or self.status_code in (204, 304): return () if self.direct_passthrough: return self.response return ClosingIterator(self.iter_encoded(), self.close) def get_wsgi_response(self, environ): if self.fix_headers.func_code is not BaseResponse.fix_headers.func_code: self.fix_headers(environ) headers = self.headers else: headers = self.get_wsgi_headers(environ) app_iter = self.get_app_iter(environ) return (app_iter, self.status, headers.to_list(self.charset)) def __call__(self, environ, start_response): app_iter, status, headers = self.get_wsgi_response(environ) start_response(status, headers) return app_iter
def test_headers(): # simple header tests headers = Headers() headers.add("Content-Type", "text/plain") headers.add("X-Foo", "bar") assert "x-Foo" in headers assert "Content-type" in headers headers["Content-Type"] = "foo/bar" assert headers["Content-Type"] == "foo/bar" assert len(headers.getlist("Content-Type")) == 1 # list conversion assert headers.to_list() == [("Content-Type", "foo/bar"), ("X-Foo", "bar")] assert str(headers) == ("Content-Type: foo/bar\r\n" "X-Foo: bar\r\n" "\r\n") assert str(Headers()) == "\r\n" # extended add headers.add("Content-Disposition", "attachment", filename="foo") assert headers["Content-Disposition"] == "attachment; filename=foo" headers.add("x", "y", z='"') assert headers["x"] == r'y; z="\""' # defaults headers = Headers([("Content-Type", "text/plain"), ("X-Foo", "bar"), ("X-Bar", "1"), ("X-Bar", "2")]) assert headers.getlist("x-bar") == ["1", "2"] assert headers.get("x-Bar") == "1" assert headers.get("Content-Type") == "text/plain" assert headers.setdefault("X-Foo", "nope") == "bar" assert headers.setdefault("X-Bar", "nope") == "1" assert headers.setdefault("X-Baz", "quux") == "quux" assert headers.setdefault("X-Baz", "nope") == "quux" headers.pop("X-Baz") # type conversion assert headers.get("x-bar", type=int) == 1 assert headers.getlist("x-bar", type=int) == [1, 2] # list like operations assert headers[0] == ("Content-Type", "text/plain") assert headers[:1] == Headers([("Content-Type", "text/plain")]) del headers[:2] del headers[-1] assert headers == Headers([("X-Bar", "1")]) # copying a = Headers([("foo", "bar")]) b = a.copy() a.add("foo", "baz") assert a.getlist("foo") == ["bar", "baz"] assert b.getlist("foo") == ["bar"] headers = Headers([("a", 1)]) assert headers.pop("a") == 1 assert headers.pop("b", 2) == 2 assert_raises(KeyError, headers.pop, "c") # set replaces and accepts same arguments as add a = Headers() a.set("Content-Disposition", "useless") a.set("Content-Disposition", "attachment", filename="foo") assert a["Content-Disposition"] == "attachment; filename=foo"
def test_headers(): # simple header tests headers = Headers() headers.add('Content-Type', 'text/plain') headers.add('X-Foo', 'bar') assert 'x-Foo' in headers assert 'Content-type' in headers headers['Content-Type'] = 'foo/bar' assert headers['Content-Type'] == 'foo/bar' assert len(headers.getlist('Content-Type')) == 1 # list conversion assert headers.to_list() == [ ('Content-Type', 'foo/bar'), ('X-Foo', 'bar') ] assert str(headers) == ( "Content-Type: foo/bar\r\n" "X-Foo: bar\r\n" "\r\n") assert str(Headers()) == "\r\n" # extended add headers.add('Content-Disposition', 'attachment', filename='foo') assert headers['Content-Disposition'] == 'attachment; filename=foo' headers.add('x', 'y', z='"') assert headers['x'] == r'y; z="\""' # defaults headers = Headers([ ('Content-Type', 'text/plain'), ('X-Foo', 'bar'), ('X-Bar', '1'), ('X-Bar', '2') ]) assert headers.getlist('x-bar') == ['1', '2'] assert headers.get('x-Bar') == '1' assert headers.get('Content-Type') == 'text/plain' assert headers.setdefault('X-Foo', 'nope') == 'bar' assert headers.setdefault('X-Bar', 'nope') == '1' assert headers.setdefault('X-Baz', 'quux') == 'quux' assert headers.setdefault('X-Baz', 'nope') == 'quux' headers.pop('X-Baz') # type conversion assert headers.get('x-bar', type=int) == 1 assert headers.getlist('x-bar', type=int) == [1, 2] # list like operations assert headers[0] == ('Content-Type', 'text/plain') assert headers[:1] == Headers([('Content-Type', 'text/plain')]) del headers[:2] del headers[-1] assert headers == Headers([('X-Bar', '1')]) # copying a = Headers([('foo', 'bar')]) b = a.copy() a.add('foo', 'baz') assert a.getlist('foo') == ['bar', 'baz'] assert b.getlist('foo') == ['bar'] headers = Headers([('a', 1)]) assert headers.pop('a') == 1 assert headers.pop('b', 2) == 2 assert_raises(KeyError, headers.pop, 'c') # set replaces and accepts same arguments as add a = Headers() a.set('Content-Disposition', 'useless') a.set('Content-Disposition', 'attachment', filename='foo') assert a['Content-Disposition'] == 'attachment; filename=foo'
def test_headers(): # simple header tests headers = Headers() headers.add('Content-Type', 'text/plain') headers.add('X-Foo', 'bar') assert 'x-Foo' in headers assert 'Content-type' in headers headers['Content-Type'] = 'foo/bar' assert headers['Content-Type'] == 'foo/bar' assert len(headers.getlist('Content-Type')) == 1 # list conversion assert headers.to_list() == [('Content-Type', 'foo/bar'), ('X-Foo', 'bar')] assert str(headers) == ("Content-Type: foo/bar\r\n" "X-Foo: bar\r\n" "\r\n") assert str(Headers()) == "\r\n" # extended add headers.add('Content-Disposition', 'attachment', filename='foo') assert headers['Content-Disposition'] == 'attachment; filename=foo' headers.add('x', 'y', z='"') assert headers['x'] == r'y; z="\""' # defaults headers = Headers([('Content-Type', 'text/plain'), ('X-Foo', 'bar'), ('X-Bar', '1'), ('X-Bar', '2')]) assert headers.getlist('x-bar') == ['1', '2'] assert headers.get('x-Bar') == '1' assert headers.get('Content-Type') == 'text/plain' assert headers.setdefault('X-Foo', 'nope') == 'bar' assert headers.setdefault('X-Bar', 'nope') == '1' assert headers.setdefault('X-Baz', 'quux') == 'quux' assert headers.setdefault('X-Baz', 'nope') == 'quux' headers.pop('X-Baz') # type conversion assert headers.get('x-bar', type=int) == 1 assert headers.getlist('x-bar', type=int) == [1, 2] # list like operations assert headers[0] == ('Content-Type', 'text/plain') assert headers[:1] == Headers([('Content-Type', 'text/plain')]) del headers[:2] del headers[-1] assert headers == Headers([('X-Bar', '1')]) # copying a = Headers([('foo', 'bar')]) b = a.copy() a.add('foo', 'baz') assert a.getlist('foo') == ['bar', 'baz'] assert b.getlist('foo') == ['bar'] headers = Headers([('a', 1)]) assert headers.pop('a') == 1 assert headers.pop('b', 2) == 2 assert_raises(KeyError, headers.pop, 'c') # set replaces and accepts same arguments as add a = Headers() a.set('Content-Disposition', 'useless') a.set('Content-Disposition', 'attachment', filename='foo') assert a['Content-Disposition'] == 'attachment; filename=foo'