Esempio n. 1
0
		/// <summary>
		/// Call the incoming Rpc requests methods and gives the appropriate respones
		/// </summary>
		/// <param name="requests">List of Rpc requests</param>
		/// <param name="route">Rpc route that applies to the current request</param>
		/// <param name="httpContext">The context of the current http request</param>
		/// <param name="jsonSerializerSettings">Json serialization settings that will be used in serialization and deserialization for rpc requests</param>
		/// <returns>List of Rpc responses for the requests</returns>
		public async Task<List<RpcResponse>> InvokeBatchRequestAsync(List<RpcRequest> requests, RpcRoute route, HttpContext httpContext, JsonSerializerSettings jsonSerializerSettings = null)
		{
			this.logger?.LogDebug($"Invoking '{requests.Count}' batch requests");
			var invokingTasks = new List<Task<RpcResponse>>();
			foreach (RpcRequest request in requests)
			{
				Task<RpcResponse> invokingTask = Task.Run(async () => await this.InvokeRequestAsync(request, route, httpContext, jsonSerializerSettings));
				if (request.Id != null)
				{
					//Only wait for non-notification requests
					invokingTasks.Add(invokingTask);
				}
			}

			await Task.WhenAll(invokingTasks.ToArray());

			List<RpcResponse> responses = invokingTasks
				.Select(t => t.Result)
				.Where(r => r != null)
				.ToList();

			this.logger?.LogDebug($"Finished '{requests.Count}' batch requests");

			return responses;
		}
Esempio n. 2
0
        /// <summary>
        /// Call the incoming Rpc requests methods and gives the appropriate respones
        /// </summary>
        /// <param name="requests">List of Rpc requests</param>
        /// <param name="route">Rpc route that applies to the current request</param>
        /// <param name="serviceProvider">(Optional)IoC Container for rpc method controllers</param>
        /// <param name="jsonSerializerSettings">Json serialization settings that will be used in serialization and deserialization for rpc requests</param>
        /// <returns>List of Rpc responses for the requests</returns>
        public List <RpcResponse> InvokeBatchRequest(List <RpcRequest> requests, RpcRoute route, IServiceProvider serviceProvider = null, JsonSerializerSettings jsonSerializerSettings = null)
        {
            this.Logger?.LogDebug($"Invoking '{requests.Count}' batch requests");
            var invokingTasks = new List <Task <RpcResponse> >();

            foreach (RpcRequest request in requests)
            {
                Task <RpcResponse> invokingTask = Task.Run(() => this.InvokeRequest(request, route, serviceProvider, jsonSerializerSettings));
                if (request.Id != null)
                {
                    //Only wait for non-notification requests
                    invokingTasks.Add(invokingTask);
                }
            }

            Task.WaitAll(invokingTasks.Cast <Task>().ToArray());

            List <RpcResponse> responses = invokingTasks
                                           .Select(t => t.Result)
                                           .Where(r => r != null)
                                           .ToList();

            this.Logger?.LogDebug($"Finished '{requests.Count}' batch requests");

            return(responses);
        }
Esempio n. 3
0
        /// <summary>
        /// Indicates if the incoming request matches any predefined routes
        /// </summary>
        /// <param name="requestUrl">The current request url</param>
        /// <param name="route">The matching route corresponding to the request url if found, otherwise it is null</param>
        /// <param name="routeProvider">Provider that allows the retrieval of all configured routes</param>
        /// <returns>True if the request url matches any Rpc routes, otherwise False</returns>
        public bool MatchesRpcRoute(IRpcRouteProvider routeProvider, string requestUrl, out RpcRoute route)
        {
            if (requestUrl == null)
            {
                throw new ArgumentNullException(nameof(requestUrl));
            }
            this.logger?.LogDebug($"Attempting to match Rpc route for the request url '{requestUrl}'");
            RpcPath requestPath = RpcPath.Parse(requestUrl);
            this.logger?.LogTrace($"Request path: {requestPath}");

            foreach (RpcRoute rpcRoute in routeProvider.GetRoutes())
            {
                RpcPath routePath = RpcPath.Parse(rpcRoute.Name);
                this.logger?.LogTrace($"Trying to match against route - Name: {rpcRoute.Name}, Path: {routePath}");
                if (requestPath == routePath)
                {
                    this.logger?.LogDebug($"Matched the request url '{requestUrl}' to the route '{rpcRoute.Name}'");
                    route = rpcRoute;
                    return true;
                }

            }
            this.logger?.LogDebug($"Failed to match the request url '{requestUrl}' to a route");
            route = null;
            return false;
        }
