Esempio n. 1
0
    protected static async Task <IBatchQueryResult> ExecuteOperationBatchAsync(
        HttpContext context,
        IRequestExecutor requestExecutor,
        IHttpRequestInterceptor requestInterceptor,
        IServerDiagnosticEvents diagnosticEvents,
        GraphQLRequest request,
        IReadOnlyList <string> operationNames)
    {
        diagnosticEvents.StartOperationBatchRequest(context, request, operationNames);

        var requestBatch = new IReadOnlyQueryRequest[operationNames.Count];

        for (var i = 0; i < operationNames.Count; i++)
        {
            QueryRequestBuilder requestBuilder = QueryRequestBuilder.From(request);
            requestBuilder.SetOperation(operationNames[i]);

            await requestInterceptor.OnCreateAsync(
                context, requestExecutor, requestBuilder, context.RequestAborted);

            requestBatch[i] = requestBuilder.Create();
        }

        return(await requestExecutor.ExecuteBatchAsync(
                   requestBatch, cancellationToken : context.RequestAborted));
    }
Esempio n. 2
0
        private async Task HandleRequestAsync(HttpContext context)
        {
            // first we need to get the request executor to be able to execute requests.
            IRequestExecutor requestExecutor = await GetExecutorAsync(context.RequestAborted);

            IHttpRequestInterceptor requestInterceptor = requestExecutor.GetRequestInterceptor();
            IErrorHandler           errorHandler       = requestExecutor.GetErrorHandler();

            HttpStatusCode?  statusCode = null;
            IExecutionResult?result;

            try
            {
                // next we parse the GraphQL request.
                GraphQLRequest       request = _requestParser.ReadParamsRequest(context.Request.Query);
                GraphQLServerOptions?options = context.GetGraphQLServerOptions();
                result = await ExecuteSingleAsync(
                    context,
                    requestExecutor,
                    requestInterceptor,
                    request,
                    options is null or { AllowedGetOperations : AllowedGetOperations.Query }
                    ?_onlyQueries
                    : null);
            }
 /// <summary>
 /// Sets a custom <see cref="IHttpRequestInterceptor"/>
 /// </summary>
 /// <param name="httpRequestInterceptor">Interceptor for intercepting requests to Dynatrace/AppMon backends.</param>
 /// <returns><code>this</code></returns>
 public AbstractOpenKitBuilder WithHttpRequestInterceptor(IHttpRequestInterceptor httpRequestInterceptor)
 {
     if (httpRequestInterceptor != null)
     {
         HttpRequestInterceptor = httpRequestInterceptor;
     }
     return(this);
 }
    private async Task HandleRequestAsync(HttpContext context)
    {
        // first we need to get the request executor to be able to execute requests.
        IRequestExecutor requestExecutor = await GetExecutorAsync(context.RequestAborted);

        IHttpRequestInterceptor requestInterceptor = requestExecutor.GetRequestInterceptor();
        IErrorHandler           errorHandler       = requestExecutor.GetErrorHandler();

        context.Items[WellKnownContextData.RequestExecutor] = requestExecutor;

        HttpStatusCode?  statusCode = null;
        IExecutionResult?result;

        // next we parse the GraphQL request.
        GraphQLRequest request;

        using (_diagnosticEvents.ParseHttpRequest(context))
        {
            try
            {
                request = _requestParser.ReadParamsRequest(context.Request.Query);
            }
            catch (GraphQLRequestException ex)
            {
                // A GraphQL request exception is thrown if the HTTP request body couldn't be
                // parsed. In this case we will return HTTP status code 400 and return a
                // GraphQL error result.
                statusCode = HttpStatusCode.BadRequest;
                IReadOnlyList <IError> errors = errorHandler.Handle(ex.Errors);
                result = QueryResultBuilder.CreateError(errors);
                _diagnosticEvents.ParserErrors(context, errors);
                goto HANDLE_RESULT;
            }
            catch (Exception ex)
            {
                statusCode = HttpStatusCode.InternalServerError;
                IError error = errorHandler.CreateUnexpectedError(ex).Build();
                result = QueryResultBuilder.CreateError(error);
                _diagnosticEvents.HttpRequestError(context, error);
                goto HANDLE_RESULT;
            }
        }

        // after successfully parsing the request we now will attempt to execute the request.
        try
        {
            GraphQLServerOptions?options = context.GetGraphQLServerOptions();
            result = await ExecuteSingleAsync(
                context,
                requestExecutor,
                requestInterceptor,
                _diagnosticEvents,
                request,
                options is null or { AllowedGetOperations : AllowedGetOperations.Query }
                ?_onlyQueries
                : null);
        }
 public virtual Org.Apache.Http.Protocol.HttpProcessorBuilder AddLast(IHttpRequestInterceptor
                                                                      e)
 {
     if (e == null)
     {
         return(this);
     }
     GetRequestChainBuilder().AddLast(e);
     return(this);
 }
Esempio n. 6
0
        protected async Task <IExecutionResult> ExecuteSingleAsync(
            HttpContext context,
            IRequestExecutor requestExecutor,
            IHttpRequestInterceptor requestInterceptor,
            GraphQLRequest request)
        {
            QueryRequestBuilder requestBuilder = QueryRequestBuilder.From(request);

            await requestInterceptor.OnCreateAsync(
                context, requestExecutor, requestBuilder, context.RequestAborted);

            return(await requestExecutor.ExecuteAsync(
                       requestBuilder.Create(), context.RequestAborted));
        }
Esempio n. 7
0
 /// <summary>Adds this protocol interceptor to the tail of the protocol processing list.
 ///     </summary>
 /// <remarks>
 /// Adds this protocol interceptor to the tail of the protocol processing list.
 /// <p/>
 /// Please note this value can be overridden by the
 /// <see cref="SetHttpProcessor(Apache.Http.Protocol.HttpProcessor)">SetHttpProcessor(Apache.Http.Protocol.HttpProcessor)
 ///     </see>
 /// method.
 /// </remarks>
 public Apache.Http.Impl.Client.HttpClientBuilder AddInterceptorLast(IHttpRequestInterceptor
                                                                     itcp)
 {
     if (itcp == null)
     {
         return(this);
     }
     if (requestLast == null)
     {
         requestLast = new List <IHttpRequestInterceptor>();
     }
     requestLast.AddLast(itcp);
     return(this);
 }
Esempio n. 8
0
    protected static async Task <IExecutionResult> ExecuteSingleAsync(
        HttpContext context,
        IRequestExecutor requestExecutor,
        IHttpRequestInterceptor requestInterceptor,
        IServerDiagnosticEvents diagnosticEvents,
        GraphQLRequest request,
        OperationType[]?allowedOperations = null)
    {
        diagnosticEvents.StartSingleRequest(context, request);

        var requestBuilder = QueryRequestBuilder.From(request);

        requestBuilder.SetAllowedOperations(allowedOperations);

        await requestInterceptor.OnCreateAsync(
            context, requestExecutor, requestBuilder, context.RequestAborted);

        return(await requestExecutor.ExecuteAsync(
                   requestBuilder.Create(), context.RequestAborted));
    }
Esempio n. 9
0
        protected async Task <IBatchQueryResult> ExecuteBatchAsync(
            HttpContext context,
            IRequestExecutor requestExecutor,
            IHttpRequestInterceptor requestInterceptor,
            IReadOnlyList <GraphQLRequest> requests)
        {
            var requestBatch = new IReadOnlyQueryRequest[requests.Count];

            for (var i = 0; i < requests.Count; i++)
            {
                QueryRequestBuilder requestBuilder = QueryRequestBuilder.From(requests[0]);

                await requestInterceptor.OnCreateAsync(
                    context, requestExecutor, requestBuilder, context.RequestAborted);

                requestBatch[i] = requestBuilder.Create();
            }

            return(await requestExecutor.ExecuteBatchAsync(
                       requestBatch, cancellationToken : context.RequestAborted));
        }
Esempio n. 10
0
        private async Task HandleRequestAsync(HttpContext context)
        {
            // first we need to get the request executor to be able to execute requests.
            IRequestExecutor requestExecutor = await GetExecutorAsync(context.RequestAborted);

            IHttpRequestInterceptor requestInterceptor = requestExecutor.GetRequestInterceptor();
            IErrorHandler           errorHandler       = requestExecutor.GetErrorHandler();

            HttpStatusCode?  statusCode = null;
            IExecutionResult?result;

            try
            {
                // next we parse the GraphQL request.
                GraphQLRequest request = _requestParser.ReadParamsRequest(context.Request.Query);
                result = await ExecuteSingleAsync(
                    context, requestExecutor, requestInterceptor, request);
            }
            catch (GraphQLRequestException ex)
            {
                // A GraphQL request exception is thrown if the HTTP request body couldn't be
                // parsed. In this case we will return HTTP status code 400 and return a
                // GraphQL error result.
                statusCode = HttpStatusCode.BadRequest;
                result     = QueryResultBuilder.CreateError(errorHandler.Handle(ex.Errors));
            }
            catch (Exception ex)
            {
                statusCode = HttpStatusCode.InternalServerError;
                IError error = errorHandler.CreateUnexpectedError(ex).Build();
                result = QueryResultBuilder.CreateError(error);
            }

            // in any case we will have a valid GraphQL result at this point that can be written
            // to the HTTP response stream.
            Debug.Assert(result is not null, "No GraphQL result was created.");
            await WriteResultAsync(context.Response, result, statusCode, context.RequestAborted);
        }
Esempio n. 11
0
        private async Task HandleRequestAsync(
            HttpContext context,
            AllowedContentType contentType)
        {
            // first we need to get the request executor to be able to execute requests.
            IRequestExecutor requestExecutor = await GetExecutorAsync(context.RequestAborted);

            IHttpRequestInterceptor requestInterceptor = requestExecutor.GetRequestInterceptor();
            IErrorHandler           errorHandler       = requestExecutor.GetErrorHandler();

            HttpStatusCode?  statusCode = null;
            IExecutionResult?result;

            try
            {
                // next we parse the GraphQL request.
                IReadOnlyList <GraphQLRequest> requests =
                    await _requestParser.ReadJsonRequestAsync(
                        context.Request.Body, context.RequestAborted);

                switch (requests.Count)
                {
                // if the HTTP request body contains no GraphQL request structure the
                // whole request is invalid and we will create a GraphQL error response.
                case 0:
                {
                    statusCode = HttpStatusCode.BadRequest;
                    IError error = errorHandler.Handle(ErrorHelper.RequestHasNoElements());
                    result = QueryResultBuilder.CreateError(error);
                    break;
                }

                // if the HTTP request body contains a single GraphQL request and we do have
                // the batch operations query parameter specified we need to execute an
                // operation batch.
                //
                // An operation batch consists of a single GraphQL request document that
                // contains multiple operations. The batch operation query parameter
                // defines the order in which the operations shall be executed.
                case 1 when context.Request.Query.ContainsKey(_batchOperations):
                {
                    string operationNames = context.Request.Query[_batchOperations];

                    if (TryParseOperations(operationNames, out IReadOnlyList <string>?ops))
                    {
                        result = await ExecuteOperationBatchAsync(
                            context, requestExecutor, requestInterceptor, requests[0], ops);
                    }
                    else
                    {
                        IError error = errorHandler.Handle(ErrorHelper.InvalidRequest());
                        statusCode = HttpStatusCode.BadRequest;
                        result     = QueryResultBuilder.CreateError(error);
                    }
                    break;
                }

                // if the HTTP request body contains a single GraphQL request and
                // no batch query parameter is specified we need to execute a single
                // GraphQL request.
                //
                // Most GraphQL requests will be of this type where we want to execute
                // a single GraphQL query or mutation.
                case 1:
                {
                    result = await ExecuteSingleAsync(
                        context, requestExecutor, requestInterceptor, requests[0]);

                    break;
                }

                // if the HTTP request body contains more than one GraphQL request than
                // we need to execute a request batch where we need to execute multiple
                // fully specified GraphQL requests at once.
                default:
                    result = await ExecuteBatchAsync(
                        context, requestExecutor, requestInterceptor, requests);

                    break;
                }
            }
            catch (GraphQLRequestException ex)
            {
                // A GraphQL request exception is thrown if the HTTP request body couldn't be
                // parsed. In this case we will return HTTP status code 400 and return a
                // GraphQL error result.
                statusCode = HttpStatusCode.BadRequest;
                result     = QueryResultBuilder.CreateError(errorHandler.Handle(ex.Errors));
            }
            catch (Exception ex)
            {
                statusCode = HttpStatusCode.InternalServerError;
                IError error = errorHandler.CreateUnexpectedError(ex).Build();
                result = QueryResultBuilder.CreateError(error);
            }

            // in any case we will have a valid GraphQL result at this point that can be written
            // to the HTTP response stream.
            Debug.Assert(result is not null, "No GraphQL result was created.");
            await WriteResultAsync(context.Response, result, statusCode, context.RequestAborted);
        }
 public Builder WithHttpRequestInterceptor(IHttpRequestInterceptor httpRequestInterceptor)
 {
     HttpRequestInterceptor = httpRequestInterceptor;
     return(this);
 }
 public virtual Org.Apache.Http.Protocol.HttpProcessorBuilder Add(IHttpRequestInterceptor
                                                                  e)
 {
     return(AddLast(e));
 }
    protected async Task HandleRequestAsync(
        HttpContext context,
        AllowedContentType contentType)
    {
        // first we need to get the request executor to be able to execute requests.
        IRequestExecutor requestExecutor = await GetExecutorAsync(context.RequestAborted);

        IHttpRequestInterceptor requestInterceptor = requestExecutor.GetRequestInterceptor();
        IErrorHandler           errorHandler       = requestExecutor.GetErrorHandler();

        context.Items[WellKnownContextData.RequestExecutor] = requestExecutor;

        HttpStatusCode?  statusCode = null;
        IExecutionResult?result;

        // next we parse the GraphQL request.
        IReadOnlyList <GraphQLRequest> requests;

        using (DiagnosticEvents.ParseHttpRequest(context))
        {
            try
            {
                requests = await GetRequestsFromBody(context.Request, context.RequestAborted);
            }
            catch (GraphQLRequestException ex)
            {
                // A GraphQL request exception is thrown if the HTTP request body couldn't be
                // parsed. In this case we will return HTTP status code 400 and return a
                // GraphQL error result.
                statusCode = HttpStatusCode.BadRequest;
                IReadOnlyList <IError> errors = errorHandler.Handle(ex.Errors);
                result = QueryResultBuilder.CreateError(errors);
                DiagnosticEvents.ParserErrors(context, errors);
                goto HANDLE_RESULT;
            }
            catch (Exception ex)
            {
                statusCode = HttpStatusCode.InternalServerError;
                IError error = errorHandler.CreateUnexpectedError(ex).Build();
                result = QueryResultBuilder.CreateError(error);
                DiagnosticEvents.HttpRequestError(context, error);
                goto HANDLE_RESULT;
            }
        }

        // after successfully parsing the request we now will attempt to execute the request.
        try
        {
            switch (requests.Count)
            {
            // if the HTTP request body contains no GraphQL request structure the
            // whole request is invalid and we will create a GraphQL error response.
            case 0:
            {
                statusCode = HttpStatusCode.BadRequest;
                IError error = errorHandler.Handle(ErrorHelper.RequestHasNoElements());
                result = QueryResultBuilder.CreateError(error);
                DiagnosticEvents.HttpRequestError(context, error);
                break;
            }

            // if the HTTP request body contains a single GraphQL request and we do have
            // the batch operations query parameter specified we need to execute an
            // operation batch.
            //
            // An operation batch consists of a single GraphQL request document that
            // contains multiple operations. The batch operation query parameter
            // defines the order in which the operations shall be executed.
            case 1 when context.Request.Query.ContainsKey(_batchOperations):
            {
                string operationNames = context.Request.Query[_batchOperations];

                if (TryParseOperations(operationNames, out IReadOnlyList <string>?ops))
                {
                    result = await ExecuteOperationBatchAsync(
                        context,
                        requestExecutor,
                        requestInterceptor,
                        DiagnosticEvents,
                        requests[0],
                        ops);
                }
                else
                {
                    IError error = errorHandler.Handle(ErrorHelper.InvalidRequest());
                    statusCode = HttpStatusCode.BadRequest;
                    result     = QueryResultBuilder.CreateError(error);
                    DiagnosticEvents.HttpRequestError(context, error);
                }

                break;
            }

            // if the HTTP request body contains a single GraphQL request and
            // no batch query parameter is specified we need to execute a single
            // GraphQL request.
            //
            // Most GraphQL requests will be of this type where we want to execute
            // a single GraphQL query or mutation.
            case 1:
            {
                result = await ExecuteSingleAsync(
                    context,
                    requestExecutor,
                    requestInterceptor,
                    DiagnosticEvents,
                    requests[0]);

                break;
            }

            // if the HTTP request body contains more than one GraphQL request than
            // we need to execute a request batch where we need to execute multiple
            // fully specified GraphQL requests at once.
            default:
                result = await ExecuteBatchAsync(
                    context,
                    requestExecutor,
                    requestInterceptor,
                    DiagnosticEvents,
                    requests);

                break;
            }
        }
        catch (GraphQLException ex)
        {
            // This allows extensions to throw GraphQL exceptions in the GraphQL interceptor.
            statusCode = null; // we let the serializer determine the status code.
            result     = QueryResultBuilder.CreateError(ex.Errors);

            foreach (IError error in ex.Errors)
            {
                DiagnosticEvents.HttpRequestError(context, error);
            }
        }
        catch (Exception ex)
        {
            statusCode = HttpStatusCode.InternalServerError;
            IError error = errorHandler.CreateUnexpectedError(ex).Build();
            result = QueryResultBuilder.CreateError(error);
            DiagnosticEvents.HttpRequestError(context, error);
        }

HANDLE_RESULT:
        IDisposable? formatScope = null;

        try
        {
            // if cancellation is requested we will not try to attempt to write the result to the
            // response stream.
            if (context.RequestAborted.IsCancellationRequested)
            {
                return;
            }

            // in any case we will have a valid GraphQL result at this point that can be written
            // to the HTTP response stream.
            Debug.Assert(result is not null, "No GraphQL result was created.");

            if (result is IQueryResult queryResult)
            {
                formatScope = DiagnosticEvents.FormatHttpResponse(context, queryResult);
            }

            await WriteResultAsync(context.Response, result, statusCode, context.RequestAborted);
        }
        finally
        {
            // we must dispose the diagnostic scope first.
            formatScope?.Dispose();

            // query results use pooled memory an need to be disposed after we have
            // used them.
            if (result is IAsyncDisposable asyncDisposable)
            {
                await asyncDisposable.DisposeAsync();
            }

            if (result is IDisposable disposable)
            {
                disposable.Dispose();
            }
        }
    }