Example #1
0
    def format_error(error):
        if isinstance(error, GraphQLLocatedError):
            error = error.original_error

        formatted_error = format_graphql_error(error)
        graphql_error = OrderedDict([('type', error.__class__.__name__)])

        graphql_error['extensions'] = {}
        graphql_error['message'] = formatted_error['message']

        if isinstance(error, exceptions.GraphQLError):
            if error.extensions:
                graphql_error['extensions'] = error.extensions

            graphql_error['extensions']['code'] = error.code
        else:
            graphql_error['extensions']['code'] = 'ERROR'

        if 'location' in formatted_error:
            graphql_error['location'] = formatted_error['location']

        if error.__traceback__ is not None:
            info = error.__traceback__.tb_frame.f_locals.get('info')

            if info is not None:
                graphql_error['path'] = [info.field_name]
                graphql_error['operation'] = info.operation.operation

        if settings.DEBUG:
            graphql_error['extensions'][
                'stacktraceback'] = traceback.format_list(
                    traceback.extract_tb(error.__traceback__))

        return graphql_error
Example #2
0
    def format_error(error):
        if isinstance(error, GraphQLError):
            result = format_graphql_error(error)
        else:
            result = {"message": str(error)}

        exc = error
        while isinstance(exc, GraphQLError) and hasattr(exc, "original_error"):
            exc = exc.original_error

        logger.error("Exception information:", exc_info=exc)

        if settings.DEBUG:
            lines = []

            if isinstance(exc, BaseException):
                for line in traceback.format_exception(
                    type(exc), exc, exc.__traceback__
                ):
                    lines.extend(line.rstrip().splitlines())

            result["extensions"] = {
                "exception": {"code": type(exc).__name__, "stacktrace ": lines}
            }
        return result
Example #3
0
    def format_error(cls, error):
        if isinstance(error, GraphQLError):
            result = format_graphql_error(error)
        else:
            result = {"message": str(error)}

        exc = error
        while isinstance(exc, GraphQLError) and hasattr(exc, "original_error"):
            exc = exc.original_error

        if isinstance(exc, cls.HANDLED_EXCEPTIONS):
            handled_errors_logger.error("A query had an error", exc_info=exc)
        else:
            unhandled_errors_logger.error("A query failed unexpectedly",
                                          exc_info=exc)

        result["extensions"] = {"exception": {"code": type(exc).__name__}}
        if settings.DEBUG:
            lines = []

            if isinstance(exc, BaseException):
                for line in traceback.format_exception(type(exc), exc,
                                                       exc.__traceback__):
                    lines.extend(line.rstrip().splitlines())
            result["extensions"]["exception"]["stacktrace"] = lines
        return result
Example #4
0
    async def handle_graphql(self, request: Request) -> Response:
        if request.method in ("GET", "HEAD"):
            if "text/html" in request.headers.get("Accept", ""):
                if not self.graphiql:
                    return PlainTextResponse(
                        "Not Found", status_code=status.HTTP_404_NOT_FOUND)
                return await self.handle_graphiql(request)

            data = request.query_params  # type: typing.Mapping[str, typing.Any]

        elif request.method == "POST":
            content_type = request.headers.get("Content-Type", "")

            if "application/json" in content_type:
                data = await request.json()
            elif "application/graphql" in content_type:
                body = await request.body()
                text = body.decode()
                data = {"query": text}
            elif "query" in request.query_params:
                data = request.query_params
            else:
                return PlainTextResponse(
                    "Unsupported Media Type",
                    status_code=status.HTTP_415_UNSUPPORTED_MEDIA_TYPE,
                )

        else:
            return PlainTextResponse(
                "Method Not Allowed",
                status_code=status.HTTP_405_METHOD_NOT_ALLOWED)

        try:
            query = data["query"]
            variables = data.get("variables")
            operation_name = data.get("operationName")
        except KeyError:
            return PlainTextResponse(
                "No GraphQL query found in the request",
                status_code=status.HTTP_400_BAD_REQUEST,
            )

        background = BackgroundTasks()
        context = {"request": request, "background": background}

        result = await self.execute(query,
                                    variables=variables,
                                    context=context,
                                    operation_name=operation_name)
        error_data = ([format_graphql_error(err)
                       for err in result.errors] if result.errors else None)
        response_data = {"data": result.data}
        if error_data:
            response_data["errors"] = error_data
        status_code = (status.HTTP_400_BAD_REQUEST
                       if result.errors else status.HTTP_200_OK)

        return JSONResponse(response_data,
                            status_code=status_code,
                            background=background)