Esempio n. 4
0
        public bool MatchesRpcRoute(RpcRouteCollection routes, string requestUrl, out RpcRoute route)
        {
            if (routes == null)
            {
                throw new ArgumentNullException(nameof(routes));
            }
            if (requestUrl == null)
            {
                throw new ArgumentNullException(nameof(requestUrl));
            }
            this.Logger?.LogVerbose($"Attempting to match Rpc route for the request url '{requestUrl}'");
            RpcPath requestPath = RpcPath.Parse(requestUrl);
            RpcPath routePrefix = RpcPath.Parse(routes.RoutePrefix);

            foreach (RpcRoute rpcRoute in routes)
            {
                RpcPath routePath = RpcPath.Parse(rpcRoute.Name);
                routePath = routePrefix.Add(routePath);
                if (requestPath == routePath)
                {
                    this.Logger?.LogVerbose($"Matched the request url '{requestUrl}' to the route '{rpcRoute.Name}'");
                    route = rpcRoute;
                    return(true);
                }
            }
            this.Logger?.LogVerbose($"Failed to match the request url '{requestUrl}' to a route");
            route = null;
            return(false);
        }
        public RpcResponseBase InvokeRequest(RpcRequest request, RpcRoute route)
        {
            try
            {
                if (request == null)
                {
                    throw new ArgumentNullException(nameof(request));
                }
                if (route == null)
                {
                    throw new ArgumentNullException(nameof(route));
                }
            }
            catch (ArgumentNullException ex)             // Dont want to throw any exceptions when doing async requests
            {
                return(this.GetUnknownExceptionReponse(request, ex));
            }

            this.Logger?.LogVerbose($"Invoking request with id '{request.Id}'");
            RpcResponseBase rpcResponse;

            try
            {
                if (!string.Equals(request.JsonRpcVersion, "2.0"))
                {
                    throw new RpcInvalidRequestException("Request must be jsonrpc version '2.0'");
                }

                object[]  parameterList;
                RpcMethod rpcMethod = this.GetMatchingMethod(route, request, out parameterList);

                this.Logger?.LogVerbose($"Attempting to invoke method '{request.Method}'");
                object result = rpcMethod.Invoke(parameterList);
                this.Logger?.LogVerbose($"Finished invoking method '{request.Method}'");

                rpcResponse = new RpcResultResponse(request.Id, result);
            }
            catch (RpcException ex)
            {
                this.Logger?.LogError("An Rpc error occurred. Returning an Rpc error response", ex);
                RpcError error = new RpcError(ex);
                rpcResponse = new RpcErrorResponse(request.Id, error);
            }
            catch (Exception ex)
            {
                rpcResponse = this.GetUnknownExceptionReponse(request, ex);
            }

            if (request.Id != null)
            {
                this.Logger?.LogVerbose($"Finished request with id '{request.Id}'");
                //Only give a response if there is an id
                return(rpcResponse);
            }
            this.Logger?.LogVerbose($"Finished request with no id. Not returning a response");
            return(null);
        }
Esempio n. 6
0
        public void InvokeRequest_AmbiguousRequest_ErrorResponse()
        {
            RpcRequest stringRequest = new RpcRequest("1", "AmbiguousMethod", 1);
            RpcRoute   route         = new RpcRoute();

            route.AddClass <TestRouteClass>();
            IRpcInvoker invoker  = new DefaultRpcInvoker();
            RpcResponse response = invoker.InvokeRequest(stringRequest, route);

            Assert.NotNull(response.Error);
            Assert.Equal(response.Error.Code, RpcErrorCode.AmbiguousMethod);
        }
Esempio n. 7
0
        public void InvokeRequest_StringParam_ParseAsGuidType()
        {
            Guid       randomGuid    = Guid.NewGuid();
            RpcRequest stringRequest = new RpcRequest("1", "GuidTypeMethod", randomGuid.ToString());

            RpcRoute route = new RpcRoute();

            route.AddClass <TestRouteClass>();
            IRpcInvoker invoker        = new DefaultRpcInvoker();
            RpcResponse stringResponse = invoker.InvokeRequest(stringRequest, route);


            Assert.Equal(stringResponse.Result, randomGuid);
        }
Esempio n. 8
0
        /// <summary>
        /// Gets all the predefined Rpc methods for a Rpc route
        /// </summary>
        /// <param name="route">The route to get Rpc methods for</param>
        /// <param name="serviceProvider">(Optional) IoC Container for rpc method controllers</param>
        /// <param name="jsonSerializerSettings">Json serialization settings that will be used in serialization and deserialization for rpc requests</param>
        /// <returns>List of Rpc methods for the specified Rpc route</returns>
        private static List <RpcMethod> GetRpcMethods(RpcRoute route, IServiceProvider serviceProvider = null, JsonSerializerSettings jsonSerializerSettings = null)
        {
            List <RpcMethod> rpcMethods = new List <RpcMethod>();

            foreach (Type type in route.GetClasses())
            {
                MethodInfo[] publicMethods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance);
                foreach (MethodInfo publicMethod in publicMethods)
                {
                    RpcMethod rpcMethod = new RpcMethod(type, route, publicMethod, serviceProvider, jsonSerializerSettings);
                    rpcMethods.Add(rpcMethod);
                }
            }
            return(rpcMethods);
        }
Esempio n. 9
0
        public void MatchesRpcRoute_DifferentRoutes_Valid(string requestUrl, string availableRouteName, bool shouldMatch)
        {
            RpcRoute           route  = new RpcRoute(availableRouteName);
            RpcRouteCollection routes = new RpcRouteCollection {
                route
            };

            DefaultRpcParser parser = new DefaultRpcParser();
            RpcRoute         matchedRoute;
            bool             isMatch = parser.MatchesRpcRoute(routes, requestUrl, out matchedRoute);

            Assert.Equal(isMatch, shouldMatch);
            Assert.Equal(matchedRoute != null, shouldMatch);
            Assert.Equal(route == matchedRoute, shouldMatch);
        }
        private static List <RpcMethod> GetRpcMethods(RpcRoute route)
        {
            List <RpcMethod> rpcMethods = new List <RpcMethod>();

            foreach (Type type in route.GetClasses())
            {
                MethodInfo[] publicMethods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
                foreach (MethodInfo publicMethod in publicMethods)
                {
                    RpcMethod rpcMethod = new RpcMethod(type, route, publicMethod);
                    rpcMethods.Add(rpcMethod);
                }
            }
            return(rpcMethods);
        }
        public void InvokeRequest_AsyncMethod_Valid()
        {
            RpcRequest stringRequest = new RpcRequest("1", "2.0", "AddAsync", 1, 1);
            RpcRoute   route         = new RpcRoute();

            route.AddClass <TestRouteClass>();
            IRpcInvoker invoker = new DefaultRpcInvoker();

            RpcResponseBase response = invoker.InvokeRequest(stringRequest, route);

            RpcResultResponse resultResponse = Assert.IsType <RpcResultResponse>(response);

            Assert.NotNull(resultResponse.Result);
            Assert.Equal(resultResponse.Result, 2);
        }
