Example #1
0
		/// <param name="serverConfig">Configuration data for the server</param>
		/// <param name="invoker">Component that invokes Rpc requests target methods and returns a response</param>
		/// <param name="parser">Component that parses Http requests into Rpc requests</param>
		/// <param name="compressor">Component that compresses Rpc responses</param>
		/// <param name="logger">Component that logs actions from the router</param>
		/// <param name="routeProvider">Provider that allows the retrieval of all configured routes</param>
		public RpcRouter(IOptions<RpcServerConfiguration> serverConfig, IRpcInvoker invoker, IRpcParser parser, IRpcCompressor compressor, ILogger<RpcRouter> logger,
			IRpcRouteProvider routeProvider)
		{
			if (serverConfig == null)
			{
				throw new ArgumentNullException(nameof(serverConfig));
			}
			if (invoker == null)
			{
				throw new ArgumentNullException(nameof(invoker));
			}
			if (parser == null)
			{
				throw new ArgumentNullException(nameof(parser));
			}
			if (compressor == null)
			{
				throw new ArgumentNullException(nameof(compressor));
			}
			if (routeProvider == null)
			{
				throw new ArgumentNullException(nameof(routeProvider));
			}
			this.serverConfig = serverConfig;
			this.invoker = invoker;
			this.parser = parser;
			this.compressor = compressor;
			this.logger = logger;
			this.routeProvider = routeProvider;
		}
Example #2
0
        /// <summary>
        /// Extension method to use the JsonRpc router in the Asp.Net pipeline
        /// </summary>
        /// <param name="app"><see cref="IApplicationBuilder"/> that is supplied by Asp.Net</param>
        /// <param name="configureRouter">Action to configure the router properties</param>
        /// <returns><see cref="IApplicationBuilder"/> that includes the Basic auth middleware</returns>
        public static IApplicationBuilder UseJsonRpc(this IApplicationBuilder app, Action <RpcRouterConfiguration> configureRouter)
        {
            if (app == null)
            {
                throw new ArgumentNullException(nameof(app));
            }
            if (configureRouter == null)
            {
                throw new ArgumentNullException(nameof(configureRouter));
            }

            RpcRouterConfiguration configuration = new RpcRouterConfiguration();

            configureRouter.Invoke(configuration);
            if (configuration.Routes.Count < 1)
            {
                throw new RpcConfigurationException("At least on class/route must be configured for router to work.");
            }

            IRpcInvoker    rpcInvoker    = app.ApplicationServices.GetRequiredService <IRpcInvoker>();
            IRpcParser     rpcParser     = app.ApplicationServices.GetRequiredService <IRpcParser>();
            IRpcCompressor rpcCompressor = app.ApplicationServices.GetRequiredService <IRpcCompressor>();
            ILoggerFactory loggerFactory = app.ApplicationServices.GetService <ILoggerFactory>();
            ILogger        logger        = loggerFactory?.CreateLogger <RpcRouter>();

            app.UseRouter(new RpcRouter(configuration, rpcInvoker, rpcParser, rpcCompressor, logger));
            return(app);
        }
Example #3
0
 /// <param name="compressor">Component that compresses Rpc responses</param>
 /// <param name="logger">Component that logs actions from the router</param>
 /// <param name="routeProvider">Provider that allows the retrieval of all configured routes</param>
 public RpcRouter(ILogger <RpcRouter> logger, IRpcCompressor compressor, IRpcRouteProvider routeProvider, IRpcRequestHandler routeHandler)
 {
     this.logger        = logger;
     this.compressor    = compressor ?? throw new ArgumentNullException(nameof(compressor));
     this.routeProvider = routeProvider ?? throw new ArgumentNullException(nameof(routeProvider));
     this.routeHandler  = routeHandler ?? throw new ArgumentNullException(nameof(routeHandler));
 }
Example #4
0
 /// <param name="configuration">Configuration data for the router</param>
 /// <param name="invoker">Component that invokes Rpc requests target methods and returns a response</param>
 /// <param name="parser">Component that parses Http requests into Rpc requests</param>
 /// <param name="compressor">Component that compresses Rpc responses</param>
 /// <param name="logger">Component that logs actions from the router</param>
 public RpcRouter(RpcRouterConfiguration configuration, IRpcInvoker invoker, IRpcParser parser, IRpcCompressor compressor, ILogger logger)
 {
     if (configuration == null)
     {
         throw new ArgumentNullException(nameof(configuration));
     }
     if (invoker == null)
     {
         throw new ArgumentNullException(nameof(invoker));
     }
     if (parser == null)
     {
         throw new ArgumentNullException(nameof(parser));
     }
     if (compressor == null)
     {
         throw new ArgumentNullException(nameof(compressor));
     }
     this.configuration = configuration;
     this.invoker       = invoker;
     this.parser        = parser;
     this.compressor    = compressor;
     this.logger        = logger;
 }
