예제 #1
0
파일: app.py 프로젝트: mplanchard/Kyoukai
    async def handle_http_error(self, err: HTTPException, protocol,
                                ctx: HTTPRequestContext):
        """
        Handle a :class:`kyoukai.exc.HTTPException`.

        This will invoke the appropriate error handler as registered in the blueprint of the route, if we can.
        Otherwise, it will invoke the default error handler.
        """
        code = err.code
        bp = err.blueprint or self.root

        # Get the error handler.
        error_handler = bp.get_errorhandler(code)
        if not error_handler:
            # Since there's no special error handler derived for this code, return a basic Response.
            # If it's a 500 and we're in debug mode, format the traceback.
            if err.code == 500 and self.debug:
                # Use the Kyoukai debugger.
                should_err, r = self._debugger.debug(ctx, err)
                protocol.handle_resp(r)
                return should_err
            else:
                body = str(code)

            if err.response is None:
                resp = Response(code, body)
            else:
                resp = err.response

            resp.request = ctx.request
        else:
            # Invoke the error handler specified.
            try:
                resp = wrap_response(
                    await error_handler.invoke(ctx, exception=err),
                    self.response_cls)
            except Exception:
                self.logger.error(
                    "Unhandled exception in error handler:\n {}".format(
                        ''.join(traceback.format_exc())))
                resp = wrap_response("500", self.response_cls)

            resp.request = ctx.request

        protocol.handle_resp(resp)

        # Check if we should close the connection.
        if hasattr(ctx.request, "should_keep_alive"):
            if not ctx.request.should_keep_alive:
                protocol.close()
        else:
            # If it's that bad, just close it anyway.
            protocol.close()

        return True
예제 #2
0
파일: app.py 프로젝트: leofidus/OWAPI
async def jsonify(ctx, response: Response):
    """
    JSONify the response.
    """
    if isinstance(response.body, str):
        return response

    # json.dump the body.
    status_code = response.code
    if not any(response.body.values()):
        status_code = 404
    d = json.dumps(response.body)
    response.body = d
    response.headers["Content-Type"] = "application/json"
    response.code = status_code
    return response
예제 #3
0
    def write_response(self, response: Response):
        """
        Writes a :class:`Response` to the protocol

        :param response: The response to write.
        """
        data = response.to_bytes()
        self.write(data)
예제 #4
0
파일: app.py 프로젝트: Dizolivemint/OWAPI
async def jsonify(ctx, response: Response):
    """
    JSONify the response.
    """
    if isinstance(response.body, str):
        return response

    # json.dump the body.
    status_code = response.code
    if not any(response.body.values()):
        status_code = 404
    if ctx.request.args.get("format", "json") == "json_pretty":
        d = json.dumps(response.body, sort_keys=True, indent=4, separators=(',', ': '))
    else:
        d = json.dumps(response.body)
    response.body = d
    response.headers["Content-Type"] = "application/json"
    response.code = status_code
    return response
예제 #5
0
def wrap_response(response, response_cls=None):
    """
    Wrap up a response, if applicable.

    This allows Flask-like `return ""`.

    :param response: The tuple or otherwise object that is being wrapped.
    :param response_cls: The Response class that is being used.
    """
    # Import inside here to prevent circular imports.
    if response_cls is None:
        from kyoukai.response import Response
    else:
        Response = response_cls

    if response is None:
        r = Response(204, "", {})
    elif isinstance(response, tuple):
        if len(response) == 1:
            # Only body.
            r = Response(200, response[0], {})
        elif len(response) == 2:
            # Body and code.
            r = Response(response[1], response[0], {})
        elif len(response) == 3:
            # Body, code, headers.
            r = Response(response[1], response[0], response[2])
        else:
            # what
            raise HTTPException
    elif isinstance(response, Response):
        r = response
    else:

        r = Response(200, response, {})
    return r
예제 #6
0
파일: app.py 프로젝트: mplanchard/Kyoukai
    def render_template(self, filename: str, code=200, **kwargs) -> Response:
        """
        Render a template using the currently loaded rendering engine.

        Unlike :meth:`Kyoukai.render`, this returns a :class:`Response` object.

        :param filename: The filename of the template to load and render.
        :type filename: str

        :param code: The response code to add into the Response.

        :param kwargs: Additional arguments to pass to the template renderer.
                These are directly passed to :meth:`mako.template.Template.render` to render the template.

        :return: A :class:`Response` object with the rendered template.
        """
        data = self.render(filename, **kwargs)
        # Wrap it in a response.
        return Response(code, data, headers={"Content-Type": "text/html"})
예제 #7
0
파일: app.py 프로젝트: mplanchard/Kyoukai
    def get_static(self, filename: str) -> Response:
        """
        Gets a file, using static, but returns a Response instead of the file handle.
        """
        content = self.get_static_file(filename)
        if not content:
            raise HTTPException(404)

        with content:
            path = self.get_static_path(filename)
            mimetype = mimetypes.guess_type(path)[0]
            if not mimetype:
                if _has_magic:
                    mimetype = magic.from_file(path, mime=True)
                    if isinstance(mimetype, bytes):
                        mimetype = mimetype.decode()
                else:
                    mimetype = "application/octet-stream"
            return Response(200,
                            body=content.read(),
                            headers={"Content-Type": mimetype})
예제 #8
0
async def root(ctx: HTTPRequestContext):
    return Response.redirect(
        "https://github.com/SunDwarf/OWAPI/blob/master/api.md")
예제 #9
0
    def debug(self, ctx: HTTPRequestContext,
              exc: Exception) -> typing.Tuple[bool, Response]:
        """
        Produces debug output for the application in a new template.
        """
        if not self.app.debug:
            return

        # Check the request's params.
        params = ctx.request.args

        debugger = params.get("__debugger__")
        if debugger == "yes":
            command = params.get("cmd")
            # Switch based on the command.
            if command is None:
                return Response(code=404, body="404")
            elif command == "resource":
                # Send a resource down the line.
                filename = params.get("f")
                # Get the __file__ of the werkzeug debugger.
                wz_f = os.path.dirname(debug.__file__)
                filename = os.path.join(wz_f, 'shared',
                                        os.path.basename(filename))
                # Guess the content type from the filename.
                mimetype = mimetypes.guess_type(
                    filename)[0] or 'application/octet-stream'
                if os.path.exists(filename):
                    with open(filename, 'rb') as f:
                        return False, Response(
                            body=f.read(),
                            code=200,
                            headers={"Content-Type": mimetype})
                else:
                    return False, Response(body="404", code=404)
            else:
                # It's a console command.
                frame = self.frames.get(int(ctx.request.args.get('frm')))
                if frame is None:
                    return False, Response(body="404", code=404)
                # Run the console command inside the frame.
                result = frame.console.eval(command)
                return False, Response(body=result,
                                       code=200,
                                       headers={"Content-Type": "text/html"})
        else:
            # Get the traceback, now.
            traceback = get_current_traceback(skip=0,
                                              show_hidden_frames=True,
                                              ignore_system_exceptions=False)
            for frame in traceback.frames:
                self.frames[frame.id] = frame
            self.tracebacks[traceback.id] = traceback
            # Render the base page.
            body = traceback.render_full(
                evalex=True,
                evalex_trusted=True,
            )
            r = Response(code=500,
                         body=body.encode(),
                         headers={"X-XSS-Protection": "0"})
            return True, r