Esempio n. 12
0
        public async Task InvokeRequest_AmbiguousRequest_ErrorResponse()
        {
            RpcRequest stringRequest = new RpcRequest("1", "AmbiguousMethod", 1);


            var routeCriteria = new List <RouteCriteria>();

            routeCriteria.Add(new RouteCriteria(typeof(TestRouteClass)));
            RpcRoute          route        = new RpcRoute(routeCriteria);
            IRouteContext     routeContext = this.GetRouteContext();
            DefaultRpcInvoker invoker      = this.GetInvoker();
            RpcResponse       response     = await invoker.InvokeRequestAsync(stringRequest, route, routeContext);

            Assert.NotNull(response.Error);
            Assert.Equal(response.Error.Code, (int)RpcErrorCode.MethodNotFound);
        }
        public void InvokeRequest_Int64RequestParam_ConvertToInt32Param()
        {
            RpcRequest stringRequest = new RpcRequest("1", "2.0", "IntParameter", (long)1);
            RpcRoute   route         = new RpcRoute();

            route.AddClass <TestRouteClass>();
            IRpcInvoker invoker = new DefaultRpcInvoker();

            RpcResponseBase response = invoker.InvokeRequest(stringRequest, route);

            RpcResultResponse resultResponse = Assert.IsType <RpcResultResponse>(response);

            Assert.NotNull(resultResponse.Result);
            Assert.IsType <int>(resultResponse.Result);
            Assert.Equal(resultResponse.Result, 1);
        }
Esempio n. 14
0
        public async Task InvokeRequest_StringParam_ParseAsGuidType()
        {
            Guid       randomGuid    = Guid.NewGuid();
            RpcRequest stringRequest = new RpcRequest("1", "GuidTypeMethod", randomGuid.ToString());

            var routeCriteria = new List <RouteCriteria>();

            routeCriteria.Add(new RouteCriteria(typeof(TestRouteClass)));
            RpcRoute route = new RpcRoute(routeCriteria);

            IRouteContext     routeContext   = this.GetRouteContext();
            DefaultRpcInvoker invoker        = this.GetInvoker();
            RpcResponse       stringResponse = await invoker.InvokeRequestAsync(stringRequest, route, routeContext);


            Assert.Equal(stringResponse.Result, randomGuid);
        }
Esempio n. 15
0
            public IPromise <string> Call(RpcRoute route, string argument)
            {
                var message = new RpcMessage
                {
                    Type           = RpcMessageType.ActionRequest,
                    Id             = Id(),
                    ControllerName = route.ControllerName,
                    ActionName     = route.ActionName,
                    Data           = argument,
                    ReturnTag      = new Tag(Aos.Node.NodeId)
                };

                var promise = new Promise <string>();

                _waitingForResult.Add(message.Id, promise);
                _sender.DispatchMessage(route.TargetTag, message.ToString());
                return(promise);
            }
Esempio n. 16
0
        public async Task InvokeRequest_ServiceProvider_Pass()
        {
            RpcRequest stringRequest = new RpcRequest("1", "Test");
            var        routeCriteria = new List <RouteCriteria>();

            routeCriteria.Add(new RouteCriteria(typeof(TestIoCRouteClass)));
            RpcRoute route = new RpcRoute(routeCriteria);

            DefaultRpcInvoker invoker         = this.GetInvoker();
            IServiceProvider  serviceProvider = this.GetServiceProvider();
            IRouteContext     routeContext    = this.GetRouteContext();
            RpcResponse       response        = await invoker.InvokeRequestAsync(stringRequest, route, routeContext);

            RpcResponse resultResponse = Assert.IsType <RpcResponse>(response);

            Assert.NotNull(resultResponse.Result);
            Assert.Equal(JTokenType.Integer, resultResponse.Result.Type);
            Assert.Equal(resultResponse.Result.Value <int>(), 1);
        }
Esempio n. 17
0
        public void InvokeRequest_ServiceProvider_Pass()
        {
            RpcRequest stringRequest = new RpcRequest("1", "Test");
            RpcRoute   route         = new RpcRoute();

            route.AddClass <TestIoCRouteClass>();
            IRpcInvoker        invoker           = new DefaultRpcInvoker();
            IServiceCollection serviceCollection = new ServiceCollection();

            serviceCollection.AddScoped <TestInjectionClass>();
            serviceCollection.AddScoped <TestIoCRouteClass>();
            IServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
            RpcResponse      response        = invoker.InvokeRequest(stringRequest, route, serviceProvider);

            RpcResponse resultResponse = Assert.IsType <RpcResponse>(response);

            Assert.NotNull(resultResponse.Result);
            Assert.Equal(JTokenType.Integer, resultResponse.Result.Type);
            Assert.Equal(resultResponse.Result.Value <int>(), 1);
        }
