Пример #1
0
        private object[] GetParameters(ObjectMethodExecutor executor, GrainRouteValues route)
        {
            //short circuit if no parameters
            if (executor.MethodParameters == null || executor.MethodParameters.Length == 0)
            {
                return(Array.Empty <object>());
            }
            // loop through binders, in order
            // first suitable binder wins
            // so the order of registration is important
            ExceptionDispatchInfo lastException = null;

            try
            {
                var param = _parameterBinder.BindParameters(executor.MethodParameters, route);
                if (param.Length == executor.MethodParameters.Length)
                {
                    return(param);
                }
                else
                {
                    throw new UnableToFindDownstreamRouteException("The request parameter is inconsistent with the parameter that executes the action.");
                }
            }
            catch (Exception ex)
            {
                // continue on next suitable binder
                // but keep the exception when no other suitable binders are found
                lastException = ExceptionDispatchInfo.Capture(ex);
            }
            lastException?.Throw();
            return(Array.Empty <object>());
        }
        private object[] GetParameters(ObjectMethodExecutor executor, GrainRouteValues route)
        {
            //short circuit if no parameters
            if (executor.MethodParameters == null || executor.MethodParameters.Length == 0)
            {
                return(Array.Empty <object>());
            }
            // loop through binders, in order
            // first suitable binder wins
            // so the order of registration is important
            ExceptionDispatchInfo lastException = null;

            try
            {
                return(_parameterBinder.BindParameters(executor.MethodParameters, route));
            }
            catch (Exception ex)
            {
                // continue on next suitable binder
                // but keep the exception when no other suitable binders are found
                lastException = ExceptionDispatchInfo.Capture(ex);
            }
            lastException?.Throw();
            return(Array.Empty <object>());
        }
        public Response <bool> Authorise(ClaimsPrincipal claimsPrincipal, GrainRouteValues route)
        {
            var attrs = route.GrainMethod.GetCustomAttributes <AuthorizeAttribute>(true);

            if (attrs.Count() == 0)
            {
                return(new OkResponse <bool>(true));
            }

            foreach (var attr in attrs)
            {
                if (!string.IsNullOrEmpty(attr.Roles))
                {
                    var response = this.AuthoriseRole(claimsPrincipal, attr.Roles);
                    if (response.IsError || !response.Data)
                    {
                        return(response);
                    }
                }
                if (!string.IsNullOrEmpty(attr.Policy))
                {
                    var response = this.AuthorisePolicy(claimsPrincipal, attr.Policy);
                    if (response.IsError || !response.Data)
                    {
                        return(response);
                    }
                }
            }
            return(new OkResponse <bool>(true));
        }
        public async Task <object> Invoke(GrainReference grain, GrainRouteValues route)
        {
            var executors = _cachedExecutors.GetOrAdd($"{grain.GrainType.FullName}.{route.GrainMethod}",
                                                      (key) =>
            {
                //Get grainType IEnumerable<MethodInfo>
                var mis = ReflectionUtil.GetMethodsIncludingBaseInterfaces(grain.GrainType)
                          .Where(x => string.Equals(x.Name, route.GrainMethod, StringComparison.OrdinalIgnoreCase)).ToList();
                if (mis.Count <= 0)
                {
                    throw new ArgumentNullException(nameof(MethodInfo));
                }
                List <ObjectMethodExecutor> _executors = new List <ObjectMethodExecutor>();
                foreach (var mi in mis)
                {
                    var exe = ObjectMethodExecutor.Create(mi, grain.GrainType.GetTypeInfo());
                    _executors.Add(exe);
                }
                _executors.Sort((x, y) =>
                                - x.MethodParameters.Count().CompareTo(y.MethodParameters.Count())
                                );
                return(_executors);
            });

            foreach (var executor in executors)
            {
                var parameters = await GetParameters(executor, route.HttpContext.Request);

                if (executor.MethodParameters.Count() == parameters.Length)
                {
                    return(await executor.ExecuteAsync(grain.Grain, parameters));
                }
            }
            throw new InvalidOperationException("No suitable parameter binder found for request");
        }
        public GrainReference GetGrain(GrainRouteValues route)
        {
            var grain  = _GrainReferenceCache.GetOrAdd(route.GrainType.FullName, key => this.GetGrainReference(route));
            var option = _options.Clients[route.SiloName];

            if ((bool)option?.IsAuthorizationBearer)
            {
                this.SetAuthorization(route.HttpContext);
            }
            return(grain);
        }
