protected override async Task HandleCallAsyncCore(HttpContext httpContext, HttpContextServerCallContext serverCallContext) { var request = await httpContext.Request.BodyReader.ReadSingleMessageAsync <TRequest>(serverCallContext, MethodInvoker.Method.RequestMarshaller.ContextualDeserializer); var response = await _invoker.Invoke(httpContext, serverCallContext, request); 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 (serverCallContext.DeadlineManager != null && serverCallContext.DeadlineManager.CancellationToken.IsCancellationRequested) { // The cancellation token has been raised. Ensure that any DeadlineManager tasks have // been completed before continuing. await serverCallContext.DeadlineManager.CancellationProcessedTask; // There is no point trying to write to the response because it has been finished. if (serverCallContext.DeadlineManager.CallComplete) { return; } } var responseBodyWriter = httpContext.Response.BodyWriter; await responseBodyWriter.WriteMessageAsync(response, serverCallContext, MethodInvoker.Method.ResponseMarshaller.ContextualSerializer, canFlush : false); }
protected override async Task HandleCallAsyncCore(HttpContext httpContext, HttpContextServerCallContext serverCallContext) { // Disable request body data rate for client streaming DisableMinRequestBodyDataRateAndMaxRequestBodySize(httpContext); if (_pipelineInvoker == null) { var service = (TService)ServiceActivator.Create(serverCallContext, typeof(TService)); try { await _invoker( service, new HttpContextStreamReader <TRequest>(serverCallContext, Method.RequestMarshaller.ContextualDeserializer), new HttpContextStreamWriter <TResponse>(serverCallContext, Method.ResponseMarshaller.ContextualSerializer), serverCallContext); } finally { await ServiceActivator.ReleaseAsync(service); } } else { await _pipelineInvoker( new HttpContextStreamReader <TRequest>(serverCallContext, Method.RequestMarshaller.ContextualDeserializer), new HttpContextStreamWriter <TResponse>(serverCallContext, Method.ResponseMarshaller.ContextualSerializer), serverCallContext); } }
protected override async Task HandleCallAsyncCore(HttpContext httpContext, HttpContextServerCallContext serverCallContext) { var request = await httpContext.Request.BodyReader.ReadSingleMessageAsync <TRequest>(serverCallContext, Method.RequestMarshaller.ContextualDeserializer); TResponse?response = null; if (_pipelineInvoker == null) { var service = (TService)ServiceActivator.Create(serverCallContext, typeof(TService)); try { response = await _invoker(service, request, serverCallContext); } finally { await ServiceActivator.ReleaseAsync(service); } } else { response = await _pipelineInvoker(request, serverCallContext); } 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.")); } var responseBodyWriter = httpContext.Response.BodyWriter; await responseBodyWriter.WriteMessageAsync(response, serverCallContext, Method.ResponseMarshaller.ContextualSerializer, canFlush : false); }
protected override async Task HandleCallAsyncCore(HttpContext httpContext, HttpContextServerCallContext serverCallContext) { // Disable request body data rate for client streaming DisableMinRequestBodyDataRate(httpContext); if (_pipelineInvoker == null) { var activator = httpContext.RequestServices.GetRequiredService <IGrpcServiceActivator <TService> >(); TService?service = null; try { service = activator.Create(); await _invoker( service, new HttpContextStreamReader <TRequest>(serverCallContext, Method.RequestMarshaller.Deserializer), new HttpContextStreamWriter <TResponse>(serverCallContext, Method.ResponseMarshaller.Serializer), serverCallContext); } finally { if (service != null) { activator.Release(service); } } } else { await _pipelineInvoker( new HttpContextStreamReader <TRequest>(serverCallContext, Method.RequestMarshaller.Deserializer), new HttpContextStreamWriter <TResponse>(serverCallContext, Method.ResponseMarshaller.Serializer), serverCallContext); } }
public static HttpContextServerCallContext CreateServerCallContext( HttpContext?httpContext = null, List <ICompressionProvider>?compressionProviders = null, string?responseCompressionAlgorithm = null, CompressionLevel?responseCompressionLevel = null, int?maxSendMessageSize = null, int?maxReceiveMessageSize = null, ILogger?logger = null, bool initialize = true) { var options = CreateMethodOptions( compressionProviders, responseCompressionAlgorithm, responseCompressionLevel, maxSendMessageSize, maxReceiveMessageSize); var context = new HttpContextServerCallContext( httpContext ?? new DefaultHttpContext(), options, typeof(object), typeof(object), logger ?? NullLogger.Instance); if (initialize) { context.Initialize(); } return(context); }
public Task HandleCallAsync(HttpContext httpContext) { if (GrpcProtocolHelpers.IsInvalidContentType(httpContext, out var error)) { GrpcProtocolHelpers.SendHttpError(httpContext.Response, StatusCodes.Status415UnsupportedMediaType, StatusCode.Internal, error !); return(Task.CompletedTask); } var serverCallContext = new HttpContextServerCallContext(httpContext, ServiceOptions, Logger); httpContext.Features.Set <IServerCallContextFeature>(serverCallContext); GrpcProtocolHelpers.AddProtocolHeaders(httpContext.Response); try { serverCallContext.Initialize(); var handleCallTask = HandleCallAsyncCore(httpContext, serverCallContext); if (handleCallTask.IsCompletedSuccessfully) { return(serverCallContext.EndCallAsync()); } else { return(AwaitHandleCall(serverCallContext, Method, handleCallTask)); } } catch (Exception ex) { return(serverCallContext.ProcessHandlerErrorAsync(ex, Method.Name)); }
protected override async Task HandleCallAsyncCore(HttpContext httpContext, HttpContextServerCallContext serverCallContext) { // Disable request body data rate for client streaming DisableMinRequestBodyDataRateAndMaxRequestBodySize(httpContext); if (_pipelineInvoker == null) { GrpcActivatorHandle <TService> serviceHandle = default; try { serviceHandle = ServiceActivator.Create(httpContext.RequestServices); await _invoker( serviceHandle.Instance, new HttpContextStreamReader <TRequest>(serverCallContext, Method.RequestMarshaller.ContextualDeserializer), new HttpContextStreamWriter <TResponse>(serverCallContext, Method.ResponseMarshaller.ContextualSerializer), serverCallContext); } finally { if (serviceHandle.Instance != null) { ServiceActivator.Release(serviceHandle); } } } else { await _pipelineInvoker( new HttpContextStreamReader <TRequest>(serverCallContext, Method.RequestMarshaller.ContextualDeserializer), new HttpContextStreamWriter <TResponse>(serverCallContext, Method.ResponseMarshaller.ContextualSerializer), serverCallContext); } }
protected override async Task HandleCallAsyncCore(HttpContext httpContext, HttpContextServerCallContext serverCallContext) { // Decode request var request = await httpContext.Request.BodyReader.ReadSingleMessageAsync <TRequest>(serverCallContext, Method.RequestMarshaller.ContextualDeserializer); if (_pipelineInvoker == null) { GrpcActivatorHandle <TService> serviceHandle = default; try { serviceHandle = ServiceActivator.Create(httpContext.RequestServices); await _invoker( serviceHandle.Instance, request, new HttpContextStreamWriter <TResponse>(serverCallContext, Method.ResponseMarshaller.ContextualSerializer), serverCallContext); } finally { if (serviceHandle.Instance != null) { ServiceActivator.Release(serviceHandle); } } } else { await _pipelineInvoker( request, new HttpContextStreamWriter <TResponse>(serverCallContext, Method.ResponseMarshaller.ContextualSerializer), serverCallContext); } }
protected override async Task HandleCallAsyncCore(HttpContext httpContext, HttpContextServerCallContext serverCallContext) { // Disable request body data rate for client streaming DisableMinRequestBodyDataRateAndMaxRequestBodySize(httpContext); TResponse?response; var streamReader = new HttpContextStreamReader <TRequest>(serverCallContext, MethodInvoker.Method.RequestMarshaller.ContextualDeserializer); try { response = await _invoker.Invoke(httpContext, serverCallContext, streamReader); } finally { streamReader.Complete(); } 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.")); } // Check if deadline exceeded while method was invoked. If it has then skip trying to write // the response message because it will always fail. // Note that the call is still going so the deadline could still be exceeded after this point. if (serverCallContext.DeadlineManager?.IsDeadlineExceededStarted ?? false) { return; } var responseBodyWriter = httpContext.Response.BodyWriter; await responseBodyWriter.WriteSingleMessageAsync(response, serverCallContext, MethodInvoker.Method.ResponseMarshaller.ContextualSerializer); }
protected override async Task HandleCallAsyncCore(HttpContext httpContext, HttpContextServerCallContext serverCallContext) { // Decode request var request = await httpContext.Request.BodyReader.ReadSingleMessageAsync <TRequest>(serverCallContext, Method.RequestMarshaller.ContextualDeserializer); if (_pipelineInvoker == null) { var service = (TService)ServiceActivator.Create(serverCallContext, typeof(TService)); try { await _invoker( service, request, new HttpContextStreamWriter <TResponse>(serverCallContext, Method.ResponseMarshaller.ContextualSerializer), serverCallContext); } finally { await ServiceActivator.ReleaseAsync(service); } } else { await _pipelineInvoker( request, new HttpContextStreamWriter <TResponse>(serverCallContext, Method.ResponseMarshaller.ContextualSerializer), serverCallContext); } }
protected HttpContextServerCallContext CreateServerCallContext(HttpContext httpContext) { var serverCallContext = new HttpContextServerCallContext(httpContext, ServiceOptions, Logger); httpContext.Features.Set <IServerCallContextFeature>(serverCallContext); return(serverCallContext); }
protected override async Task HandleCallAsyncCore(HttpContext httpContext, HttpContextServerCallContext serverCallContext) { // Decode request var request = await httpContext.Request.BodyReader.ReadSingleMessageAsync <TRequest>(serverCallContext, MethodInvoker.Method.RequestMarshaller.ContextualDeserializer); var streamWriter = new HttpContextStreamWriter <TResponse>(serverCallContext, MethodInvoker.Method.ResponseMarshaller.ContextualSerializer); await _invoker.Invoke(httpContext, serverCallContext, request, streamWriter); }
public Task HandleCallAsync(HttpContext httpContext) { if (GrpcProtocolHelpers.IsInvalidContentType(httpContext, out var error)) { // This might be a CORS preflight request and CORS middleware hasn't been configured if (HttpMethods.IsOptions(httpContext.Request.Method)) { GrpcServerLog.UnhandledCorsPreflightRequest(Logger); GrpcProtocolHelpers.BuildHttpErrorResponse(httpContext.Response, StatusCodes.Status405MethodNotAllowed, StatusCode.Internal, "Unhandled CORS preflight request received. CORS may not be configured correctly in the application."); httpContext.Response.Headers[HeaderNames.Allow] = HttpMethods.Post; return(Task.CompletedTask); } else { GrpcServerLog.UnsupportedRequestContentType(Logger, httpContext.Request.ContentType); GrpcProtocolHelpers.BuildHttpErrorResponse(httpContext.Response, StatusCodes.Status415UnsupportedMediaType, StatusCode.Internal, error); return(Task.CompletedTask); } } if (httpContext.Request.Protocol != GrpcProtocolConstants.Http2Protocol && httpContext.Request.Protocol != GrpcProtocolConstants.Http20Protocol) { GrpcServerLog.UnsupportedRequestProtocol(Logger, httpContext.Request.Protocol); var protocolError = $"Request protocol '{httpContext.Request.Protocol}' is not supported."; GrpcProtocolHelpers.BuildHttpErrorResponse(httpContext.Response, StatusCodes.Status426UpgradeRequired, StatusCode.Internal, protocolError); httpContext.Response.Headers[HeaderNames.Upgrade] = GrpcProtocolConstants.Http2Protocol; return(Task.CompletedTask); } var serverCallContext = new HttpContextServerCallContext(httpContext, MethodInvoker.Options, typeof(TRequest), typeof(TResponse), Logger); httpContext.Features.Set <IServerCallContextFeature>(serverCallContext); GrpcProtocolHelpers.AddProtocolHeaders(httpContext.Response); try { serverCallContext.Initialize(); var handleCallTask = HandleCallAsyncCore(httpContext, serverCallContext); if (handleCallTask.IsCompletedSuccessfully) { return(serverCallContext.EndCallAsync()); } else { return(AwaitHandleCall(serverCallContext, MethodInvoker.Method, handleCallTask)); } } catch (Exception ex) { return(serverCallContext.ProcessHandlerErrorAsync(ex, MethodInvoker.Method.Name)); }
protected override Task HandleCallAsyncCore(HttpContext httpContext, HttpContextServerCallContext serverCallContext) { // Disable request body data rate for client streaming DisableMinRequestBodyDataRateAndMaxRequestBodySize(httpContext); var streamReader = new HttpContextStreamReader <TRequest>(serverCallContext, MethodInvoker.Method.RequestMarshaller.ContextualDeserializer); var streamWriter = new HttpContextStreamWriter <TResponse>(serverCallContext, MethodInvoker.Method.ResponseMarshaller.ContextualSerializer); return(_invoker.Invoke(httpContext, serverCallContext, streamReader, streamWriter)); }
public void Deadline_NoTimeoutHeader_MaxValue() { // Arrange var httpContext = new DefaultHttpContext(); var context = new HttpContextServerCallContext(httpContext); // Act context.Initialize(); // Assert Assert.AreEqual(DateTime.MaxValue, context.Deadline); }
protected override async Task HandleCallAsyncCore(HttpContext httpContext) { GrpcProtocolHelpers.AddProtocolHeaders(httpContext.Response); var serverCallContext = new HttpContextServerCallContext(httpContext, ServiceOptions, Logger); var activator = httpContext.RequestServices.GetRequiredService <IGrpcServiceActivator <TService> >(); TService service = null; TResponse response = null; try { serverCallContext.Initialize(); var requestPayload = await httpContext.Request.BodyPipe.ReadSingleMessageAsync(serverCallContext); var request = Method.RequestMarshaller.Deserializer(requestPayload); service = activator.Create(); response = await _invoker( service, request, serverCallContext); 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.")); } var responseBodyPipe = httpContext.Response.BodyPipe; await responseBodyPipe.WriteMessageAsync(response, serverCallContext, Method.ResponseMarshaller.Serializer); } catch (Exception ex) { serverCallContext.ProcessHandlerError(ex, Method.Name); } finally { serverCallContext.Dispose(); if (service != null) { activator.Release(service); } } httpContext.Response.ConsolidateTrailers(serverCallContext); // Flush any buffered content await httpContext.Response.BodyPipe.FlushAsync(); }
public static void SetupHttpContext(ServiceCollection services, CancellationToken?cancellationToken = null) { var httpContext = new DefaultHttpContext(); httpContext.RequestAborted = cancellationToken ?? CancellationToken.None; var serverCallContext = new HttpContextServerCallContext(httpContext, new GrpcServiceOptions(), NullLogger.Instance); httpContext.Features.Set <IServerCallContextFeature>(serverCallContext); services.AddSingleton <IHttpContextAccessor>(new TestHttpContextAccessor(httpContext)); }
static async Task AwaitHandleCall(HttpContextServerCallContext serverCallContext, Method <TRequest, TResponse> method, Task handleCall) { try { await handleCall; await serverCallContext.EndCallAsync(); } catch (Exception ex) { await serverCallContext.ProcessHandlerErrorAsync(ex, method.Name); } }
public void RequestHeaders_IgnoresPseudoHeaders(string headerName) { // Arrange var httpContext = new DefaultHttpContext(); httpContext.Request.Headers[headerName] = "dummy"; // Act var serverCallContext = new HttpContextServerCallContext(httpContext); // Assert Assert.AreEqual(0, serverCallContext.RequestHeaders.Count); }
public void RequestHeaders_ThrowsForNonBase64EncodedBinaryHeader() { // Arrange var httpContext = new DefaultHttpContext(); httpContext.Request.Headers["test-bin"] = "a;b"; // Act var serverCallContext = new HttpContextServerCallContext(httpContext); // Assert Assert.Throws <FormatException>(() => serverCallContext.RequestHeaders.Clear()); }
public void Deadline_ParseInvalidHeader_ThrowsError(string header) { // Arrange var httpContext = new DefaultHttpContext(); httpContext.Request.Headers[GrpcProtocolConstants.TimeoutHeader] = header; var context = new HttpContextServerCallContext(httpContext); // Act var ex = Assert.Catch <InvalidOperationException>(() => context.Initialize()); // Assert Assert.AreEqual("Error reading grpc-timeout value.", ex.Message); }
public void Deadline_UnsupportedLength_ThrowsError(string header) { // Arrange var httpContext = new DefaultHttpContext(); httpContext.Request.Headers[GrpcProtocolConstants.TimeoutHeader] = header; var context = new HttpContextServerCallContext(httpContext); // Act var ex = Assert.Catch <InvalidOperationException>(() => context.Initialize()); // Assert Assert.AreEqual("A timeout greater than 2147483647 milliseconds is not supported.", ex.Message); }
public override async Task HandleCallAsync(HttpContext httpContext) { httpContext.Response.ContentType = "application/grpc"; httpContext.Response.Headers.Append("grpc-encoding", "identity"); var serverCallContext = new HttpContextServerCallContext(httpContext, ServiceOptions, Logger); var activator = httpContext.RequestServices.GetRequiredService <IGrpcServiceActivator <TService> >(); TService service = null; TResponse response = null; try { serverCallContext.Initialize(); service = activator.Create(); response = await _invoker( service, new HttpContextStreamReader <TRequest>(httpContext, serverCallContext, Method.RequestMarshaller.Deserializer), serverCallContext); if (response == null) { // This is consistent with Grpc.Core when a null value is returned throw new RpcException(new Status(StatusCode.Cancelled, "Cancelled")); } var responseBodyPipe = httpContext.Response.BodyPipe; await responseBodyPipe.WriteMessageAsync(response, serverCallContext, Method.ResponseMarshaller.Serializer); } catch (Exception ex) { serverCallContext.ProcessHandlerError(ex, Method.Name); } finally { serverCallContext.Dispose(); if (service != null) { activator.Release(service); } } httpContext.Response.ConsolidateTrailers(serverCallContext); // Flush any buffered content await httpContext.Response.BodyPipe.FlushAsync(); }
public void Peer_FormatsRemoteAddressCorrectly(string ipAddress, int port, string expected) { // Arrange var httpContext = new DefaultHttpContext(); httpContext.Connection.RemoteIpAddress = IPAddress.Parse(ipAddress); httpContext.Connection.RemotePort = port; // Act var serverCallContext = new HttpContextServerCallContext(httpContext); // Assert Assert.AreEqual(expected, serverCallContext.Peer); }
public static HttpContextServerCallContext CreateServerCallContext( HttpContext httpContext = null, GrpcServiceOptions serviceOptions = null, ILogger logger = null) { var context = new HttpContextServerCallContext( httpContext ?? new DefaultHttpContext(), serviceOptions ?? new GrpcServiceOptions(), logger ?? NullLogger.Instance); context.Initialize(); return(context); }
public async Task WriteResponseHeadersAsyncCore_AddsMetadataToResponseHeaders() { // Arrange var httpContext = new DefaultHttpContext(); var metadata = new Metadata(); metadata.Add("foo", "bar"); // Act var serverCallContext = new HttpContextServerCallContext(httpContext); await serverCallContext.WriteResponseHeadersAsync(metadata); // Assert Assert.AreEqual("bar", httpContext.Response.Headers["foo"]); }
protected override async Task HandleCallAsyncCore(HttpContext httpContext, HttpContextServerCallContext serverCallContext) { var request = await httpContext.Request.BodyReader.ReadSingleMessageAsync <TRequest>(serverCallContext, MethodInvoker.Method.RequestMarshaller.ContextualDeserializer); var response = await _invoker.Invoke(httpContext, serverCallContext, request); 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.")); } var responseBodyWriter = httpContext.Response.BodyWriter; await responseBodyWriter.WriteMessageAsync(response, serverCallContext, MethodInvoker.Method.ResponseMarshaller.ContextualSerializer, canFlush : false); }
public void Deadline_ParseValidHeader_ReturnDeadline(string header, long ticks) { // Arrange var httpContext = new DefaultHttpContext(); httpContext.Request.Headers[GrpcProtocolConstants.TimeoutHeader] = header; var context = new HttpContextServerCallContext(httpContext); context.Clock = TestClock; // Act context.Initialize(); // Assert Assert.AreEqual(TestClock.UtcNow.Add(TimeSpan.FromTicks(ticks)), context.Deadline); }
public async Task WriteResponseHeadersAsyncCore_Base64EncodesBinaryResponseHeaders(string headerName) { // Arrange var headerBytes = new byte[] { 0x01, 0x02, 0x03, 0x04 }; var httpContext = new DefaultHttpContext(); var metadata = new Metadata(); metadata.Add(headerName, headerBytes); // Act var serverCallContext = new HttpContextServerCallContext(httpContext); await serverCallContext.WriteResponseHeadersAsync(metadata); // Assert CollectionAssert.AreEqual(headerBytes, Convert.FromBase64String(httpContext.Response.Headers["foo-bin"].ToString())); }
protected override async Task HandleCallAsyncCore(HttpContext httpContext, HttpContextServerCallContext serverCallContext) { // Disable request body data rate for client streaming DisableMinRequestBodyDataRateAndMaxRequestBodySize(httpContext); var streamReader = new HttpContextStreamReader <TRequest>(serverCallContext, MethodInvoker.Method.RequestMarshaller.ContextualDeserializer); var response = await _invoker.Invoke(httpContext, serverCallContext, streamReader); 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.")); } var responseBodyWriter = httpContext.Response.BodyWriter; await responseBodyWriter.WriteMessageAsync(response, serverCallContext, MethodInvoker.Method.ResponseMarshaller.ContextualSerializer, canFlush : false); }