Esempio n. 18
0
        public async Task InvokeRequest_Int64RequestParam_ConvertToInt32Param()
        {
            RpcRequest stringRequest = new RpcRequest("1", "IntParameter", (long)1);


            var routeCriteria = new List <RouteCriteria>();

            routeCriteria.Add(new RouteCriteria(typeof(TestRouteClass)));
            RpcRoute          route        = new RpcRoute(routeCriteria);
            IRouteContext     routeContext = this.GetRouteContext();
            DefaultRpcInvoker invoker      = this.GetInvoker();

            RpcResponse response = await invoker.InvokeRequestAsync(stringRequest, route, routeContext);

            RpcResponse resultResponse = Assert.IsType <RpcResponse>(response);

            Assert.NotNull(resultResponse.Result);
            Assert.Equal(JTokenType.Integer, resultResponse.Result.Type);
            Assert.Equal(resultResponse.Result.Value <int>(), 1);
        }
Esempio n. 19
0
        public async Task InvokeRequest_AsyncMethod_Valid()
        {
            RpcRequest stringRequest = new RpcRequest("1", "AddAsync", 1, 1);


            var routeCriteria = new List <RouteCriteria>();

            routeCriteria.Add(new RouteCriteria(typeof(TestRouteClass)));
            RpcRoute route = new RpcRoute(routeCriteria);

            IRouteContext     routeContext = this.GetRouteContext();
            DefaultRpcInvoker invoker      = this.GetInvoker();

            RpcResponse response = await invoker.InvokeRequestAsync(stringRequest, route, routeContext);

            RpcResponse resultResponse = Assert.IsType <RpcResponse>(response);

            Assert.NotNull(resultResponse.Result);
            Assert.Equal(resultResponse.Result, 2);
        }
Esempio n. 20
0
        /// <summary>
        /// Gets all the predefined Rpc methods for a Rpc route
        /// </summary>
        /// <param name="route">The route to get Rpc methods for</param>
        /// <param name="serviceProvider">(Optional) IoC Container for rpc method controllers</param>
        /// <param name="jsonSerializerSettings">Json serialization settings that will be used in serialization and deserialization for rpc requests</param>
        /// <returns>List of Rpc methods for the specified Rpc route</returns>
        private static List <RpcMethod> GetRpcMethods(RpcRoute route, IServiceProvider serviceProvider = null, JsonSerializerSettings jsonSerializerSettings = null)
        {
            List <RpcMethod> rpcMethods = new List <RpcMethod>();

            foreach (RouteCriteria routeCriteria in route.RouteCriteria)
            {
                foreach (Type type in routeCriteria.Types)
                {
                    List <MethodInfo> publicMethods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance)
                                                      //Ignore ToString, GetHashCode and Equals
                                                      .Where(m => m.DeclaringType != typeof(object))
                                                      .ToList();
                    foreach (MethodInfo publicMethod in publicMethods)
                    {
                        RpcMethod rpcMethod = new RpcMethod(type, route, publicMethod, serviceProvider, jsonSerializerSettings);
                        rpcMethods.Add(rpcMethod);
                    }
                }
            }
            return(rpcMethods);
        }
Esempio n. 21
0
        public async Task InvokeRequest_OptionalParameter_Valid()
        {
            var routeCriteria = new List <RouteCriteria>();

            routeCriteria.Add(new RouteCriteria(typeof(TestRouteClass)));
            RpcRoute route = new RpcRoute(routeCriteria);

            DefaultRpcInvoker invoker         = this.GetInvoker();
            IServiceProvider  serviceProvider = this.GetServiceProvider();
            IRouteContext     routeContext    = this.GetRouteContext();


            //No params specified
            RpcRequest  stringRequest = new RpcRequest("1", "Optional");
            RpcResponse response      = await invoker.InvokeRequestAsync(stringRequest, route, routeContext);

            RpcResponse resultResponse = Assert.IsType <RpcResponse>(response);

            Assert.Null(resultResponse.Result);
            Assert.False(resultResponse.HasError);

            //Param is null
            stringRequest = new RpcRequest("1", "Optional", parameterList: null);
            response      = await invoker.InvokeRequestAsync(stringRequest, route, routeContext);

            resultResponse = Assert.IsType <RpcResponse>(response);
            Assert.Null(resultResponse.Result);
            Assert.False(resultResponse.HasError);


            //Param is a string
            stringRequest = new RpcRequest("1", "Optional", parameterList: "Test");
            response      = await invoker.InvokeRequestAsync(stringRequest, route, routeContext);

            resultResponse = Assert.IsType <RpcResponse>(response);
            Assert.NotNull(resultResponse.Result);
            Assert.Equal(JTokenType.String, resultResponse.Result.Type);
            Assert.Equal(resultResponse.Result.Value <string>(), "Test");
        }
        public List <RpcResponseBase> InvokeBatchRequest(List <RpcRequest> requests, RpcRoute route)
        {
            this.Logger?.LogVerbose($"Invoking '{requests.Count}' batch requests");
            var invokingTasks = new List <Task <RpcResponseBase> >();

            foreach (RpcRequest request in requests)
            {
                Task <RpcResponseBase> invokingTask = Task.Run(() => this.InvokeRequest(request, route));
                invokingTasks.Add(invokingTask);
            }

            Task.WaitAll(invokingTasks.Cast <Task>().ToArray());

            List <RpcResponseBase> responses = invokingTasks
                                               .Select(t => t.Result)
                                               .Where(r => r != null)
                                               .ToList();

            this.Logger?.LogVerbose($"Finished '{requests.Count}' batch requests");

            return(responses);
        }
