class Response(Future): '''connect/express inspired response object''' default_status = 200 default_mimetype = 'text/plain' @property def status_code(self): return self._status_code @status_code.setter def status_code(self, code): self._status_code = code try: self._status = '%d %s' % (code, HTTP_STATUS_CODES[code].upper()) except KeyError: self._status = '%d UNKNOWN' % code def __init__(self, environ, start_response): super(Response, self).__init__() self.environ = environ self.start_response = start_response self.headers = Headers() self.status_code = self.default_status self.headers['Content-Type'] = self.default_status def status(self, code): self.status_code = code return self def end(self): headers = self.headers.to_wsgi_list() self.start_response(self._status, headers) return self def send(self, result): if isinstance(result, bytes): result = [result] headers = self.headers.to_wsgi_list() self.start_response(self._status, headers) self.set_result(result) return self
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_wsgi_list(), exc_info)
def fixing_start_response(status, headers, exc_info=None): headers = Headers(headers) self.fix_headers(environ, headers, status) return start_response(status, headers.to_wsgi_list(), exc_info)
class Response(object): """A response wrapper. :param body: Body of the response. :param headers: Headers to respond with. :param status_code: Status-code of the response [default 200]. :type body: str :type headers: werkzeug.datastructures.Headers | list :type status_code: int .. code-block:: python import poort def application(environ, start_response): request = poort.Request(environ) response = poort.Response('Hallo world!') return response(request, start_response) """ def __init__(self, body='', headers=None, status_code=200): self.status_code = status_code self.headers = Headers(headers) self.body = body def get_status(self): """Get the status of the response as HTTP code. :rtype: str """ return '{:d} {:s}'.format(self.status_code, HTTP_STATUS_CODES[self.status_code]) def get_body(self): """Retrieve the body of the response. You can override this method to serialize JSON, for example, and return this as the body. :rtype: str """ return self.body def prepare_response(self, request=None): """Prepare the response. This prepares (encodes) the body, you can override this method to add/override headers when the response is being prepared. To yield other content, you should look at `get_body`. :param request: Request that was made, None is allowed. :type request: poort.Request :rtype: str """ if PY2: return [self.get_body().encode('utf-8')] else: return [bytes(self.get_body(), 'UTF8')] def respond(self, request): """Prepare a tuple to respond with. :param request: Request that was made, None is allowed. :type request: poort.Request :rtype: tuple[str, list[str], str] """ response = self.prepare_response(request) return (self.get_status(), self.headers.to_wsgi_list(), response) def __call__(self, request, start_response): """Respond to WSGI with the current settings. :param request: Request that was made, None is allowed. :param start_response: Handler provided by WSGI. :type request: poort.Request :type start_response: callable """ status, headers, response = self.respond(request) start_response(status, headers) return response def set_cookie(self, name, value='', max_age=None, path='/', domain=None, secure=False, httponly=True): """Add a cookie to the response. :param name: Name of the cookie. :param value: Value of the cookie (should always be a string). :param max_age: Maximum age (leave `None` for "browser session"). :param path: Path to bind the cookie to [default `'/'`]. :param domain: Domain to bind the cookie to [default `None`]. :param secure: Secure the cookie [default `False`], handy: `request.ssl`. :param httponly: Cookie not accessable by JavaScript [default `true`]. :type name: str :type value: str :type max_age: int | None :type path: str :type domain: str | None :type secure: bool :type httponly: bool """ self.headers.add('Set-Cookie', dump_cookie( name, value=str(value), max_age=max_age, path=path, domain=domain, secure=secure, httponly=httponly, charset='utf-8', sync_expires=True)) def del_cookie(self, name, path='/', domain=None, secure=False, httponly=True): """Delete a cookie from the browser. :param name: Name of the cookie. :param path: Path to bind the cookie to [default `'/'`]. :param domain: Domain to bind the cookie to [default `None`]. :param secure: Secure the cookie [default `False`], handy: `request.ssl`. :param httponly: Cookie not accessable by JavaScript [default `true`]. :type name: str :type path: str :type domain: str | None :type secure: bool :type httponly: bool .. note:: Take note that you must match the original settings of the cookie. Deleting a cookie with a non-matching path will not work. """ self.set_cookie(name, max_age=0, path=path, domain=domain, secure=secure, httponly=httponly)