private static Task WriteMessageCoreAsync(this PipeWriter pipeWriter, byte[] messageData, HttpContextServerCallContext serverCallContext, bool flush) { Debug.Assert(serverCallContext.ResponseGrpcEncoding != null); var isCompressed = serverCallContext.CanWriteCompressed() && !string.Equals(serverCallContext.ResponseGrpcEncoding, GrpcProtocolConstants.IdentityGrpcEncoding, StringComparison.Ordinal); if (isCompressed) { messageData = GrpcProtocolHelpers.CompressMessage( serverCallContext.ResponseGrpcEncoding, serverCallContext.ServiceOptions.ResponseCompressionLevel, serverCallContext.ServiceOptions.CompressionProviders, messageData); } WriteHeader(pipeWriter, messageData.Length, isCompressed); pipeWriter.Write(messageData); if (flush) { serverCallContext.HasBufferedMessage = false; return(pipeWriter.FlushAsync().GetAsTask()); } else { // Set flag so buffered message will be written at the end serverCallContext.HasBufferedMessage = true; } return(Task.CompletedTask); }
public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection) { if (httpContext == null) { return(false); } return(GrpcProtocolHelpers.IsGrpcContentType(httpContext.Request.ContentType)); }
private ICompressionProvider?ResolveCompressionProvider() { if (_serverCallContext.ResponseGrpcEncoding != null && GrpcProtocolHelpers.CanWriteCompressed(_serverCallContext.WriteOptions) && _serverCallContext.Options.CompressionProviders.TryGetValue(_serverCallContext.ResponseGrpcEncoding, out var compressionProvider)) { return(compressionProvider); } return(null); }
public RequestDelegate CreateUnimplementedMethod() { var logger = _loggerFactory.CreateLogger <ServerCallHandlerFactory <TService> >(); return(httpContext => { GrpcProtocolHelpers.AddProtocolHeaders(httpContext.Response); var unimplementedMethod = httpContext.Request.RouteValues["unimplementedMethod"]?.ToString(); Log.MethodUnimplemented(logger, unimplementedMethod); GrpcProtocolHelpers.SetStatusTrailers(httpContext.Response, new Status(StatusCode.Unimplemented, "Method is unimplemented.")); return Task.CompletedTask; }); }
public RequestDelegate CreateUnimplementedService() { var logger = _loggerFactory.CreateLogger <ServerCallHandlerFactory <TService> >(); return(httpContext => { GrpcProtocolHelpers.AddProtocolHeaders(httpContext.Response); var unimplementedService = httpContext.Request.RouteValues["unimplementedService"]?.ToString() ?? "<unknown>"; Log.ServiceUnimplemented(logger, unimplementedService); GrpcProtocolHelpers.SetStatus(GrpcProtocolHelpers.GetTrailersDestination(httpContext.Response), new Status(StatusCode.Unimplemented, "Service is unimplemented.")); return Task.CompletedTask; }); }
public static void ConsolidateTrailers(this HttpResponse httpResponse, HttpContextServerCallContext context) { var trailersDestination = GrpcProtocolHelpers.GetTrailersDestination(httpResponse); if (context.HasResponseTrailers) { foreach (var trailer in context.ResponseTrailers) { var value = (trailer.IsBinary) ? Convert.ToBase64String(trailer.ValueBytes) : trailer.Value; trailersDestination.Append(trailer.Key, value); } } // Append status trailers, these overwrite any existing status trailers set via ServerCallContext.ResponseTrailers GrpcProtocolHelpers.SetStatus(trailersDestination, context.Status); }
private TimeSpan GetTimeout() { if (HttpContext.Request.Headers.TryGetValue(GrpcProtocolConstants.TimeoutHeader, out var values)) { // CancellationTokenSource does not support greater than int.MaxValue milliseconds if (GrpcProtocolHelpers.TryDecodeTimeout(values, out var timeout) && timeout > TimeSpan.Zero && timeout.TotalMilliseconds <= int.MaxValue) { return(timeout); } InvalidTimeoutIgnored(_logger, values); } return(TimeSpan.Zero); }
private ICompressionProvider?ResolveCompressionProvider() { Debug.Assert( _serverCallContext.ResponseGrpcEncoding != null, "Response encoding should have been calculated at this point."); var canCompress = GrpcProtocolHelpers.CanWriteCompressed(_serverCallContext.WriteOptions) && !string.Equals(_serverCallContext.ResponseGrpcEncoding, GrpcProtocolConstants.IdentityGrpcEncoding, StringComparison.Ordinal); if (canCompress) { if (_serverCallContext.Options.CompressionProviders.TryGetValue(_serverCallContext.ResponseGrpcEncoding, out var compressionProvider)) { return(compressionProvider); } } return(null); }
public static void ConsolidateTrailers(this HttpResponse httpResponse, HttpContextServerCallContext context) { if (context.HasResponseTrailers) { foreach (var trailer in context.ResponseTrailers) { if (trailer.IsBinary) { httpResponse.AppendTrailer(trailer.Key, Convert.ToBase64String(trailer.ValueBytes)); } else { httpResponse.AppendTrailer(trailer.Key, trailer.Value); } } } // Append status trailers, these overwrite any existing status trailers set via ServerCallContext.ResponseTrailers GrpcProtocolHelpers.AppendStatusTrailers(httpResponse, context.Status); }
public void Initialize() { var timeout = GrpcProtocolHelpers.GetTimeout(HttpContext); if (timeout != TimeSpan.MaxValue) { // CancellationTokenSource does not support greater than int.MaxValue milliseconds if (timeout.TotalMilliseconds > int.MaxValue) { throw new InvalidOperationException("A timeout greater than 2147483647 milliseconds is not supported."); } _deadline = Clock.UtcNow.Add(timeout); _cts = new CancellationTokenSource(timeout); } else { _deadline = DateTime.MaxValue; _cts = new CancellationTokenSource(); } }
public RequestDelegate CreateUnimplementedMethod() { var logger = _loggerFactory.CreateLogger <ServerCallHandlerFactory <TService> >(); return(httpContext => { // CORS preflight request should be handled by CORS middleware. // If it isn't then return 404 from endpoint request delegate. if (GrpcProtocolHelpers.IsCorsPreflightRequest(httpContext)) { httpContext.Response.StatusCode = StatusCodes.Status404NotFound; return Task.CompletedTask; } GrpcProtocolHelpers.AddProtocolHeaders(httpContext.Response); var unimplementedMethod = httpContext.Request.RouteValues["unimplementedMethod"]?.ToString() ?? "<unknown>"; Log.MethodUnimplemented(logger, unimplementedMethod); GrpcEventSource.Log.CallUnimplemented(httpContext.Request.Path.Value); GrpcProtocolHelpers.SetStatus(GrpcProtocolHelpers.GetTrailersDestination(httpContext.Response), new Status(StatusCode.Unimplemented, "Method is unimplemented.")); return Task.CompletedTask; }); }
private static Task WriteMessageCoreAsync(this PipeWriter pipeWriter, byte[] messageData, HttpContextServerCallContext serverCallContext, bool flush) { Debug.Assert(serverCallContext.ResponseGrpcEncoding != null); var isCompressed = serverCallContext.CanWriteCompressed() && !string.Equals(serverCallContext.ResponseGrpcEncoding, GrpcProtocolConstants.IdentityGrpcEncoding, StringComparison.Ordinal); if (isCompressed) { messageData = GrpcProtocolHelpers.CompressMessage( serverCallContext.ResponseGrpcEncoding, serverCallContext.ServiceOptions.ResponseCompressionLevel, serverCallContext.ServiceOptions.CompressionProviders, messageData); } WriteHeader(pipeWriter, messageData.Length, isCompressed); pipeWriter.Write(messageData); if (flush) { var valueTask = pipeWriter.FlushAsync(); if (valueTask.IsCompletedSuccessfully) { // We do this to reset the underlying value task (which happens in GetResult()) valueTask.GetAwaiter().GetResult(); return(Task.CompletedTask); } return(valueTask.AsTask()); } return(Task.CompletedTask); }
public static async Task WriteMessageAsync <TResponse>(this PipeWriter pipeWriter, TResponse response, HttpContextServerCallContext serverCallContext, Action <TResponse, SerializationContext> serializer, bool canFlush) where TResponse : class { var logger = serverCallContext.Logger; try { GrpcServerLog.SendingMessage(logger); var serializationContext = serverCallContext.SerializationContext; serializer(response, serializationContext); var responsePayload = serializationContext.Payload; serializationContext.Payload = null; if (responsePayload == null) { throw new InvalidOperationException("Serialization did not return a payload."); } GrpcServerLog.SerializedMessage(serverCallContext.Logger, typeof(TResponse), responsePayload.Length); // Must call StartAsync before the first pipeWriter.GetSpan() in WriteHeader var httpResponse = serverCallContext.HttpContext.Response; if (!httpResponse.HasStarted) { await httpResponse.StartAsync(); } var canCompress = GrpcProtocolHelpers.CanWriteCompressed(serverCallContext.WriteOptions) && !string.Equals(serverCallContext.ResponseGrpcEncoding, GrpcProtocolConstants.IdentityGrpcEncoding, StringComparison.Ordinal); var isCompressed = false; if (canCompress) { Debug.Assert( serverCallContext.ServiceOptions.ResolvedCompressionProviders != null, "Compression providers should have been resolved for service."); if (TryCompressMessage( serverCallContext.Logger, serverCallContext.ResponseGrpcEncoding !, serverCallContext.ServiceOptions.ResponseCompressionLevel, serverCallContext.ServiceOptions.ResolvedCompressionProviders, responsePayload, out var result)) { responsePayload = result; isCompressed = true; } } if (responsePayload.Length > serverCallContext.ServiceOptions.MaxSendMessageSize) { throw new RpcException(SendingMessageExceedsLimitStatus); } WriteHeader(pipeWriter, responsePayload.Length, isCompressed); pipeWriter.Write(responsePayload); // Flush messages unless WriteOptions.Flags has BufferHint set var flush = canFlush && ((serverCallContext.WriteOptions?.Flags ?? default) & WriteFlags.BufferHint) != WriteFlags.BufferHint; if (flush) { serverCallContext.HasBufferedMessage = false; await pipeWriter.FlushAsync(); } else { // Set flag so buffered message will be written at the end serverCallContext.HasBufferedMessage = true; } GrpcServerLog.MessageSent(serverCallContext.Logger); GrpcEventSource.Log.MessageSent(); } catch (Exception ex) { GrpcServerLog.ErrorSendingMessage(logger, ex); throw; } }