Esempio n. 23
0
        /// <summary>
        /// Call the incoming Rpc requests methods and gives the appropriate respones
        /// </summary>
        /// <param name="requests">List of Rpc requests</param>
        /// <param name="route">Rpc route that applies to the current request</param>
        /// <param name="httpContext">The context of the current http request</param>
        /// <param name="jsonSerializerSettings">Json serialization settings that will be used in serialization and deserialization for rpc requests</param>
        /// <returns>List of Rpc responses for the requests</returns>
        public async Task <List <RpcResponse> > InvokeBatchRequestAsync(List <RpcRequest> requests, RpcRoute route, IRouteContext routeContext, JsonSerializerSettings jsonSerializerSettings = null)
        {
            this.logger?.LogDebug($"Invoking '{requests.Count}' batch requests");
            var invokingTasks = new List <Task <RpcResponse> >();

            foreach (RpcRequest request in requests)
            {
                Task <RpcResponse> invokingTask = Task.Run(async() => await this.InvokeRequestAsync(request, route, routeContext, jsonSerializerSettings));
                if (request.Id != null)
                {
                    //Only wait for non-notification requests
                    invokingTasks.Add(invokingTask);
                }
            }

            await Task.WhenAll(invokingTasks.ToArray());

            List <RpcResponse> responses = invokingTasks
                                           .Select(t => t.Result)
                                           .Where(r => r != null)
                                           .ToList();

            this.logger?.LogDebug($"Finished '{requests.Count}' batch requests");

            return(responses);
        }
Esempio n. 24
0
        /// <summary>
        /// Finds the matching Rpc method for the current request
        /// </summary>
        /// <param name="route">Rpc route for the current request</param>
        /// <param name="request">Current Rpc request</param>
        /// <param name="parameterList">Paramter list parsed from the request</param>
        /// <param name="serviceProvider">(Optional)IoC Container for rpc method controllers</param>
        /// <param name="jsonSerializerSettings">Json serialization settings that will be used in serialization and deserialization for rpc requests</param>
        /// <returns>The matching Rpc method to the current request</returns>
        private RpcMethod GetMatchingMethod(RpcRoute route, RpcRequest request, out object[] parameterList, IServiceProvider serviceProvider = null, JsonSerializerSettings jsonSerializerSettings = null)
        {
            if (route == null)
            {
                throw new ArgumentNullException(nameof(route));
            }
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }
            this.logger?.LogDebug($"Attempting to match Rpc request to a method '{request.Method}'");
            List <RpcMethod> methods = DefaultRpcInvoker.GetRpcMethods(route, serviceProvider, jsonSerializerSettings);

            //Case insenstive check for hybrid approach. Will check for case sensitive if there is ambiguity
            methods = methods
                      .Where(m => string.Equals(m.Method, request.Method, StringComparison.OrdinalIgnoreCase))
                      .ToList();

            RpcMethod rpcMethod = null;

            parameterList = null;
            int originalMethodCount = methods.Count;

            if (methods.Count > 0)
            {
                List <RpcMethod> potentialMatches = new List <RpcMethod>();
                foreach (RpcMethod method in methods)
                {
                    bool matchingMethod;
                    if (request.ParameterMap != null)
                    {
                        matchingMethod = method.HasParameterSignature(request.ParameterMap, out parameterList);
                    }
                    else
                    {
                        matchingMethod = method.HasParameterSignature(request.ParameterList, out parameterList);
                    }
                    if (matchingMethod)
                    {
                        potentialMatches.Add(method);
                    }
                }

                if (potentialMatches.Count > 1)
                {
                    //Try to remove ambiguity with case sensitive check
                    potentialMatches = potentialMatches
                                       .Where(m => string.Equals(m.Method, request.Method, StringComparison.Ordinal))
                                       .ToList();
                    if (potentialMatches.Count != 1)
                    {
                        this.logger?.LogError("More than one method matched the rpc request. Unable to invoke due to ambiguity.");
                        throw new RpcMethodNotFoundException();
                    }
                }

                if (potentialMatches.Count == 1)
                {
                    rpcMethod = potentialMatches.First();
                }
            }
            if (rpcMethod == null)
            {
                this.logger?.LogError("No methods matched request.");
                throw new RpcMethodNotFoundException();
            }
            this.logger?.LogDebug("Request was matched to a method");
            return(rpcMethod);
        }