Пример #6
0
        private void GivenHeaderSuccess()
        {
            var route = new GrainRouteValues();

            _routeValuesBuilder.Setup(x => x.Build(this.context)).Returns(new OkResponse <GrainRouteValues>(route));
            _authorisation.Setup(x => x.Authorise(this.context.HttpContext.User, route)).Returns(new OkResponse <bool>(true));
            var grain = new GrainReference(null, null);

            _clusterClientBuilder.Setup(x => x.Build(route, this.context)).Returns(new OkResponse <GrainReference>(grain));
            Response <OrleansResponseMessage> response = new OkResponse <OrleansResponseMessage>(new OrleansResponseMessage(null, HttpStatusCode.OK));

            _grainInvoker.Setup(x => x.Invoke(grain, route)).Returns(Task.FromResult(response));
        }
Пример #7
0
        public Response <GrainRouteValues> Build(DownstreamContext context)
        {
            try
            {
                GrainRouteValues route = this.GetRequestRoute(context);
                if (route == null)
                {
                    return(this.SetUnableToFindDownstreamRouteError(context, $"The request address is invalid URL:{context.DownstreamRequest.ToUri()}"));
                }

                this._logger.LogDebug($"Http address translation Orleans request address {context.DownstreamRequest.ToUri()}");

                //Get client option based on serviceName
                if (!_options.Clients.ContainsKey(route.SiloName))
                {
                    return(this.SetUnableToFindDownstreamRouteError(context, $"{nameof(OrleansClientOptions)} without {route.SiloName} configured "));
                }
                route.ClientOptions = _options.Clients[route.SiloName];

                //Find the request corresponding to the Orleans interface
                route.GrainType = this.GetGrainType(route);
                if (route.GrainType == null)
                {
                    return(this.SetUnableToFindDownstreamRouteError(context, $"The request address is invalid,No corresponding Orleans interface  found. URL:{route.RequestUri}"));
                }
                //Find the request corresponding to the method in the Orleans interface
                route.GrainMethod = this.GetGtainMethods(route);
                if (route.GrainMethod == null)
                {
                    return(this.SetUnableToFindDownstreamRouteError(context, $"The request address is invalid and the corresponding method in the Orleans interface {route.SiloName}_#_{route.GrainName} was not found. {route.GrainMethodName}. URL:{route.RequestUri}"));
                }

                return(new OkResponse <GrainRouteValues>(route));
            }
            catch (OrleansConfigurationException ex)
            {
                this._logger.LogError($"{nameof(OrleansConfigurationException)}   {ex.Message}", ex);
                return(this.SetUnknownError(ex.Message));
            }
            catch (OrleansGrainReferenceException ex)
            {
                this._logger.LogError($"{nameof(OrleansGrainReferenceException)}   {ex.Message}", ex);
                return(this.SetUnknownError(ex.Message));
            }
            catch (Exception ex)
            {
                this._logger.LogError(ex.Message, ex);
                return(this.SetUnknownError(ex.Message));
            }
        }
Пример #8
0
        private IClusterClient BuildClusterClient(GrainRouteValues routeValues, DownstreamContext context)
        {
            var clientOptions = routeValues.ClientOptions;

            IClientBuilder build = new ClientBuilder();

            build.Configure <ClusterOptions>(opt =>
            {
                opt.ClusterId = clientOptions.ClusterId;
                opt.ServiceId = clientOptions.ServiceId;
            });

            build = this.UseServiceDiscovery(build, context);
            var client = build.Build();

            return(this.ConnectClient(routeValues.GrainName, client));
        }
