private void AddMethodCore <TRequest, TResponse>( Method <TRequest, TResponse> method, HttpRule httpRule, string pattern, string httpVerb, string body, string responseBody, MethodDescriptor methodDescriptor) where TRequest : class where TResponse : class { try { if (!pattern.StartsWith('/')) { // This validation is consistent with grpc-gateway code generation. // We should match their validation to be a good member of the eco-system. throw new InvalidOperationException($"Path template must start with /: {pattern}"); } var(invoker, metadata) = CreateModelCore <UnaryServerMethod <TService, TRequest, TResponse> >( method.Name, new[] { typeof(TRequest), typeof(ServerCallContext) }, httpVerb, httpRule, methodDescriptor); var methodContext = global::Grpc.Shared.Server.MethodOptions.Create(new[] { _globalOptions, _serviceOptions }); var routePattern = RoutePatternFactory.Parse(pattern); var routeParameterDescriptors = ServiceDescriptorHelpers.ResolveRouteParameterDescriptors(routePattern, methodDescriptor.InputType); ServiceDescriptorHelpers.ResolveBodyDescriptor(body, methodDescriptor, out var bodyDescriptor, out var bodyFieldDescriptors, out var bodyDescriptorRepeated); FieldDescriptor?responseBodyDescriptor = null; if (!string.IsNullOrEmpty(responseBody)) { responseBodyDescriptor = methodDescriptor.OutputType.FindFieldByName(responseBody); if (responseBodyDescriptor == null) { throw new InvalidOperationException($"Couldn't find matching field for response body '{responseBody}' on {methodDescriptor.OutputType.Name}."); } } var unaryInvoker = new UnaryServerMethodInvoker <TService, TRequest, TResponse>(invoker, method, methodContext, _serviceActivator); var unaryServerCallHandler = new UnaryServerCallHandler <TService, TRequest, TResponse>( unaryInvoker, responseBodyDescriptor, bodyDescriptor, bodyDescriptorRepeated, bodyFieldDescriptors, routeParameterDescriptors); _context.AddMethod <TRequest, TResponse>(method, routePattern, metadata, unaryServerCallHandler.HandleCallAsync); } catch (Exception ex) { throw new InvalidOperationException($"Error binding {method.Name} on {typeof(TService).Name} to HTTP API.", ex); } }
public UnaryServerCallHandler( UnaryServerMethodInvoker <TService, TRequest, TResponse> invoker, ILoggerFactory loggerFactory) : base(invoker, loggerFactory) { _invoker = invoker; }
public UnaryServerCallHandler( UnaryServerMethodInvoker <TService, TRequest, TResponse> unaryMethodInvoker, FieldDescriptor?responseBodyDescriptor, MessageDescriptor?bodyDescriptor, bool bodyDescriptorRepeated, List <FieldDescriptor>?bodyFieldDescriptors, Dictionary <string, List <FieldDescriptor> > routeParameterDescriptors, GrpcHttpApiOptions httpApiOptions) { _unaryMethodInvoker = unaryMethodInvoker; _responseBodyDescriptor = responseBodyDescriptor; _bodyDescriptor = bodyDescriptor; _bodyDescriptorRepeated = bodyDescriptorRepeated; _bodyFieldDescriptors = bodyFieldDescriptors; if (_bodyFieldDescriptors != null) { _bodyFieldDescriptorsPath = string.Join('.', _bodyFieldDescriptors.Select(d => d.Name)); } if (_bodyDescriptorRepeated && _bodyFieldDescriptors != null) { _resolvedBodyFieldDescriptors = _bodyFieldDescriptors.Take(_bodyFieldDescriptors.Count - 1).ToList(); } _routeParameterDescriptors = routeParameterDescriptors; _jsonFormatter = httpApiOptions.JsonFormatter; _jsonParser = httpApiOptions.JsonParser; _pathDescriptorsCache = new ConcurrentDictionary <string, List <FieldDescriptor>?>(StringComparer.Ordinal); }
public async Task Invoke_AwaitedSuccess_ReleaseCalled() { // Arrange var methodTcs = new TaskCompletionSource <TestMessage>(TaskCreationOptions.RunContinuationsAsynchronously); var methodResult = new TestMessage(); var serviceActivator = new TestGrpcServiceActivator <TestService>(); var invoker = new UnaryServerMethodInvoker <TestService, TestMessage, TestMessage>( (service, reader, context) => methodTcs.Task, new Method <TestMessage, TestMessage>(MethodType.Unary, "test", "test", _marshaller, _marshaller), HttpContextServerCallContextHelper.CreateMethodOptions(), serviceActivator); var httpContext = HttpContextHelpers.CreateContext(); // Act var task = invoker.Invoke(httpContext, HttpContextServerCallContextHelper.CreateServerCallContext(), new TestMessage()); Assert.False(task.IsCompleted); methodTcs.SetResult(methodResult); var awaitedResult = await task; // Assert Assert.AreEqual(methodResult, awaitedResult); Assert.True(serviceActivator.Released); }
public UnaryServerCallHandler( UnaryServerMethodInvoker <TService, TRequest, TResponse> unaryMethodInvoker, ILoggerFactory loggerFactory, CallHandlerDescriptorInfo descriptorInfo, JsonSerializerOptions options) : base(unaryMethodInvoker, loggerFactory, descriptorInfo, options) { _invoker = unaryMethodInvoker; }
public UnaryServerCallHandler <TService, TRequest, TResponse> CreateUnary <TRequest, TResponse>(Method <TRequest, TResponse> method, UnaryServerMethod <TService, TRequest, TResponse> invoker) where TRequest : class where TResponse : class { var options = CreateMethodOptions(); var methodInvoker = new UnaryServerMethodInvoker <TService, TRequest, TResponse>(invoker, method, options, _serviceActivator); return(new UnaryServerCallHandler <TService, TRequest, TResponse>(methodInvoker, _loggerFactory)); }
public UnaryServerCallHandler( UnaryServerMethodInvoker <TService, TRequest, TResponse> unaryMethodInvoker, FieldDescriptor?responseBodyDescriptor, MessageDescriptor?bodyDescriptor, FieldDescriptor?bodyFieldDescriptor, Dictionary <string, List <FieldDescriptor> > routeParameterDescriptors) { _unaryMethodInvoker = unaryMethodInvoker; _responseBodyDescriptor = responseBodyDescriptor; _bodyDescriptor = bodyDescriptor; _bodyFieldDescriptor = bodyFieldDescriptor; _routeParameterDescriptors = routeParameterDescriptors; _queryParameterDescriptors = new ConcurrentDictionary <string, List <FieldDescriptor> >(StringComparer.Ordinal); }
private static UnaryServerCallHandler <HttpApiGreeterService, HelloRequest, HelloReply> CreateCallHandler( UnaryServerMethod <HttpApiGreeterService, HelloRequest, HelloReply> invoker, FieldDescriptor?responseBodyDescriptor = null, Dictionary <string, List <FieldDescriptor> >?routeParameterDescriptors = null, MessageDescriptor?bodyDescriptor = null, FieldDescriptor?bodyFieldDescriptor = null) { var unaryServerCallInvoker = new UnaryServerMethodInvoker <HttpApiGreeterService, HelloRequest, HelloReply>( invoker, CreateServiceMethod <HelloRequest, HelloReply>("TestMethodName", HelloRequest.Parser, HelloReply.Parser), Shared.Server.MethodOptions.Create(new[] { new GrpcServiceOptions() }), new TestGrpcServiceActivator <HttpApiGreeterService>()); return(new UnaryServerCallHandler <HttpApiGreeterService, HelloRequest, HelloReply>( unaryServerCallInvoker, responseBodyDescriptor, bodyDescriptor, bodyFieldDescriptor, routeParameterDescriptors ?? new Dictionary <string, List <FieldDescriptor> >())); }
public async Task Invoke_SuccessAwaitedRelease_ReleaseCalled() { // Arrange var releaseTcs = new TaskCompletionSource <object?>(TaskCreationOptions.RunContinuationsAsynchronously); var serviceActivator = new TcsGrpcServiceActivator <TestService>(releaseTcs); var invoker = new UnaryServerMethodInvoker <TestService, TestMessage, TestMessage>( (service, reader, context) => Task.FromResult(new TestMessage()), new Method <TestMessage, TestMessage>(MethodType.Unary, "test", "test", _marshaller, _marshaller), HttpContextServerCallContextHelper.CreateMethodOptions(), serviceActivator); var httpContext = HttpContextHelpers.CreateContext(); // Act var task = invoker.Invoke(httpContext, HttpContextServerCallContextHelper.CreateServerCallContext(), new TestMessage()); Assert.False(task.IsCompleted); releaseTcs.SetResult(null); await task; // Assert Assert.True(serviceActivator.Released); }
private void AddMethodCore <TRequest, TResponse>( Method <TRequest, TResponse> method, string pattern, string httpVerb, string body, string responseBody, MethodDescriptor methodDescriptor) where TRequest : class where TResponse : class { try { var(invoker, metadata) = CreateModelCore <UnaryServerMethod <TService, TRequest, TResponse> >( method.Name, new[] { typeof(TRequest), typeof(ServerCallContext) }, httpVerb); var methodContext = global::Grpc.Shared.Server.MethodOptions.Create(new[] { _globalOptions, _serviceOptions }); var routeParameterDescriptors = ResolveRouteParameterDescriptors(pattern, methodDescriptor.InputType); MessageDescriptor?bodyDescriptor = null; FieldDescriptor? bodyFieldDescriptor = null; if (!string.IsNullOrEmpty(body)) { if (!string.Equals(body, "*", StringComparison.Ordinal)) { bodyFieldDescriptor = methodDescriptor.InputType.FindFieldByName(body); if (bodyFieldDescriptor == null) { throw new InvalidOperationException($"Couldn't find matching field for body '{body}' on {methodDescriptor.InputType.Name}."); } bodyDescriptor = bodyFieldDescriptor.ContainingType; } else { bodyDescriptor = methodDescriptor.InputType; } } FieldDescriptor?responseBodyDescriptor = null; if (!string.IsNullOrEmpty(responseBody)) { responseBodyDescriptor = methodDescriptor.OutputType.FindFieldByName(responseBody); if (responseBodyDescriptor == null) { throw new InvalidOperationException($"Couldn't find matching field for response body '{responseBody}' on {methodDescriptor.OutputType.Name}."); } } var unaryInvoker = new UnaryServerMethodInvoker <TService, TRequest, TResponse>(invoker, method, methodContext, _serviceActivator); var unaryServerCallHandler = new UnaryServerCallHandler <TService, TRequest, TResponse>( unaryInvoker, responseBodyDescriptor, bodyDescriptor, bodyFieldDescriptor, routeParameterDescriptors); _context.AddMethod <TRequest, TResponse>(method, RoutePatternFactory.Parse(pattern), metadata, unaryServerCallHandler.HandleCallAsync); } catch (Exception ex) { throw new InvalidOperationException($"Error binding {method.Name} on {typeof(TService).Name} to HTTP API.", ex); } }
private void AddMethodCore <TRequest, TResponse>( Method <TRequest, TResponse> method, string pattern, string httpVerb, string body, string responseBody, MethodDescriptor methodDescriptor) where TRequest : class where TResponse : class { try { if (!pattern.StartsWith('/')) { // This validation is consistent with grpc-gateway code generation. // We should match their validation to be a good member of the eco-system. throw new InvalidOperationException($"Path template must start with /: {pattern}"); } var(invoker, metadata) = CreateModelCore <UnaryServerMethod <TService, TRequest, TResponse> >( method.Name, new[] { typeof(TRequest), typeof(ServerCallContext) }, httpVerb); var methodContext = global::Grpc.Shared.Server.MethodOptions.Create(new[] { _globalOptions, _serviceOptions }); var routeParameterDescriptors = ResolveRouteParameterDescriptors(pattern, methodDescriptor.InputType); MessageDescriptor? bodyDescriptor = null; List <FieldDescriptor>?bodyFieldDescriptors = null; var bodyDescriptorRepeated = false; if (!string.IsNullOrEmpty(body)) { if (!string.Equals(body, "*", StringComparison.Ordinal)) { if (!ServiceDescriptorHelpers.TryResolveDescriptors(methodDescriptor.InputType, body, out bodyFieldDescriptors)) { throw new InvalidOperationException($"Couldn't find matching field for body '{body}' on {methodDescriptor.InputType.Name}."); } var leafDescriptor = bodyFieldDescriptors.Last(); if (leafDescriptor.IsRepeated) { // A repeating field isn't a message type. The JSON parser will parse using the containing // type to get the repeating collection. bodyDescriptor = leafDescriptor.ContainingType; bodyDescriptorRepeated = true; } else { bodyDescriptor = leafDescriptor.MessageType; } } else { bodyDescriptor = methodDescriptor.InputType; } } FieldDescriptor?responseBodyDescriptor = null; if (!string.IsNullOrEmpty(responseBody)) { responseBodyDescriptor = methodDescriptor.OutputType.FindFieldByName(responseBody); if (responseBodyDescriptor == null) { throw new InvalidOperationException($"Couldn't find matching field for response body '{responseBody}' on {methodDescriptor.OutputType.Name}."); } } var unaryInvoker = new UnaryServerMethodInvoker <TService, TRequest, TResponse>(invoker, method, methodContext, _serviceActivator); var unaryServerCallHandler = new UnaryServerCallHandler <TService, TRequest, TResponse>( unaryInvoker, responseBodyDescriptor, bodyDescriptor, bodyDescriptorRepeated, bodyFieldDescriptors, routeParameterDescriptors); _context.AddMethod <TRequest, TResponse>(method, RoutePatternFactory.Parse(pattern), metadata, unaryServerCallHandler.HandleCallAsync); } catch (Exception ex) { throw new InvalidOperationException($"Error binding {method.Name} on {typeof(TService).Name} to HTTP API.", ex); } }