Esempio n. 25
0
        /// <summary>
        /// Call the incoming Rpc request method and gives the appropriate response
        /// </summary>
        /// <param name="request">Rpc request</param>
        /// <param name="route">Rpc route that applies to the current request</param>
        /// <param name="httpContext">The context of the current http request</param>
        /// <param name="jsonSerializerSettings">Json serialization settings that will be used in serialization and deserialization for rpc requests</param>
        /// <returns>An Rpc response for the request</returns>
        public async Task <RpcResponse> InvokeRequestAsync(RpcRequest request, RpcRoute route, IRouteContext routeContext, JsonSerializerSettings jsonSerializerSettings = null)
        {
            try
            {
                if (request == null)
                {
                    throw new ArgumentNullException(nameof(request));
                }
                if (route == null)
                {
                    throw new ArgumentNullException(nameof(route));
                }
            }
            catch (ArgumentNullException ex)             // Dont want to throw any exceptions when doing async requests
            {
                return(this.GetUnknownExceptionReponse(request, ex));
            }

            this.logger?.LogDebug($"Invoking request with id '{request.Id}'");
            RpcResponse rpcResponse;

            try
            {
                if (!string.Equals(request.JsonRpcVersion, JsonRpcContants.JsonRpcVersion))
                {
                    throw new RpcInvalidRequestException($"Request must be jsonrpc version '{JsonRpcContants.JsonRpcVersion}'");
                }

                object[]  parameterList;
                RpcMethod rpcMethod = this.GetMatchingMethod(route, request, out parameterList, routeContext.RequestServices, jsonSerializerSettings);

                bool isAuthorized = await this.IsAuthorizedAsync(rpcMethod, routeContext);

                if (isAuthorized)
                {
                    this.logger?.LogDebug($"Attempting to invoke method '{request.Method}'");
                    object result = await rpcMethod.InvokeAsync(parameterList);

                    this.logger?.LogDebug($"Finished invoking method '{request.Method}'");

                    JsonSerializer jsonSerializer = JsonSerializer.Create(jsonSerializerSettings);
                    if (result is IRpcMethodResult)
                    {
                        this.logger?.LogTrace($"Result is {nameof(IRpcMethodResult)}.");
                        rpcResponse = ((IRpcMethodResult)result).ToRpcResponse(request.Id, obj => JToken.FromObject(obj, jsonSerializer));
                    }
                    else
                    {
                        this.logger?.LogTrace($"Result is plain object.");
                        JToken resultJToken = result != null?JToken.FromObject(result, jsonSerializer) : null;

                        rpcResponse = new RpcResponse(request.Id, resultJToken);
                    }
                }
                else
                {
                    var authError = new RpcError(RpcErrorCode.InvalidRequest, "Unauthorized");
                    rpcResponse = new RpcResponse(request.Id, authError);
                }
            }
            catch (RpcException ex)
            {
                this.logger?.LogException(ex, "An Rpc error occurred. Returning an Rpc error response");
                RpcError error = new RpcError(ex, this.serverConfig.Value.ShowServerExceptions);
                rpcResponse = new RpcResponse(request.Id, error);
            }
            catch (Exception ex)
            {
                rpcResponse = this.GetUnknownExceptionReponse(request, ex);
            }

            if (request.Id != null)
            {
                this.logger?.LogDebug($"Finished request with id '{request.Id}'");
                //Only give a response if there is an id
                return(rpcResponse);
            }
            this.logger?.LogDebug($"Finished request with no id. Not returning a response");
            return(null);
        }
Esempio n. 26
0
        /// <summary>
        /// Indicates if the incoming request matches any predefined routes
        /// </summary>
        /// <param name="requestUrl">The current request url</param>
        /// <param name="route">The matching route corresponding to the request url if found, otherwise it is null</param>
        /// <param name="routeProvider">Provider that allows the retrieval of all configured routes</param>
        /// <returns>True if the request url matches any Rpc routes, otherwise False</returns>
        public bool MatchesRpcRoute(IRpcRouteProvider routeProvider, string requestUrl, out RpcRoute route)
        {
            if (requestUrl == null)
            {
                throw new ArgumentNullException(nameof(requestUrl));
            }
            this.logger?.LogDebug($"Attempting to match Rpc route for the request url '{requestUrl}'");
            RpcPath requestPath = RpcPath.Parse(requestUrl);

            this.logger?.LogTrace($"Request path: {requestPath}");

            foreach (RpcRoute rpcRoute in routeProvider.GetRoutes())
            {
                RpcPath routePath = RpcPath.Parse(rpcRoute.Name);
                this.logger?.LogTrace($"Trying to match against route - Name: {rpcRoute.Name}, Path: {routePath}");
                if (requestPath == routePath)
                {
                    this.logger?.LogDebug($"Matched the request url '{requestUrl}' to the route '{rpcRoute.Name}'");
                    route = rpcRoute;
                    return(true);
                }
            }
            this.logger?.LogDebug($"Failed to match the request url '{requestUrl}' to a route");
            route = null;
            return(false);
        }
Esempio n. 27
0
		/// <summary>
		/// Finds the matching Rpc method for the current request
		/// </summary>
		/// <param name="route">Rpc route for the current request</param>
		/// <param name="request">Current Rpc request</param>
		/// <param name="parameterList">Paramter list parsed from the request</param>
		/// <param name="serviceProvider">(Optional)IoC Container for rpc method controllers</param>
		/// <param name="jsonSerializerSettings">Json serialization settings that will be used in serialization and deserialization for rpc requests</param>
		/// <returns>The matching Rpc method to the current request</returns>
		private RpcMethod GetMatchingMethod(RpcRoute route, RpcRequest request, out object[] parameterList, IServiceProvider serviceProvider = null, JsonSerializerSettings jsonSerializerSettings = null)
		{
			if (route == null)
			{
				throw new ArgumentNullException(nameof(route));
			}
			if (request == null)
			{
				throw new ArgumentNullException(nameof(request));
			}
			this.logger?.LogDebug($"Attempting to match Rpc request to a method '{request.Method}'");
			List<RpcMethod> methods = DefaultRpcInvoker.GetRpcMethods(route, serviceProvider, jsonSerializerSettings);

			//Case insenstive check for hybrid approach. Will check for case sensitive if there is ambiguity
			methods = methods
				.Where(m => string.Equals(m.Method, request.Method, StringComparison.OrdinalIgnoreCase))
				.ToList();

			RpcMethod rpcMethod = null;
			parameterList = null;
			int originalMethodCount = methods.Count;
			if (methods.Count > 0)
			{
				List<RpcMethod> potentialMatches = new List<RpcMethod>();
				foreach (RpcMethod method in methods)
				{
					bool matchingMethod;
					if (request.ParameterMap != null)
					{
						matchingMethod = method.HasParameterSignature(request.ParameterMap, out parameterList);
					}
					else
					{
						matchingMethod = method.HasParameterSignature(request.ParameterList);
						parameterList = request.ParameterList;
					}
					if (matchingMethod)
					{
						potentialMatches.Add(method);
					}
				}

				if (potentialMatches.Count > 1)
				{
					//Try to remove ambiguity with case sensitive check
					potentialMatches = potentialMatches
						.Where(m => string.Equals(m.Method, request.Method, StringComparison.Ordinal))
						.ToList();
					if (potentialMatches.Count != 1) 
					{
						this.logger?.LogError("More than one method matched the rpc request. Unable to invoke due to ambiguity.");
						throw new RpcMethodNotFoundException();
					}
				}

				if (potentialMatches.Count == 1)
				{
					rpcMethod = potentialMatches.First();
				}
			}
			if (rpcMethod == null)
			{
				this.logger?.LogError("No methods matched request.");
				throw new RpcMethodNotFoundException();
			}
			this.logger?.LogDebug("Request was matched to a method");
			return rpcMethod;
		}