Example #5
0
def format_error(error):
    if hasattr(error, 'original_error'):
        err = error.original_error
        formatted_error = {}
        if isinstance(err, AppException):
            if isinstance(err, InternalErrorException):
                log_error(err.detail, exc_info=(err.__class__, err, err.stack))
            formatted_error['message'] = err.detail
            formatted_error['code'] = err.code
        else:
            log_error('Exception during GraphQL method execution.',
                      exc_info=(err.__class__, err, err.stack))
            formatted_error['message'] = 'Internal error.'
            formatted_error['code'] = InternalErrorException.code

        if hasattr(err, 'errors') and err.errors is not None:
            formatted_error['errors'] = [{
                'key': to_camel_case(x.key),
                'message': x.message
            } for x in err.errors]
        if error.locations is not None:
            formatted_error['locations'] = [{
                'line': loc.line,
                'column': loc.column
            } for loc in error.locations]
        return formatted_error
    if isinstance(error, GraphQLError):
        return format_graphql_error(error)
    return {'message': str(error)}
Example #6
0
def process_result(result: ExecutionResult) -> GraphQLHTTPResponse:
    data: GraphQLHTTPResponse = {"data": result.data}

    if result.errors:
        data["errors"] = [format_graphql_error(err) for err in result.errors]

    return data
Example #7
0
 def format_error(error):
     try:
         if isinstance(error, GraphQLLocatedError):
             return format_located_error(error)
         if isinstance(error, GraphQLSyntaxError):
             return format_graphql_error(error)
     except Exception as e:
         return format_internal_error(e)
Example #8
0
def format_error(error):
    if isinstance(error, GraphQLError):
        return format_graphql_error(error)

    return {
        'message': '{}: {}'.format(error.__class__.__name__,
                                   six.text_type(error))
    }
Example #9
0
 def format_error(error):
     # Why don't other people care about stack traces? It's absurd to have add this myself
     trace = traceback.format_exception(etype=type(error),
                                        value=error,
                                        tb=error.__traceback__)
     if isinstance(error, GraphQLError):
         return R.merge(dict(trace=trace), format_graphql_error(error))
     return {"message": six.text_type(error), "trace": trace}
Example #10
0
    async def handle_subscribe(self, message: SubscribeMessage) -> None:
        if not self.connection_acknowledged:
            await self.close(code=4401, reason="Unauthorized")
            return

        if message.id in self.subscriptions.keys():
            reason = f"Subscriber for {message.id} already exists"
            await self.close(code=4409, reason=reason)
            return

        context = await self.get_context()
        root_value = await self.get_root_value()

        if self.debug:  # pragma: no cover
            pretty_print_graphql_operation(
                message.payload.operationName,
                message.payload.query,
                message.payload.variables,
            )

        try:
            result_source = await self.schema.subscribe(
                query=message.payload.query,
                variable_values=message.payload.variables,
                operation_name=message.payload.operationName,
                context_value=context,
                root_value=root_value,
            )
        except GraphQLError as error:
            payload = [format_graphql_error(error)]
            await self.send_message(
                ErrorMessage(id=message.id, payload=payload))
            self.schema.process_errors([error])
            return

        if isinstance(result_source, GraphQLExecutionResult):
            assert result_source.errors
            payload = [format_graphql_error(result_source.errors[0])]
            await self.send_message(
                ErrorMessage(id=message.id, payload=payload))
            self.schema.process_errors(result_source.errors)
            return

        handler = self.handle_async_results(result_source, message.id)
        self.subscriptions[message.id] = result_source
        self.tasks[message.id] = asyncio.create_task(handler)
def error_format(exception):
    if isinstance(exception, ExecutionError):
        return [{"message": e} for e in exception.errors]
    elif isinstance(exception, GraphQLError):
        return [format_graphql_error(exception)]
    elif isinstance(exception, web.HTTPError):
        return [{"message": exception.log_message, "reason": exception.reason}]
    else:
        return [{"message": "Unknown server error"}]