Пример #9
0
        private MethodInfo GetGtainMethods(GrainRouteValues route)
        {
            var methods = _MethodInfoCache.GetOrAdd($"{route.SiloName}_#_{route.GrainName}_#_{route.GrainMethodName}", (key) =>
            {
                //Get grainType IEnumerable<MethodInfo>
                return(ReflectionUtil.GetMethodsIncludingBaseInterfaces(route.GrainType)
                       .Where(x => string.Equals(x.Name, route.GrainMethodName, StringComparison.OrdinalIgnoreCase)).ToList());
            });

            if (methods.Count == 0)
            {
                return(null);
            }

            //Get the first method, temporarily only support one method with the same name
            return(methods.FirstOrDefault());
        }
        public object[] BindParameters(ParameterInfo[] parameters, GrainRouteValues routeValues)
        {
            if (parameters == null || parameters.Length <= 0)
            {
                return(Array.Empty <object>());
            }

            var result = new object[parameters.Length];

            for (int i = 0; i < parameters.Length; i++)
            {
                try
                {
                    var    param = parameters[i];
                    object value = null;
                    if (param.ParameterType.CanHaveChildren())
                    {
                        value = this.BindClassType(param, routeValues.Body);
                    }
                    else
                    {
                        value = this.BindPrimitiveType(param, routeValues.Querys, routeValues.Body);
                        if (value == null)
                        {
                            if (param.HasDefaultValue)
                            {
                                value = param.DefaultValue;
                            }
                            else
                            {
                                return(new object[0]);
                            }
                        }
                    }

                    result[i] = value;
                }
                catch (Exception ex)
                {
                    throw new OrleansGrainReferenceException("Bind this parameters data failed", ex);
                }
            }

            return(result);
        }
        private GrainRouteValues GetRequestRoute(DownstreamContext context)
        {
            GrainRouteValues routeValues = new GrainRouteValues();

            string[] route = context.DownstreamRequest.AbsolutePath.Split('/')
                             .Where(s => !string.IsNullOrEmpty(s))
                             .ToArray();
            if (route.Length < 2 || route.Length > 3)
            {
                return(null);
            }

            routeValues.SiloName        = context.DownstreamReRoute.ServiceName;
            routeValues.GrainName       = route[0];
            routeValues.GrainMethodName = route[1];
            routeValues.RequestUri      = context.DownstreamRequest.ToUri();

            //Claims to Claims Tranformation Whether to inject GrainKey
            var claim = context.HttpContext.User.FindFirst("GrainKey");

            if (claim != null)
            {
                routeValues.GrainId = claim.Value;
            }
            else
            {
                routeValues.GrainId = (route.Length == 3) ? route[2] : null;
            }

            try
            {
                routeValues.Querys = this.GetQueryParameter(context.DownstreamRequest.Query);
                routeValues.Body   = this.GetBodyParameter(context.DownstreamRequest, context.HttpContext.Request);
            }
            catch (Exception ex)
            {
                throw new OrleansGrainReferenceException("Error parsing request parameters ...", ex);
            }
            return(routeValues);
        }
Пример #12
0
        public Response Build(GrainRouteValues routeValues, DownstreamContext context)
        {
            try
            {
                string clientKey = this.GetClientKey(routeValues.GrainType);
                if (clusterClientCache.Keys.Where(f => f == clientKey).Count() > 0)
                {
                    return(new OkResponse());
                }

                clusterClientCache.GetOrAdd(clientKey, (key) =>
                {
                    return(this.BuildClusterClient(routeValues, context));
                });
                return(new OkResponse());
            }
            catch (Exception ex)
            {
                this._logger.LogError(ex.Message, ex);
                return(new ErrorResponse <GrainRouteValues>(new UnknownError(ex.Message)));
            }
        }
Пример #13
0
        private Type GetGrainType(GrainRouteValues route)
        {
            return(_GrainTypeCache.GetOrAdd($"{route.SiloName}_#_{route.GrainName}", (key) =>
            {
                this._logger.LogDebug($"Looking for the {route.ClientOptions.ServiceName} Grain interface");
                if (this._config == null || this._config.MapRouteToGraininterface == null)
                {
                    throw new OrleansConfigurationException($"{route.ClientOptions.ServiceName}Route map Grain interface configured to set");
                }

                try
                {
                    string grainInterface = this._config.MapRouteToGraininterface.Invoke(route);
                    var types = route.ClientOptions.Assembly.GetExportedTypes();
                    return types.Where(f => typeof(IGrain).IsAssignableFrom(f) && f.Name.Equals(grainInterface, StringComparison.OrdinalIgnoreCase))
                    .FirstOrDefault();
                }
                catch (Exception ex)
                {
                    throw new OrleansConfigurationException($"{route.ClientOptions.ServiceName} Orleans Client Options configuration error, unable to find Grain interface", ex);
                }
            }));
        }
 public Response <GrainReference> GetGrainReference(GrainRouteValues route)
 {
     try
     {
         var grainFunc = _GrainReferenceCache.GetOrAdd(route.GrainType.FullName, key =>
         {
             return(this.BuildFactoryMethod(route.GrainType));
         });
         var grain          = grainFunc(route.GrainId);
         var grainReference = new GrainReference(route.GrainType, grain);
         return(new OkResponse <GrainReference>(grainReference));
     }
     catch (UnableToFindDownstreamRouteException ex)
     {
         this._logger.LogWarning(ex.Message);
         return(new ErrorResponse <GrainReference>(new UnableToFindDownstreamRouteError(route.RequestUri, "orleans")));
     }
     catch (Exception ex)
     {
         this._logger.LogError(ex.Message, ex);
         return(new ErrorResponse <GrainReference>(new UnknownError(ex.Message)));
     }
 }
        public async Task <Response <OrleansResponseMessage> > Invoke(GrainReference grain, GrainRouteValues route)
        {
            try
            {
                string key      = $"{route.SiloName}.{route.GrainName}.{route.GrainMethodName}";
                var    executor = _cachedExecutors.GetOrAdd(key, (_key) =>
                {
                    ObjectMethodExecutor _executor = ObjectMethodExecutor.Create(route.GrainMethod, grain.GrainType.GetTypeInfo());
                    return(_executor);
                });

                var parameters = GetParameters(executor, route);
                var result     = await this.ExecuteAsync(executor, grain, parameters);

                var message = new OrleansResponseMessage(new OrleansContent(result, this._jsonSerializer), HttpStatusCode.OK);
                return(new OkResponse <OrleansResponseMessage>(message));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.Message, ex);
                return(new ErrorResponse <OrleansResponseMessage>(new UnknownError(ex.Message)));
            }
        }
        public GrainReference GetGrainReference(Type type, GrainRouteValues route)
        {
            var grain = this.BuildFactoryMethod(type)(route.GrainId);

            return(new GrainReference(type, grain));
        }