Esempio n. 28
0
        /// <summary>
        /// Call the incoming Rpc request method and gives the appropriate response
        /// </summary>
        /// <param name="request">Rpc request</param>
        /// <param name="route">Rpc route that applies to the current request</param>
        /// <param name="serviceProvider">(Optional)IoC Container for rpc method controllers</param>
        /// <param name="jsonSerializerSettings">Json serialization settings that will be used in serialization and deserialization for rpc requests</param>
        /// <returns>An Rpc response for the request</returns>
        public RpcResponse InvokeRequest(RpcRequest request, RpcRoute route, IServiceProvider serviceProvider = null, JsonSerializerSettings jsonSerializerSettings = null)
        {
            try
            {
                if (request == null)
                {
                    throw new ArgumentNullException(nameof(request));
                }
                if (route == null)
                {
                    throw new ArgumentNullException(nameof(route));
                }
            }
            catch (ArgumentNullException ex)             // Dont want to throw any exceptions when doing async requests
            {
                return(this.GetUnknownExceptionReponse(request, ex));
            }

            this.Logger?.LogDebug($"Invoking request with id '{request.Id}'");
            RpcResponse rpcResponse;

            try
            {
                if (!string.Equals(request.JsonRpcVersion, JsonRpcContants.JsonRpcVersion))
                {
                    throw new RpcInvalidRequestException($"Request must be jsonrpc version '{JsonRpcContants.JsonRpcVersion}'");
                }

                object[]  parameterList;
                RpcMethod rpcMethod = this.GetMatchingMethod(route, request, out parameterList, serviceProvider, jsonSerializerSettings);

                this.Logger?.LogDebug($"Attempting to invoke method '{request.Method}'");
                object result = rpcMethod.Invoke(parameterList);
                this.Logger?.LogDebug($"Finished invoking method '{request.Method}'");

                JsonSerializer jsonSerializer = JsonSerializer.Create(jsonSerializerSettings);

                JToken resultJToken = result != null?JToken.FromObject(result, jsonSerializer) : null;

                rpcResponse = new RpcResponse(request.Id, resultJToken);
            }
            catch (RpcException ex)
            {
                this.Logger?.LogException(ex, "An Rpc error occurred. Returning an Rpc error response");
                RpcError error = new RpcError(ex, this.ShowServerExceptions);
                rpcResponse = new RpcResponse(request.Id, error);
            }
            catch (Exception ex)
            {
                rpcResponse = this.GetUnknownExceptionReponse(request, ex);
            }

            if (request.Id != null)
            {
                this.Logger?.LogDebug($"Finished request with id '{request.Id}'");
                //Only give a response if there is an id
                return(rpcResponse);
            }
            this.Logger?.LogDebug($"Finished request with no id. Not returning a response");
            return(null);
        }
Esempio n. 29
0
		/// <summary>
		/// Gets all the predefined Rpc methods for a Rpc route
		/// </summary>
		/// <param name="route">The route to get Rpc methods for</param>
		/// <param name="serviceProvider">(Optional) IoC Container for rpc method controllers</param>
		/// <param name="jsonSerializerSettings">Json serialization settings that will be used in serialization and deserialization for rpc requests</param>
		/// <returns>List of Rpc methods for the specified Rpc route</returns>
		private static List<RpcMethod> GetRpcMethods(RpcRoute route, IServiceProvider serviceProvider = null, JsonSerializerSettings jsonSerializerSettings = null)
		{
			List<RpcMethod> rpcMethods = new List<RpcMethod>();
			foreach (RouteCriteria routeCriteria in route.RouteCriteria)
			{
				foreach (Type type in routeCriteria.Types)
				{
					MethodInfo[] publicMethods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance);
					foreach (MethodInfo publicMethod in publicMethods)
					{
						RpcMethod rpcMethod = new RpcMethod(type, route, publicMethod, serviceProvider, jsonSerializerSettings);
						rpcMethods.Add(rpcMethod);
					}
				}
			}
			return rpcMethods;
		}