Example #12
0
 def error_format(exception):
     if isinstance(exception, ExecutionError):
         return [{'message': e} for e in exception.errors]
     elif isinstance(exception, GraphQLError):
         return [format_graphql_error(exception)]
     elif isinstance(exception, web.HTTPError):
         return [{'message': exception.log_message}]
     else:
         return [{'message': 'Unknown server error'}]
Example #13
0
    async def handle_graphql(self, request: Request) -> Response:
        if request.method == "GET":
            if "text/html" in request.headers.get("Accept", ""):
                return await self.handle_graphiql(request)

            data = request.query_params  # type: typing.Mapping[str, typing.Any]

        elif request.method == "POST":
            content_type = request.headers.get("Content-Type", "")

            if "application/json" in content_type:
                data = await request.json()
            elif "application/graphql" in content_type:
                body = await request.body()
                text = body.decode()
                data = {"query": text}
            elif "query" in request.query_params:
                data = request.query_params
            elif "multipart/form-data" in content_type:
                form = await request.form()
                data = {}
                file_map = json.loads(form["file_map"])
                data = {"query": form["query"]}
                variables = json.loads(form["variables"])

                for key, path in file_map.items():
                    variables[path] = await form[key].read()

                data["variables"] = variables
            else:
                return PlainTextResponse(
                    "Unsupported Media Type",
                    status_code=status.HTTP_415_UNSUPPORTED_MEDIA_TYPE,
                )

        else:
            return PlainTextResponse(
                "Method Not Allowed",
                status_code=status.HTTP_405_METHOD_NOT_ALLOWED)

        try:
            query = data["query"]
            variables = data.get("variables")
            operation_name = data.get("operationName")
        except KeyError:
            return PlainTextResponse(
                "No GraphQL query found in the request",
                status_code=status.HTTP_400_BAD_REQUEST,
            )

        result = await self.execute(query, variables)
        error_data = ([format_graphql_error(err)
                       for err in result.errors] if result.errors else None)
        response_data = {"data": result.data, "errors": error_data}
        status_code = (status.HTTP_400_BAD_REQUEST
                       if result.errors else status.HTTP_200_OK)
        return JSONResponse(response_data, status_code=status_code)
Example #14
0
    async def start_subscription(self, data, operation_id: str,
                                 websocket: WebSocket):
        query = data["query"]
        variables = data.get("variables")
        operation_name = data.get("operation_name")

        if self.debug:
            pretty_print_graphql_operation(operation_name, query, variables)

        data = await subscribe(self.schema,
                               query,
                               variable_values=variables,
                               operation_name=operation_name)

        try:
            async for result in data:
                payload = {"data": result.data}

                if result.errors:
                    payload["errors"] = [
                        format_graphql_error(err) for err in result.errors
                    ]
                await self._send_message(websocket, GQL_DATA, payload,
                                         operation_id)
        except Exception as error:
            if not isinstance(error, GraphQLError):
                error = GraphQLError(str(error), original_error=error)

            await self._send_message(
                websocket,
                GQL_DATA,
                {
                    "data": None,
                    "errors": [format_graphql_error(error)]
                },
                operation_id,
            )

        await self._send_message(websocket, GQL_COMPLETE, None, operation_id)

        if self._keep_alive_task:
            self._keep_alive_task.cancel()

        await websocket.close()
Example #15
0
def error_format(exception):
    if isinstance(exception, ExecutionError):
        return [{'message': e} for e in exception.errors]
    elif isinstance(exception, GraphQLError):
        return [format_graphql_error(exception)]
    elif isinstance(exception, web.HTTPError):
        return [{'message': exception.log_message,
                 'reason': exception.reason}]
    else:
        return [{'message': 'Unknown server error'}]
Example #16
0
    async def handle_async_results(self, results: typing.AsyncGenerator,
                                   operation_id: str, websocket: WebSocket):
        try:
            async for result in results:
                payload = {"data": result.data}

                if result.errors:
                    payload["errors"] = [
                        format_graphql_error(err) for err in result.errors
                    ]

                await self._send_message(websocket, GQL_DATA, payload,
                                         operation_id)
        except asyncio.CancelledError:
            # CancelError will be received when the client disconnects
            # and the `handle_async_results` task gets cancelled

            # Suppress the error and prevent sending any message, since the
            # client was disconnected now
            return

        except Exception as error:
            if not isinstance(error, GraphQLError):
                error = GraphQLError(str(error), original_error=error)

            await self._send_message(
                websocket,
                GQL_DATA,
                {
                    "data": None,
                    "errors": [format_graphql_error(error)]
                },
                operation_id,
            )

        if (websocket.client_state != WebSocketState.DISCONNECTED and
                websocket.application_state != WebSocketState.DISCONNECTED):
            try:
                await self._send_message(websocket, GQL_COMPLETE, None,
                                         operation_id)
            except ConnectionClosedError:
                pass
