using JsonRPC4.Common.Tools; using JsonRPC4.Router.Abstractions; using JsonRPC4.Router.Defaults; using JsonRPC4.Router.Utilities; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Linq; using System.Threading.Tasks; namespace JsonRPC4.Router { public class RpcHttpRouter : IRouter { private static readonly char[] encodingSeperators = new char[2] { ',', ' ' }; private IRpcMethodProvider methodProvider { get; } public RpcHttpRouter(IRpcMethodProvider methodProvider) { this.methodProvider = methodProvider; } public VirtualPathData GetVirtualPath(VirtualPathContext context) { return null; } public async Task RouteAsync(RouteContext context) { ILogger logger = context.HttpContext.RequestServices.GetService>(); try { RpcPath requestPath; if (!context.HttpContext.Request.Path.HasValue) { requestPath = null; goto IL_00d3; } if (RpcPath.TryParse(MemoryExtensions.AsSpan(context.HttpContext.Request.Path.Value), out requestPath)) { goto IL_00d3; } logger?.LogInformation("Could not parse the path '" + context.HttpContext.Request.Path.Value + "' for the request into an rpc path. Skipping rpc router middleware."); goto end_IL_0035; IL_00d3: logger?.LogInformation($"Rpc request with route '{requestPath}' started."); IRpcRequestHandler requestHandler = context.HttpContext.RequestServices.GetRequiredService(); IRouteContext routeContext = DefaultRouteContext.FromHttpContext(context.HttpContext, methodProvider); Stream writableStream = BuildWritableResponseStream(context.HttpContext); using (MemoryStream requestBody = new MemoryStream()) { await context.HttpContext.Request.Body.CopyToAsync(requestBody); requestBody.Position = 0L; if (!(await requestHandler.HandleRequestAsync(requestPath, requestBody, routeContext, writableStream))) { context.HttpContext.Response.StatusCode = 204; context.MarkAsHandled(); return; } } context.MarkAsHandled(); logger?.LogInformation("Rpc request complete"); end_IL_0035:; } catch (Exception ex) { string message = "Unknown exception occurred when trying to process Rpc request. Marking route unhandled"; logger?.LogException(ex, message); context.MarkAsHandled(); } } private Stream BuildWritableResponseStream(HttpContext httpContext) { httpContext.Response.ContentType = "application/json"; string text = httpContext.Request.Headers["Accept-Encoding"]; if (!string.IsNullOrWhiteSpace(text)) { IStreamCompressor service = httpContext.RequestServices.GetService(); if (service != null) { string[] array = text.Split(encodingSeperators, StringSplitOptions.RemoveEmptyEntries); foreach (string text2 in array) { if (service.TryGetCompressionStream(httpContext.Response.Body, text2, CompressionMode.Compress, out Stream compressedStream)) { httpContext.Response.Headers.Add("Content-Encoding", text2); return compressedStream; } } } } return httpContext.Response.Body; } } }