Esempio n. 30
0
		/// <summary>
		/// Call the incoming Rpc request method and gives the appropriate response
		/// </summary>
		/// <param name="request">Rpc request</param>
		/// <param name="route">Rpc route that applies to the current request</param>
		/// <param name="httpContext">The context of the current http request</param>
		/// <param name="jsonSerializerSettings">Json serialization settings that will be used in serialization and deserialization for rpc requests</param>
		/// <returns>An Rpc response for the request</returns>
		public async Task<RpcResponse> InvokeRequestAsync(RpcRequest request, RpcRoute route, HttpContext httpContext, JsonSerializerSettings jsonSerializerSettings = null)
		{
			try
			{
				if (request == null)
				{
					throw new ArgumentNullException(nameof(request));
				}
				if (route == null)
				{
					throw new ArgumentNullException(nameof(route));
				}
			}
			catch (ArgumentNullException ex) // Dont want to throw any exceptions when doing async requests
			{
				return this.GetUnknownExceptionReponse(request, ex);
			}

			this.logger?.LogDebug($"Invoking request with id '{request.Id}'");
			RpcResponse rpcResponse;
			try
			{
				if (!string.Equals(request.JsonRpcVersion, JsonRpcContants.JsonRpcVersion))
				{
					throw new RpcInvalidRequestException($"Request must be jsonrpc version '{JsonRpcContants.JsonRpcVersion}'");
				}

				object[] parameterList;
				RpcMethod rpcMethod = this.GetMatchingMethod(route, request, out parameterList, httpContext.RequestServices, jsonSerializerSettings);

				bool isAuthorized = await this.IsAuthorizedAsync(rpcMethod, httpContext);

				if (isAuthorized)
				{

					this.logger?.LogDebug($"Attempting to invoke method '{request.Method}'");
					object result = await rpcMethod.InvokeAsync(parameterList);
					this.logger?.LogDebug($"Finished invoking method '{request.Method}'");

					JsonSerializer jsonSerializer = JsonSerializer.Create(jsonSerializerSettings);
					if (result is IRpcMethodResult)
					{
						this.logger?.LogTrace($"Result is {nameof(IRpcMethodResult)}.");
						rpcResponse = ((IRpcMethodResult)result).ToRpcResponse(request.Id, obj => JToken.FromObject(obj, jsonSerializer));
					}
					else
					{
						this.logger?.LogTrace($"Result is plain object.");
						JToken resultJToken = result != null ? JToken.FromObject(result, jsonSerializer) : null;
						rpcResponse = new RpcResponse(request.Id, resultJToken);
					}
				}
				else
				{
					var authError = new RpcError(RpcErrorCode.InvalidRequest, "Unauthorized");
					rpcResponse = new RpcResponse(request.Id, authError);
				}
			}
			catch (RpcException ex)
			{
				this.logger?.LogException(ex, "An Rpc error occurred. Returning an Rpc error response");
				RpcError error = new RpcError(ex, this.serverConfig.Value.ShowServerExceptions);
				rpcResponse = new RpcResponse(request.Id, error);
			}
			catch (Exception ex)
			{
				rpcResponse = this.GetUnknownExceptionReponse(request, ex);
			}

			if (request.Id != null)
			{
				this.logger?.LogDebug($"Finished request with id '{request.Id}'");
				//Only give a response if there is an id
				return rpcResponse;
			}
			this.logger?.LogDebug($"Finished request with no id. Not returning a response");
			return null;
		}
Esempio n. 31
0
        /// <summary>
        /// Finds the matching Rpc method for the current request
        /// </summary>
        /// <param name="route">Rpc route for the current request</param>
        /// <param name="request">Current Rpc request</param>
        /// <param name="parameterList">Paramter list parsed from the request</param>
        /// <param name="serviceProvider">(Optional)IoC Container for rpc method controllers</param>
        /// <param name="jsonSerializerSettings">Json serialization settings that will be used in serialization and deserialization for rpc requests</param>
        /// <returns>The matching Rpc method to the current request</returns>
        private RpcMethod GetMatchingMethod(RpcRoute route, RpcRequest request, out object[] parameterList, IServiceProvider serviceProvider = null, JsonSerializerSettings jsonSerializerSettings = null)
        {
            if (route == null)
            {
                throw new ArgumentNullException(nameof(route));
            }
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }
            this.Logger?.LogDebug($"Attempting to match Rpc request to a method '{request.Method}'");
            List <RpcMethod> methods = DefaultRpcInvoker.GetRpcMethods(route, serviceProvider, jsonSerializerSettings);

            methods = methods
                      .Where(m => string.Equals(m.Method, request.Method, StringComparison.OrdinalIgnoreCase))
                      .ToList();

            RpcMethod rpcMethod = null;

            parameterList = null;
            if (methods.Count > 1)
            {
                foreach (RpcMethod method in methods)
                {
                    bool matchingMethod;
                    if (request.ParameterMap != null)
                    {
                        matchingMethod = method.HasParameterSignature(request.ParameterMap, out parameterList);
                    }
                    else
                    {
                        matchingMethod = method.HasParameterSignature(request.ParameterList);
                        parameterList  = request.ParameterList;
                    }
                    if (matchingMethod)
                    {
                        if (rpcMethod != null)                         //If already found a match
                        {
                            throw new RpcAmbiguousMethodException();
                        }
                        rpcMethod = method;
                    }
                }
            }
            else if (methods.Count == 1)
            {
                //Only signature check for methods that have the same name for performance reasons
                rpcMethod = methods.First();
                if (request.ParameterMap != null)
                {
                    bool signatureMatch = rpcMethod.TryParseParameterList(request.ParameterMap, out parameterList);
                    if (!signatureMatch)
                    {
                        throw new RpcMethodNotFoundException();
                    }
                }
                else
                {
                    parameterList = request.ParameterList;
                }
            }
            if (rpcMethod == null)
            {
                throw new RpcMethodNotFoundException();
            }
            this.Logger?.LogDebug("Request was matched to a method");
            return(rpcMethod);
        }