Exemple #1
0
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
Exemple #2
0
 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)
Exemple #3
0
 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)
Exemple #4
0
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)