예제 #1
0
def notFoundResponse(request: IRequest) -> KleinRenderable:
    """
    Respond with a NOT FOUND status.
    """
    log.debug("Resource not found: {request.uri}", request=request)

    request.setResponseCode(http.NOT_FOUND)
    return textResponse(request, "Not found")
예제 #2
0
def notFoundResponse(request: IRequest) -> KleinRenderable:
    """
    Respond with a NOT FOUND status.
    """
    log.debug("Resource not found: {request.uri}", request=request)

    request.setResponseCode(http.NOT_FOUND)
    return textResponse(request, "Not found")
예제 #3
0
def noContentResponse(request: IRequest,
                      etag: Optional[str] = None) -> KleinRenderable:
    """
    Respond with no content.
    """
    request.setResponseCode(http.NO_CONTENT)
    if etag is not None:
        request.setHeader(HeaderName.etag.value, etag)
    return b""
예제 #4
0
def forbiddenResponse(request: IRequest) -> KleinRenderable:
    """
    Respond with a FORBIDDEN status.
    """
    log.debug("Forbidden resource for user {user}: {request.uri}",
              request=request,
              user=getattr(request, "user", None))

    request.setResponseCode(http.FORBIDDEN)
    return textResponse(request, "Permission denied")
예제 #5
0
def methodNotAllowedResponse(request: IRequest) -> KleinRenderable:
    """
    Respond with a METHOD NOT ALLOWED status.
    """
    log.debug(
        "Method {request.method} not allowed for resource: {request.uri}",
        request=request)

    request.setResponseCode(http.NOT_ALLOWED)
    return textResponse(request, "HTTP method not allowed")
예제 #6
0
def noContentResponse(
    request: IRequest, etag: Optional[str] = None
) -> KleinRenderable:
    """
    Respond with no content.
    """
    request.setResponseCode(http.NO_CONTENT)
    if etag is not None:
        request.setHeader(HeaderName.etag.value, etag)
    return b""
예제 #7
0
    def valueError(self, request: IRequest, failure) -> KleinRenderable:
        """
        Error handler for :exc:`ValueError`.

        :param request: The request to respond to.

        :param failure: The failure that occurred.
        """
        request.setResponseCode(http.BAD_REQUEST)
        return "Invalid inputs provided."
예제 #8
0
def methodNotAllowedResponse(request: IRequest) -> KleinRenderable:
    """
    Respond with a METHOD NOT ALLOWED status.
    """
    log.debug(
        "Method {request.method} not allowed for resource: {request.uri}",
        request=request
    )

    request.setResponseCode(http.NOT_ALLOWED)
    return textResponse(request, "HTTP method not allowed")
예제 #9
0
def forbiddenResponse(request: IRequest) -> KleinRenderable:
    """
    Respond with a FORBIDDEN status.
    """
    log.debug(
        "Forbidden resource for user {user}: {request.uri}",
        request=request, user=getattr(request, "user", None)
    )

    request.setResponseCode(http.FORBIDDEN)
    return textResponse(request, "Permission denied")
예제 #10
0
def badRequestResponse(request: IRequest,
                       message: Optional[str] = None) -> KleinRenderable:
    """
    Respond with a BAD REQUEST status.
    """
    log.debug("Bad request for resource: {request.uri}: {message}",
              request=request,
              message=message)

    request.setResponseCode(http.BAD_REQUEST)
    if message is None:
        message = "Bad request"
    else:
        message = str(message)
    return textResponse(request, message)
예제 #11
0
def internalErrorResponse(request: IRequest,
                          message: Optional[str] = None) -> KleinRenderable:
    """
    Respond with an INTERNAL SERVER ERROR status.
    """
    log.critical("Internal error for resource: {request.uri}: {message}",
                 request=request,
                 message=message)

    request.setResponseCode(http.INTERNAL_SERVER_ERROR)
    if message is None:
        message = "Internal error"
    else:
        message = f"{message}"
    return textResponse(request, message)
예제 #12
0
def internalErrorResponse(
    request: IRequest, message: Optional[str] = None
) -> KleinRenderable:
    """
    Respond with an INTERNAL SERVER ERROR status.
    """
    log.critical(
        "Internal error for resource: {request.uri}: {message}",
        request=request, message=message
    )

    request.setResponseCode(http.INTERNAL_SERVER_ERROR)
    if message is None:
        message = "Internal error"
    else:
        message = f"{message}"
    return textResponse(request, message)