Example #17
0
async def get_http_response(
    request: Request, execute: typing.Callable, graphiql: bool
) -> Response:
    if request.method == "GET":
        if not graphiql:
            return HTMLResponse(status_code=status.HTTP_404_NOT_FOUND)

        html = get_graphiql_html()
        return HTMLResponse(html)

    if request.method == "POST":
        content_type = request.headers.get("Content-Type", "")

        if "application/json" in content_type:
            data = await request.json()
        else:
            return PlainTextResponse(
                "Unsupported Media Type",
                status_code=status.HTTP_415_UNSUPPORTED_MEDIA_TYPE,
            )
    else:
        return PlainTextResponse(
            "Method Not Allowed",
            status_code=status.HTTP_405_METHOD_NOT_ALLOWED,
        )

    try:
        query = data["query"]
        variables = data.get("variables")
        operation_name = data.get("operationName")
    except KeyError:
        return PlainTextResponse(
            "No GraphQL query found in the request",
            status_code=status.HTTP_400_BAD_REQUEST,
        )

    context = {"request": request}

    result = await execute(
        query,
        variables=variables,
        context=context,
        operation_name=operation_name,
    )

    response_data = {"data": result.data}

    if result.errors:
        response_data["errors"] = [
            format_graphql_error(err) for err in result.errors
        ]

    return JSONResponse(response_data, status_code=status.HTTP_200_OK)
Example #18
0
    def execute_graphql_subscription(
        self,
        websocket: WebSocket,
        operation_id: str,
        query: str,
        variables: Optional[Dict[str, Any]],
        operation_name: Optional[str],
    ) -> Tuple[Optional[Task], Optional[Dict[str, Any]]]:
        request_context = self.make_request_context(websocket)
        try:
            async_result = self._graphql_schema.execute(
                query,
                variables=variables,
                operation_name=operation_name,
                context=request_context,
                allow_subscriptions=True,
            )
        except GraphQLError as error:
            error_payload = format_graphql_error(error)
            return None, error_payload

        if isinstance(async_result, ExecutionResult):
            if not async_result.errors:
                check.failed(
                    f"Only expect non-async result on error, got {async_result}"
                )
            error_payload = format_graphql_error(
                async_result.errors[0])  # type: ignore
            return None, error_payload

        # in the future we should get back async gen directly, back compat for now
        disposable, async_gen = _disposable_and_async_gen_from_obs(
            async_result, get_event_loop())
        task = get_event_loop().create_task(
            _handle_async_results(async_gen, operation_id, websocket))
        task.add_done_callback(lambda _: disposable.dispose())

        return task, None
Example #19
0
    async def handle_start(self, message: OperationMessage) -> None:
        operation_id = message["id"]
        payload = cast(StartPayload, message["payload"])
        query = payload["query"]
        operation_name = payload.get("operationName")
        variables = payload.get("variables")

        context = await self.get_context()
        root_value = await self.get_root_value()

        if self.debug:
            pretty_print_graphql_operation(operation_name, query, variables)

        try:
            result_source = await self.schema.subscribe(
                query=query,
                variable_values=variables,
                operation_name=operation_name,
                context_value=context,
                root_value=root_value,
            )
        except GraphQLError as error:
            error_payload = format_graphql_error(error)
            await self.send_message(GQL_ERROR, operation_id, error_payload)
            self.schema.process_errors([error])
            return

        if isinstance(result_source, GraphQLExecutionResult):
            assert result_source.errors
            error_payload = format_graphql_error(result_source.errors[0])
            await self.send_message(GQL_ERROR, operation_id, error_payload)
            self.schema.process_errors(result_source.errors)
            return

        self.subscriptions[operation_id] = result_source
        result_handler = self.handle_async_results(result_source, operation_id)
        self.tasks[operation_id] = asyncio.create_task(result_handler)