Example #5
0
 /// <param name="serverConfig">Configuration data for the server</param>
 /// <param name="invoker">Component that invokes Rpc requests target methods and returns a response</param>
 /// <param name="parser">Component that parses Http requests into Rpc requests</param>
 /// <param name="compressor">Component that compresses Rpc responses</param>
 /// <param name="logger">Component that logs actions from the router</param>
 /// <param name="routeProvider">Provider that allows the retrieval of all configured routes</param>
 public RpcRouter(IOptions <RpcServerConfiguration> serverConfig, IRpcInvoker invoker, IRpcParser parser, IRpcCompressor compressor, ILogger <RpcRouter> logger,
                  IRpcRouteProvider routeProvider)
 {
     if (serverConfig == null)
     {
         throw new ArgumentNullException(nameof(serverConfig));
     }
     if (invoker == null)
     {
         throw new ArgumentNullException(nameof(invoker));
     }
     if (parser == null)
     {
         throw new ArgumentNullException(nameof(parser));
     }
     if (compressor == null)
     {
         throw new ArgumentNullException(nameof(compressor));
     }
     if (routeProvider == null)
     {
         throw new ArgumentNullException(nameof(routeProvider));
     }
     this.serverConfig  = serverConfig;
     this.invoker       = invoker;
     this.parser        = parser;
     this.compressor    = compressor;
     this.logger        = logger;
     this.routeProvider = routeProvider;
 }
Example #6
0
        /// <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)
        {
            ILogger <RpcRouter> logger = context.HttpContext.RequestServices.GetService <ILogger <RpcRouter> >();

            try
            {
                RpcPath requestPath;
                if (!context.HttpContext.Request.Path.HasValue)
                {
                    requestPath = RpcPath.Default;
                }
                else
                {
                    if (!RpcPath.TryParse(context.HttpContext.Request.Path.Value, out requestPath))
                    {
                        logger?.LogInformation($"Could not parse the path '{context.HttpContext.Request.Path.Value}' for the " +
                                               $"request into an rpc path. Skipping rpc router middleware.");
                        return;
                    }
                }
                if (!requestPath.TryRemoveBasePath(this.routeProvider.BaseRequestPath, out requestPath))
                {
                    logger?.LogTrace("Request did not match the base request path. Skipping rpc router.");
                    return;
                }
                HashSet <RpcPath> availableRoutes = this.routeProvider.GetRoutes();
                if (!availableRoutes.Any())
                {
                    logger?.LogDebug($"Request matched base request path but no routes.");
                    return;
                }
                logger?.LogInformation($"Rpc request route '{requestPath}' matched.");

                Stream contentStream = context.HttpContext.Request.Body;

                string jsonString;
                if (contentStream == null)
                {
                    jsonString = null;
                }
                else
                {
                    StreamReader streamReader = new StreamReader(contentStream);
                    jsonString = streamReader.ReadToEnd().Trim();
                }

                var    requestHandler = context.HttpContext.RequestServices.GetRequiredService <IRpcRequestHandler>();
                var    routeContext   = DefaultRouteContext.FromHttpContext(context.HttpContext, this.routeProvider);
                string responseJson   = await requestHandler.HandleRequestAsync(requestPath, jsonString, routeContext);

                if (responseJson == null)
                {
                    //No response required
                    return;
                }

                context.HttpContext.Response.ContentType = "application/json";

                bool   responseSet    = false;
                string acceptEncoding = context.HttpContext.Request.Headers["Accept-Encoding"];
                if (!string.IsNullOrWhiteSpace(acceptEncoding))
                {
                    IRpcCompressor compressor = context.HttpContext.RequestServices.GetService <IRpcCompressor>();
                    if (compressor != null)
                    {
                        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 });
                            compressor.CompressText(context.HttpContext.Response.Body, responseJson, Encoding.UTF8, compressionType);
                            responseSet = true;
                            break;
                        }
                    }
                }
                if (!responseSet)
                {
                    await context.HttpContext.Response.WriteAsync(responseJson);
                }

                context.MarkAsHandled();

                logger?.LogInformation("Rpc request complete");
            }
            catch (Exception ex)
            {
                string errorMessage = "Unknown exception occurred when trying to process Rpc request. Marking route unhandled";
                logger?.LogException(ex, errorMessage);
                context.MarkAsHandled();
            }
        }