public static async ValueTask SendMessage <TResponse>(JsonTranscodingServerCallContext serverCallContext, JsonSerializerOptions serializerOptions, TResponse message, CancellationToken cancellationToken) where TResponse : class { var response = serverCallContext.HttpContext.Response; try { GrpcServerLog.SendingMessage(serverCallContext.Logger); object responseBody; Type responseType; if (serverCallContext.DescriptorInfo.ResponseBodyDescriptor != null) { // TODO: Support recursive response body? responseBody = serverCallContext.DescriptorInfo.ResponseBodyDescriptor.Accessor.GetValue((IMessage)message); responseType = JsonConverterHelper.GetFieldType(serverCallContext.DescriptorInfo.ResponseBodyDescriptor); } else { responseBody = message; responseType = message.GetType(); } await JsonRequestHelpers.WriteResponseMessage(response, serverCallContext.RequestEncoding, responseBody, serializerOptions, cancellationToken); GrpcServerLog.SerializedMessage(serverCallContext.Logger, responseType); GrpcServerLog.MessageSent(serverCallContext.Logger); } catch (Exception ex) { GrpcServerLog.ErrorSendingMessage(serverCallContext.Logger, ex); throw; } }
protected override async Task HandleCallAsyncCore(HttpContext httpContext, JsonTranscodingServerCallContext serverCallContext) { var request = await JsonRequestHelpers.ReadMessage <TRequest>(serverCallContext, SerializerOptions); var response = await _invoker.Invoke(httpContext, serverCallContext, request); if (serverCallContext.Status.StatusCode != StatusCode.OK) { throw new RpcException(serverCallContext.Status); } if (response == null) { // This is consistent with Grpc.Core when a null value is returned throw new RpcException(new Status(StatusCode.Cancelled, "No message returned from method.")); } if (response is HttpBody httpBody) { serverCallContext.EnsureResponseHeaders(httpBody.ContentType); await serverCallContext.HttpContext.Response.Body.WriteAsync(httpBody.Data.Memory); } else { serverCallContext.EnsureResponseHeaders(); await JsonRequestHelpers.SendMessage(serverCallContext, SerializerOptions, response, CancellationToken.None); } }
internal async Task ProcessHandlerErrorAsync(Exception ex, string method, bool isStreaming, JsonSerializerOptions options) { Status status; if (ex is RpcException rpcException) { // RpcException is thrown by client code to modify the status returned from the server. // Log the status and detail. Don't log the exception to reduce log verbosity. GrpcServerLog.RpcConnectionError(Logger, rpcException.StatusCode, rpcException.Status.Detail); status = rpcException.Status; } else { GrpcServerLog.ErrorExecutingServiceMethod(Logger, method, ex); var message = ErrorMessageHelper.BuildErrorMessage("Exception was thrown by handler.", ex, Options.EnableDetailedErrors); // Note that the exception given to status won't be returned to the client. // It is still useful to set in case an interceptor accesses the status on the server. status = new Status(StatusCode.Unknown, message, ex); } await JsonRequestHelpers.SendErrorResponse(HttpContext.Response, RequestEncoding, status, options); if (isStreaming) { await HttpContext.Response.Body.WriteAsync(GrpcProtocolConstants.StreamingDelimiter); } }
public void Initialize() { IsJsonRequestContent = JsonRequestHelpers.HasJsonContentType(HttpContext.Request, out var charset); RequestEncoding = JsonRequestHelpers.GetEncodingFromCharset(charset) ?? Encoding.UTF8; // HttpContext.Items is publically exposed as ServerCallContext.UserState. // Because this is a custom ServerCallContext, HttpContext must be added to UserState so GetHttpContext() continues to work. // https://github.com/grpc/grpc-dotnet/blob/7ef184f3c4cd62fbc3cde55e4bb3e16b58258ca1/src/Grpc.AspNetCore.Server/ServerCallContextExtensions.cs#L53-L61 HttpContext.Items["__HttpContext"] = HttpContext; }
protected override async Task HandleCallAsyncCore(HttpContext httpContext, HttpApiServerCallContext serverCallContext) { // Decode request var request = await JsonRequestHelpers.ReadMessage <TRequest>(serverCallContext, SerializerOptions); var streamWriter = new HttpContextStreamWriter <TResponse>(serverCallContext, SerializerOptions); try { await _invoker.Invoke(httpContext, serverCallContext, request, streamWriter); } finally { streamWriter.Complete(); } }
public async Task Request_SupportedCharset_Success(string?charset) { // Arrange Task <HelloReply> UnaryMethod(HelloRequest request, ServerCallContext context) { return(Task.FromResult(new HelloReply { Message = $"Hello {request.Name}!" })); } var method = Fixture.DynamicGrpc.AddUnaryMethod <HelloRequest, HelloReply>( UnaryMethod, Greeter.Descriptor.FindMethodByName("SayHelloPost")); var encoding = JsonRequestHelpers.GetEncodingFromCharset(charset); var contentType = charset != null ? "application/json; charset=" + charset : "application/json"; var client = new HttpClient(Fixture.Handler) { BaseAddress = new Uri("http://localhost") }; var requestMessage = new HelloRequest { Name = "test" }; var content = new ByteArrayContent((encoding ?? Encoding.UTF8).GetBytes(requestMessage.ToString())); content.Headers.ContentType = MediaTypeHeaderValue.Parse(contentType); // Act var response = await client.PostAsync("/v1/greeter", content).DefaultTimeout(); var responseText = await response.Content.ReadAsStringAsync(); using var result = JsonDocument.Parse(responseText); // Assert Assert.Equal("application/json", response.Content.Headers.ContentType !.MediaType); Assert.Equal(encoding?.WebName ?? "utf-8", response.Content.Headers.ContentType !.CharSet); Assert.Equal("Hello test!", result.RootElement.GetProperty("message").GetString()); }
protected override async Task HandleCallAsyncCore(HttpContext httpContext, HttpApiServerCallContext serverCallContext) { var request = await JsonRequestHelpers.ReadMessage <TRequest>(serverCallContext, SerializerOptions); var response = await _invoker.Invoke(httpContext, serverCallContext, request); if (serverCallContext.Status.StatusCode != StatusCode.OK) { throw new RpcException(serverCallContext.Status); } if (response == null) { // This is consistent with Grpc.Core when a null value is returned throw new RpcException(new Status(StatusCode.Cancelled, "No message returned from method.")); } httpContext.Response.StatusCode = StatusCodes.Status200OK; httpContext.Response.ContentType = MediaType.ReplaceEncoding("application/json", serverCallContext.RequestEncoding); await JsonRequestHelpers.SendMessage(serverCallContext, SerializerOptions, response); }