예제 #13
0
def badRequestResponse(
    request: IRequest, message: Optional[str] = None
) -> KleinRenderable:
    """
    Respond with a BAD REQUEST status.
    """
    log.debug(
        "Bad request for resource: {request.uri}: {message}",
        request=request, message=message
    )

    request.setResponseCode(http.BAD_REQUEST)
    if message is None:
        message = "Bad request"
    else:
        message = str(message)
    return textResponse(request, message)
예제 #14
0
파일: _form.py 프로젝트: shippool/klein
def defaultValidationFailureHandler(
    instance: Optional[object],
    request: IRequest,
    fieldValues: "FieldValues",
) -> Element:
    """
    This is the default validation failure handler, which will be used by form
    handlers (i.e. any routes which use L{klein.Requirer} to require a field)
    in the case of any input validation failure when no other validation
    failure handler is registered via L{Form.onValidationFailureFor}.

    Its behavior is to simply return an HTML rendering of the form object,
    which includes inline information about fields which failed to validate.

    @param instance: The instance associated with the router that the form
        handler was handled on.
    @type instance: L{object}

    @param request: The request including the form submission.
    @type request: L{twisted.web.iweb.IRequest}

    @return: Any object acceptable from a Klein route.
    """
    session = request.getComponent(ISession)
    request.setResponseCode(400)
    enctype = ((request.getHeader(b"content-type")
                or RenderableForm.ENCTYPE_URL_ENCODED.encode("ascii")
                ).split(b";")[0].decode("charmap"))
    renderable = RenderableForm(
        fieldValues.form,
        session,
        "/".join(
            segment.decode("utf-8", errors="replace")
            for segment in request.prepath),
        request.method,
        enctype,
        "utf-8",
        fieldValues.prevalidationValues,
        fieldValues.validationErrors,
    )

    return Element(TagLoader(renderable))
예제 #15
0
    def _applyToRequest(self, request: IRequest) -> Any:
        """
        Apply this L{Response} to the given L{IRequest}, setting its response
        code and headers.

        Private because:

            - this should only ever be applied by Klein, and

            - hopefully someday soon this will be replaced with something that
              actually creates a txrequest-style response object.
        """
        request.setResponseCode(self.code)
        for headerName, headerValueOrValues in self.headers.items():
            if not isinstance(headerValueOrValues, (text_type, bytes)):
                headerValues = headerValueOrValues
            else:
                headerValues = [headerValueOrValues]
            request.responseHeaders.setRawHeaders(headerName, headerValues)
        return self.body
예제 #16
0
    async def hostname(self, request: IRequest, name: str) -> KleinRenderable:
        """
        Hostname lookup resource.

        Performs a lookup on the given name and responds with the resulting
        address.

        :param request: The request to respond to.

        :param name: A host name.
        """
        try:
            address = await getHostByName(name)
        except DNSNameError:
            request.setResponseCode(http.NOT_FOUND)
            return "no such host"
        except DNSLookupError:
            request.setResponseCode(http.NOT_FOUND)
            return "lookup error"

        return address
예제 #17
0
def redirect(
    request: IRequest, location: URL, origin: Optional[str] = None
) -> KleinRenderable:
    """
    Perform a redirect.
    """
    if origin is not None:
        try:
            location = location.set(origin, request.uri.decode("utf-8"))
        except ValueError:
            return badRequestResponse(request, "Invalid origin URI")

    log.debug(
        "Redirect {source} -> {destination}",
        source=request.uri.decode("utf-8"), destination=location.asText(),
    )
    url = location.asText().encode("utf-8")

    request.setHeader(HeaderName.contentType.value, ContentType.html.value)
    request.setHeader(HeaderName.location.value, url)
    request.setResponseCode(http.FOUND)

    return RedirectPage(location=location)
예제 #18
0
def redirect(request: IRequest,
             location: URL,
             origin: Optional[str] = None) -> KleinRenderable:
    """
    Perform a redirect.
    """
    if origin is not None:
        try:
            location = location.set(origin, request.uri.decode("utf-8"))
        except ValueError:
            return badRequestResponse(request, "Invalid origin URI")

    log.debug(
        "Redirect {source} -> {destination}",
        source=request.uri.decode("utf-8"),
        destination=location.asText(),
    )
    url = location.asText().encode("utf-8")

    request.setHeader(HeaderName.contentType.value, ContentType.html.value)
    request.setHeader(HeaderName.location.value, url)
    request.setResponseCode(http.FOUND)

    return RedirectPage(location)
예제 #19
0
파일: _form.py 프로젝트: shippool/klein
 def render(self, request: IRequest) -> bytes:
     """
     For all HTTP methods, return a 403.
     """
     request.setResponseCode(FORBIDDEN, b"FAILURECSRF")
     return ("CSRF TOKEN FAILURE: " + self.message).encode("utf-8")