Example #20
0
    async def handle_async_results(
        self,
        result_source: AsyncGenerator,
        operation_id: str,
    ) -> None:
        try:
            async for result in result_source:
                if result.errors:
                    error_payload = [
                        format_graphql_error(err) for err in result.errors
                    ]
                    error_message = ErrorMessage(id=operation_id,
                                                 payload=error_payload)
                    await self.send_message(error_message)
                    self.schema.process_errors(result.errors)
                    return
                else:
                    next_payload = {"data": result.data}
                    next_message = NextMessage(id=operation_id,
                                               payload=next_payload)
                    await self.send_message(next_message)
        except asyncio.CancelledError:
            # CancelledErrors are expected during task cleanup.
            return
        except Exception as error:
            # GraphQLErrors are handled by graphql-core and included in the
            # ExecutionResult
            error = GraphQLError(str(error), original_error=error)
            error_payload = [format_graphql_error(error)]
            error_message = ErrorMessage(id=operation_id,
                                         payload=error_payload)
            await self.send_message(error_message)
            self.schema.process_errors([error])
            return

        await self.send_message(CompleteMessage(id=operation_id))
Example #21
0
    def dispatch(self, request, *args, **kwargs):

        if request.method.lower() not in ("get", "post"):
            return HttpResponseNotAllowed(
                ["GET", "POST"],
                "GraphQL only supports GET and POST requests.")

        if "text/html" in request.META.get("HTTP_ACCEPT", ""):
            return render(
                request,
                "graphql/playground.html",
                {"REQUEST_PATH": request.get_full_path()},
            )

        data = json.loads(request.body)

        try:
            query = data["query"]
            variables = data.get("variables")
            operation_name = data.get("operationName")
        except KeyError:
            return HttpResponseBadRequest(
                "No GraphQL query found in the request")

        context = {"request": request}

        result = graphql_sync(
            self.schema,
            query,
            variable_values=variables,
            context_value=context,
            operation_name=operation_name,
        )

        response_data = {"data": result.data}

        if result.errors:
            response_data["errors"] = [
                format_graphql_error(err) for err in result.errors
            ]
            self._capture_sentry_exceptions(result.errors)

        return JsonResponse(response_data, status=200)
Example #22
0
    def format_error(error):
        if isinstance(error, GraphQLError):
            result = format_graphql_error(error)
        else:
            result = {"message": str(error)}

        exc = error
        while isinstance(exc, GraphQLError) and hasattr(exc, "original_error"):
            exc = exc.original_error

        logger.error("Exception information:", exc_info=exc)

        if settings.DEBUG:
            lines = []
            for line in traceback.format_exception(type(exc), exc, exc.__traceback__):
                lines.extend(line.rstrip().splitlines())
            result["extensions"] = {
                "exception": {"code": type(exc).__name__, "stacktrace ": lines}
            }
        return result
Example #23
0
 def format_error(original_error):
     error = getattr(original_error, 'original_error', original_error)
     #        sentry_sdk.capture_exception(original_error)
     if isinstance(original_error, GraphQLLocatedError) or isinstance(
             original_error, GraphQLError):
         if isinstance(error, ValidationError):
             return format_internal_error(error, code=400)
         if isinstance(error, GrapheneDjangoJWTBaseException):
             return format_internal_error(error)
         if settings.DEBUG:
             return format_internal_error(error)
         else:
             return format_internal_error(BaseException())
     if isinstance(error, GraphQLSyntaxError):
         return format_graphql_error(error)
     else:
         if settings.DEBUG:
             return format_internal_error(error)
         else:
             return format_internal_error(BaseException())
Example #24
0
    def dispatch(self, request, *args, **kwargs):
        if request.method.lower() not in ("get", "post"):
            return HttpResponseNotAllowed(
                ["GET", "POST"],
                "GraphQL only supports GET and POST requests.")

        if "text/html" in request.META.get("HTTP_ACCEPT", ""):
            if not self.graphiql:
                raise Http404("GraphiQL has been disabled")

            return self._render_graphiql(request)

        data = json.loads(request.body)

        try:
            query = data["query"]
            variables = data.get("variables")
            operation_name = data.get("operationName")
        except KeyError:
            return HttpResponseBadRequest(
                "No GraphQL query found in the request")

        context = {"request": request}

        result = graphql_sync(
            self.schema,
            query,
            root_value=self.get_root_value(),
            variable_values=variables,
            context_value=context,
            operation_name=operation_name,
        )

        response_data = {"data": result.data}

        if result.errors:
            response_data["errors"] = [
                format_graphql_error(err) for err in result.errors
            ]

        return JsonResponse(response_data)
