public RpcEndpointBuilder AddController(Type controllerType) { var attribute = controllerType.GetCustomAttribute <RpcRouteAttribute>(true); ReadOnlySpan <char> routePathString; if (attribute == null || attribute.RouteName == null) { if (controllerType.Name.EndsWith("Controller")) { routePathString = controllerType.Name.AsSpan(0, controllerType.Name.IndexOf("Controller")); } else { routePathString = controllerType.Name.AsSpan(); } } else { routePathString = attribute.RouteName.AsSpan(); } RpcPath routePath = RpcPath.Parse(routePathString); return(this.AddControllerWithCustomPath(controllerType, routePath)); }
/// <summary> /// Takes a route/http contexts and attempts to parse, invoke, respond to an Rpc request /// </summary> /// <param name="context">Route context</param> /// <returns>Task for async routing</returns> public async Task RouteAsync(RouteContext context) { try { RpcPath requestPath; if (!context.HttpContext.Request.Path.HasValue) { requestPath = RpcPath.Default; } else { requestPath = RpcPath.Parse(context.HttpContext.Request.Path.Value); } if (!requestPath.StartsWith(this.routeProvider.BaseRequestPath)) { this.logger?.LogTrace("Request did not match the base request path. Skipping rpc router."); return; } HashSet <RpcPath> availableRoutes = this.routeProvider.GetRoutes(); if (!availableRoutes.Any()) { this.logger?.LogDebug($"Request matched base request path but no routes."); return; } this.logger?.LogInformation($"Rpc request route '{requestPath}' matched."); Stream contentStream = context.HttpContext.Request.Body; string jsonString; if (contentStream == null) { jsonString = null; } else { using (StreamReader streamReader = new StreamReader(contentStream)) { jsonString = streamReader.ReadToEnd().Trim(); } } var routeContext = DefaultRouteContext.FromHttpContext(context.HttpContext, this.routeProvider); string responseJson = await this.routeHandler.HandleRequestAsync(requestPath, jsonString, routeContext); if (responseJson == null) { //No response required return; } bool responseSet = false; string acceptEncoding = context.HttpContext.Request.Headers["Accept-Encoding"]; if (!string.IsNullOrWhiteSpace(acceptEncoding)) { string[] encodings = acceptEncoding.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); foreach (string encoding in encodings) { bool haveType = Enum.TryParse(encoding, true, out CompressionType compressionType); if (!haveType) { continue; } context.HttpContext.Response.Headers.Add("Content-Encoding", new[] { encoding }); this.compressor.CompressText(context.HttpContext.Response.Body, responseJson, Encoding.UTF8, compressionType); responseSet = true; break; } } if (!responseSet) { Stream responseStream = context.HttpContext.Response.Body; using (StreamWriter streamWriter = new StreamWriter(responseStream)) { await streamWriter.WriteAsync(responseJson); } } context.MarkAsHandled(); this.logger?.LogInformation("Rpc request complete"); } catch (Exception ex) { string errorMessage = "Unknown exception occurred when trying to process Rpc request. Marking route unhandled"; this.logger?.LogException(ex, errorMessage); context.MarkAsHandled(); } }