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")
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")
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""
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")
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")
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""
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."
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")
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")
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)
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)
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)
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)
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))
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
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
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)
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)
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")
def render(self, request: IRequest) -> bytes: request.setResponseCode(UNAUTHORIZED) return "{} DENIED".format(qual(self._interface)).encode("utf-8")
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