Example #25
0
 def format_error(error):
     if isinstance(error, GraphQLError):
         result = format_graphql_error(error)
     else:
         result = {'message': str(error)}
     if settings.DEBUG:
         exc = error
         while (isinstance(exc, GraphQLError)
                and hasattr(exc, 'original_error')):
             exc = exc.original_error
         lines = []
         for line in traceback.format_exception(type(exc), exc,
                                                exc.__traceback__):
             lines.extend(line.rstrip().splitlines())
         result['extensions'] = {
             'exception': {
                 'code': type(exc).__name__,
                 'stacktrace ': lines
             }
         }
     return result
Example #26
0
    def dispatch_request(self):
        if "text/html" in request.environ.get("HTTP_ACCEPT", ""):
            if not self.graphiql:
                abort(404)

            template = render_graphiql_page()
            return self.render_template(request, template=template)

        data = request.json

        try:
            query = data["query"]
            variables = data.get("variables")
            operation_name = data.get("operationName")

        except KeyError:
            return Response("No valid query was provided for the request", 400)

        context = {"request": request}

        result = self.schema.execute_sync(
            query,
            variable_values=variables,
            context_value=context,
            operation_name=operation_name,
            root_value=self.root_value,
        )

        response_data = {"data": result.data}

        if result.errors:
            response_data["errors"] = [
                format_graphql_error(err) for err in result.errors
            ]

        return Response(
            json.dumps(response_data),
            status=400 if result.errors else 200,
            content_type="application/json",
        )
Example #27
0
    def format_error(error):
        if isinstance(error, GraphQLLocatedError):
            error = error.original_error

        formatted_error = format_graphql_error(error)
        graphql_error = OrderedDict([('type', error.__class__.__name__)])

        if extensions_settings.EXT_SHOW_ERROR_MESSAGE_HANDLER(error):
            graphql_error['message'] = formatted_error['message']
        else:
            # Internal errors must be masked
            graphql_error['message'] = _('Internal server error')

        if isinstance(error, exceptions.GraphQLError):
            graphql_error['code'] = error.code

            if error.error_data:
                graphql_error['data'] = error.error_data
        else:
            graphql_error['code'] = 'error'

        if 'location' in formatted_error:
            graphql_error['location'] = formatted_error['location']

        if error.__traceback__ is not None:
            info = error.__traceback__.tb_frame.f_locals.get('info')

            if info is not None:
                graphql_error['path'] = [info.field_name]
                graphql_error['operation'] = info.operation.operation

        if settings.DEBUG:
            graphql_error['trace'] = traceback.format_list(
                traceback.extract_tb(error.__traceback__))

        return graphql_error
    def format_error(error):
        if isinstance(error, GraphQLError):
            return format_graphql_error(error)

        return {'message': six.text_type(error)}
Example #29
0
def error_formatter(error):
    formatted = format_graphql_error(error)
    if hasattr(error, 'original_error'):
        if isinstance(error.original_error, GraphExecutionError):
            formatted['code'] = error.original_error.code
    return formatted
Example #30
0
 def handle_graphql_errors(self, errors):
     return [format_graphql_error(err) for err in errors]
Example #31
0
def default_format_error(error):
    if isinstance(error, GraphQLError):
        return format_graphql_error(error)
    return {"message": str(error)}
Example #32
0
def format_error(error):
    if isinstance(error, GraphQLError):
        return format_graphql_error(error)
    else:
        return {'message': str(error)}
Example #33
0
    def format_error(error):
        if isinstance(error, GraphQLError):
            return format_graphql_error(error)

        return {'message': six.text_type(error)}
Example #34
0
def format_error(error):
    if isinstance(error, GraphQLError):
        return format_graphql_error(error)

    return {'message': '{}: {}'.format(
        error.__class__.__name__, six.text_type(error))}