Пример #17
0
        private GrainRouteValues GetRequestRoute(DownstreamContext context)
        {
            GrainRouteValues routeValues = new GrainRouteValues();

            string[] route = context.DownstreamRequest.AbsolutePath.Split('/')
                             .Where(s => !string.IsNullOrEmpty(s))
                             .ToArray();
            if (route.Length < 2 || route.Length > 3)
            {
                return(null);
            }

            routeValues.SiloName        = context.DownstreamReRoute.ServiceName;
            routeValues.GrainName       = route[0];
            routeValues.GrainMethodName = route[1];
            routeValues.RequestUri      = context.DownstreamRequest.ToUri();

            //Claims to Claims Tranformation Whether to inject GrainKey
            var claim = context.HttpContext.User.FindFirst("GrainKey");

            if (claim != null)
            {
                routeValues.GrainId = claim.Value;
            }
            else
            {
                routeValues.GrainId = (route.Length == 3) ? route[2] : null;
            }

            try
            {
                routeValues.Querys = this.GetQueryParameter(context.DownstreamRequest.Query);


                var body = this.ReadBodyStream(context.DownstreamRequest);
                if (body != null && body.Length > 0)
                {
                    var requestContentType = context.HttpContext.Request.GetTypedHeaders().ContentType;
                    if (requestContentType == null)
                    {
                        routeValues.Body = null;
                    }
                    else
                    {
                        this._logger.LogInformation($"Http request ContentType :{requestContentType.MediaType.ToString()}");
                        if (requestContentType.MediaType.Equals("application/json", StringComparison.OrdinalIgnoreCase))
                        {
                            routeValues.Body = this.GetJsonParameter(body, context.HttpContext.Request);
                        }
                        else
                        {
                            routeValues.Body = this.GetFormDataParameter(body, context.HttpContext.Request);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new OrleansGrainReferenceException("Error parsing request parameters ...", ex);
            }
            return(routeValues);
        }
 private GrainReference GetGrainReference(GrainRouteValues route)
 {
     return(_grainReferenceProvider.GetGrainReference(route.GrainType, route));
 }
Пример #19
0
        public async Task <Response <OrleansResponseMessage> > Invoke(GrainReference grain, GrainRouteValues route)
        {
            ObjectMethodExecutor executor;

            object[] parameters;
            try
            {
                string key = $"{route.SiloName}.{route.GrainName}.{route.GrainMethodName}";
                executor = _cachedExecutors.GetOrAdd(key, (_key) =>
                {
                    ObjectMethodExecutor _executor = ObjectMethodExecutor.Create(route.GrainMethod, grain.GrainType.GetTypeInfo());
                    return(_executor);
                });
                parameters = GetParameters(executor, route);
            }
            catch (Exception ex)
            {
                _logger.LogError($"Binding parameter failed", ex);
                return(new ErrorResponse <OrleansResponseMessage>(new UnknownError(ex.Message)));
            }
            try
            {
                return(await this.Invoke(executor, grain, parameters));
            }
            catch (Exception ex)
            {
                _logger.LogError($"Request {grain.GrainType.Name} Orleans failed,", ex);
                if (ex.InnerException != null && ex.InnerException is Orleans.Runtime.OrleansMessageRejectionException)
                {
                    await Task.Delay(1);

                    return(await this.Invoke(executor, grain, parameters));
                }
                throw ex;
            }
        }