示例#1
0
        /// <summary>
        /// Process grpc request
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        private async Task ProcessInternal(HttpContext context, Func <Task> next)
        {
            var downstreamRoute = context.Items.DownstreamRoute();
            var methodPath      = downstreamRoute.DownstreamPathTemplate.Value;

            try
            {
                var grpcAssemblyResolver = context.RequestServices.GetService <GrpcAssemblyResolver>();
                var methodDescriptor     =
                    grpcAssemblyResolver.FindMethodDescriptor(methodPath.Split('/').Last().ToUpperInvariant());

                if (methodDescriptor == null)
                {
                    await next.Invoke();

                    return;
                }

                var downstreamRequest = context.Items.DownstreamRequest();
                var upstreamHeaders   = new Dictionary <string, string>
                {
                    {
                        "x-grpc-route-data",
                        JsonConvert.SerializeObject(
                            context.Items.TemplatePlaceholderNameAndValues().Select(x => new { x.Name, x.Value }))
                    },
                    { "x-grpc-body-data", await downstreamRequest.Content.ReadAsStringAsync() }
                };

                var requestData = context.ParseJsonRequest(upstreamHeaders);
                var client      = await CreateGrpcClient(context);

                var timeout       = _options.GetRouteTimeout(methodPath);
                var deadline      = (timeout != TimeSpan.MaxValue) ? DateTime.UtcNow.Add(timeout) : DateTime.MaxValue;
                var requestObject = JsonConvert.DeserializeObject(requestData, methodDescriptor.InputType.ClrType, _jsonSerializerSettings);
                var headers       = context.BuildRequestHeaders(downstreamRoute, downstreamRequest);
                var result        = await client.InvokeAsync(methodDescriptor, headers, requestObject, deadline);

                var content  = new GrpcHttpContent(JsonConvert.SerializeObject(result, _jsonSerializerSettings));
                var response = new OkResponse <GrpcHttpContent>(content);

                response.Data.Headers.ContentType = new MediaTypeHeaderValue(MediaTypeNames.Application.Json);

                context.Response.ContentType = MediaTypeNames.Application.Json;
                context.Items.UpsertDownstreamResponse(new DownstreamResponse(response.Data, HttpStatusCode.OK, response.Data.Headers, HttpStatusCode.OK.ToString()));
            }
            catch (RpcException e)
            {
                ProcessRpcError(context, e);
            }
            catch (Exception e)
            {
                ProcessError(context, e);
            }
        }
        private static DownstreamResponse CreateHttpResponseMessage(CachedResponse cached)
        {
            if (cached == null)
            {
                return(null);
            }

            var streamContent = new GrpcHttpContent(cached.Body);

            foreach (var(key, value) in cached.ContentHeaders)
            {
                streamContent.Headers.TryAddWithoutValidation(key, value);
            }

            return(new DownstreamResponse(streamContent, cached.StatusCode, cached.Headers.ToList(), cached.ReasonPhrase));
        }
示例#3
0
        private static void ProcessError(HttpContext context, Exception e)
        {
            var content = new GrpcHttpContent(new ApiResponse
            {
                ResponseCode = _defaultErrorStatus,
                Errors       = new[] { new ApiError(e.Message, e.InnerException?.Message) }
            });

            context.Response.ContentType = MediaTypeNames.Application.Json;
            var response = new DownstreamResponse(content,
                                                  _defaultErrorCode,
                                                  new List <Header>
            {
                new Header(HeaderNames.ContentType, new [] { MediaTypeNames.Application.Json })
            },
                                                  _defaultErrorCode.ToString());

            context.Items.UpsertDownstreamResponse(response);
        }
示例#4
0
        public async Task Invoke(HttpContext context, Func <Task> next)
        {
            var downstreamRoute = context.Items.DownstreamRoute();
            var methodPath      = downstreamRoute.DownstreamPathTemplate.Value;

            // ignore if the request is not a gRPC content type
            if (!_options.IsGrpcRoute(methodPath))
            {
                await next.Invoke();

                if (context.Items.DownstreamResponse() != null) // if has response - everything is ok, just return
                {
                    return;
                }

                // add human friendly error message for grpc-call
                var errors   = context.Items.Errors() ?? new List <Error>();
                var response = new GrpcHttpContent(new
                {
                    ResponseCode = _defaultErrorStatus,
                    Errors       = errors.Any()
                        ? errors
                                   .Select(x => $"{x.Code}: {x.Message}")
                                   .ToArray()
                        : new[]
                    {
                        "Request process error. Either request is invalid or application wasn't configured properly"
                    }
                });

                context.Response.ContentType = "application/json";
                context.Response.StatusCode  = (int)_defaultErrorCode;
                await response.WriteStream(context.Response.Body);

                return;
            }

            await _cacheHelper.Process(context, async ctx => await ProcessInternal(ctx, next));
        }