예제 #20
0
 def render(self, request: IRequest) -> bytes:
     request.setResponseCode(UNAUTHORIZED)
     return "{} DENIED".format(qual(self._interface)).encode("utf-8")
예제 #21
0
파일: _resource.py 프로젝트: dantoac/klein
    def render(self, request: IRequest) -> "KleinRenderable":
        # Stuff we need to know for the mapper.
        try:
            (
                url_scheme,
                server_name,
                server_port,
                path_info,
                script_name,
            ) = _extractURLparts(request)
        except _URLDecodeError as e:
            for what, fail in e.errors:
                log.err(fail, f"Invalid encoding in {what}.")
            request.setResponseCode(400)
            return b"Non-UTF-8 encoding in URL."

        # Bind our mapper.
        mapper = self._app.url_map.bind(
            server_name,
            script_name,
            path_info=path_info,
            default_method=request.method,
            url_scheme=url_scheme,
        )
        # Make the mapper available to the view.
        kleinRequest = IKleinRequest(request)
        kleinRequest.mapper = mapper

        # Make sure we'll notice when the connection goes away unambiguously.
        request_finished = [False]

        def _finish(result: object) -> None:
            request_finished[0] = True

        def _execute() -> Deferred:
            # Actually doing the match right here. This can cause an exception
            # to percolate up. If that happens it will be handled below in
            # processing_failed, either by a user-registered error handler or
            # one of our defaults.
            (rule, kwargs) = mapper.match(return_rule=True)
            endpoint = rule.endpoint

            # Try pretty hard to fix up prepath and postpath.
            segment_count = self._app.endpoints[
                endpoint
            ].segment_count  # type: ignore[union-attr]
            request.prepath.extend(request.postpath[:segment_count])
            request.postpath = request.postpath[segment_count:]

            request.notifyFinish().addBoth(_finish)

            # Standard Twisted Web stuff. Defer the method action, giving us
            # something renderable or printable. Return NOT_DONE_YET and set up
            # the incremental renderer.
            d = maybeDeferred(
                self._app.execute_endpoint, endpoint, request, **kwargs
            )

            request.notifyFinish().addErrback(lambda _: d.cancel())

            return d

        d = maybeDeferred(_execute)

        # type note: returns Any because Response._applyToRequest returns Any
        def process(r: object) -> Any:
            """
            Recursively go through r and any child Resources until something
            returns an IRenderable, then render it and let the result of that
            bubble back up.
            """
            if isinstance(r, Response):
                r = r._applyToRequest(request)

            if IResource.providedBy(r):
                request.render(getChildForRequest(r, request))
                return StandInResource

            if IRenderable.providedBy(r):
                renderElement(request, r)
                return StandInResource

            return r

        d.addCallback(process)

        def processing_failed(
            failure: Failure, error_handlers: "ErrorHandlers"
        ) -> Deferred:
            # The failure processor writes to the request.  If the
            # request is already finished we should suppress failure
            # processing.  We don't return failure here because there
            # is no way to surface this failure to the user if the
            # request is finished.
            if request_finished[0]:
                if not failure.check(defer.CancelledError):
                    log.err(failure, "Unhandled Error Processing Request.")
                return

            # If there are no more registered handlers, apply some defaults
            if len(error_handlers) == 0:
                if failure.check(HTTPException):
                    he = failure.value
                    request.setResponseCode(he.code)
                    resp = he.get_response({})

                    for header, value in resp.headers:
                        request.setHeader(
                            ensure_utf8_bytes(header), ensure_utf8_bytes(value)
                        )

                    return ensure_utf8_bytes(b"".join(resp.iter_encoded()))
                else:
                    request.processingFailed(failure)
                    return

            error_handler = error_handlers[0]

            # Each error handler is a tuple of
            # (list_of_exception_types, handler_fn)
            if failure.check(*error_handler[0]):
                d = maybeDeferred(
                    self._app.execute_error_handler,
                    error_handler[1],
                    request,
                    failure,
                )

                d.addCallback(process)

                return d.addErrback(processing_failed, error_handlers[1:])

            return processing_failed(failure, error_handlers[1:])

        d.addErrback(processing_failed, self._app._error_handlers)

        def write_response(r: object) -> None:
            if r is not StandInResource:
                if isinstance(r, str):
                    r = r.encode("utf-8")

                if (r is not None) and (r != NOT_DONE_YET):
                    request.write(r)

                if not request_finished[0]:
                    request.finish()

        d.addCallback(write_response)
        d.addErrback(log.err, _why="Unhandled Error writing response")

        return server.NOT_DONE_YET