예제 #1
0
    /// <summary>
    /// Creates a <see cref="RoutePattern"/> from its string representation along
    /// with provided default values and parameter policies.
    /// </summary>
    /// <param name="pattern">The route pattern string to parse.</param>
    /// <param name="defaults">
    /// Additional default values to associated with the route pattern. May be null.
    /// The provided object will be converted to key-value pairs using <see cref="RouteValueDictionary"/>
    /// and then merged into the parsed route pattern.
    /// </param>
    /// <param name="parameterPolicies">
    /// Additional parameter policies to associated with the route pattern. May be null.
    /// The provided object will be converted to key-value pairs using <see cref="RouteValueDictionary"/>
    /// and then merged into the parsed route pattern.
    /// Multiple policies can be specified for a key by providing a collection as the value.
    /// </param>
    /// <returns>The <see cref="RoutePattern"/>.</returns>
    public static RoutePattern Parse(string pattern, object?defaults, object?parameterPolicies)
    {
        if (pattern == null)
        {
            throw new ArgumentNullException(nameof(pattern));
        }

        var original = RoutePatternParser.Parse(pattern);

        return(PatternCore(original.RawText, Wrap(defaults), Wrap(parameterPolicies), requiredValues: null, original.PathSegments));
    }
예제 #2
0
        private ServiceEntry Create(MethodInfo method, string serviceName, string routeTemplate)
        {
            var serviceId         = _serviceIdGenerator.GenerateServiceId(method);
            var attributes        = method.GetCustomAttributes().ToList();
            var serviceDescriptor = new ServiceDescriptor
            {
                Id        = serviceId,
                RoutePath = RoutePatternParser.Parse(routeTemplate, serviceName, method.Name)
            };

            var descriptorAttributes = method.GetCustomAttributes <ServiceDescriptorAttribute>();

            foreach (var descriptorAttribute in descriptorAttributes)
            {
                descriptorAttribute.Apply(serviceDescriptor);
            }
            var authorization = attributes.Where(p => p is AuthorizationFilterAttribute).FirstOrDefault();

            if (authorization != null)
            {
                serviceDescriptor.EnableAuthorization(true);
            }
            if (authorization != null)
            {
                serviceDescriptor.AuthType(((authorization as AuthorizationAttribute)?.AuthType)
                                           ?? AuthorizationType.AppSecret);
            }
            var fastInvoker = GetHandler(serviceId, method);

            return(new ServiceEntry
            {
                Descriptor = serviceDescriptor,
                RoutePath = serviceDescriptor.RoutePath,
                MethodName = method.Name,
                Type = method.DeclaringType,
                Attributes = attributes,
                Func = (key, parameters) =>
                {
                    var instance = _serviceProvider.GetInstances(key, method.DeclaringType);
                    var list = new List <object>();

                    foreach (var parameterInfo in method.GetParameters())
                    {
                        var value = parameters[parameterInfo.Name];
                        var parameterType = parameterInfo.ParameterType;
                        var parameter = _typeConvertibleService.Convert(value, parameterType);
                        list.Add(parameter);
                    }
                    var result = fastInvoker(instance, list.ToArray());
                    return Task.FromResult(result);
                }
            });
        }
예제 #3
0
    public void Parse_OptionalParameter()
    {
        // Arrange
        var template = "{p?}";

        var expected = Pattern(template, Segment(ParameterPart("p", null, RoutePatternParameterKind.Optional)));

        // Act
        var actual = RoutePatternParser.Parse(template);

        // Assert
        Assert.Equal <RoutePattern>(expected, actual, new RoutePatternEqualityComparer());
    }
예제 #4
0
    public void Parse_SingleParameter()
    {
        // Arrange
        var template = "{p}";

        var expected = Pattern(template, Segment(ParameterPart("p")));

        // Act
        var actual = RoutePatternParser.Parse(template);

        // Assert
        Assert.Equal <RoutePattern>(expected, actual, new RoutePatternEqualityComparer());
    }
예제 #5
0
    public void ParseRouteParameter_ThrowsIf_ParameterContainsSpecialCharacters(
        string template,
        string parameterName)
    {
        // Arrange
        var expectedMessage = "The route parameter name '" + parameterName + "' is invalid. Route parameter " +
                              "names must be non-empty and cannot contain these characters: '{', '}', '/'. The '?' character " +
                              "marks a parameter as optional, and can occur only at the end of the parameter. The '*' character " +
                              "marks a parameter as catch-all, and can occur only at the start of the parameter.";

        // Act & Assert
        ExceptionAssert.Throws <RoutePatternException>(() => RoutePatternParser.Parse(template), expectedMessage);
    }
예제 #6
0
    public void Parse_MultipleLiterals()
    {
        // Arrange
        var template = "cool/awesome/super";

        var expected = Pattern(
            template,
            Segment(LiteralPart("cool")),
            Segment(LiteralPart("awesome")),
            Segment(LiteralPart("super")));

        // Act
        var actual = RoutePatternParser.Parse(template);

        // Assert
        Assert.Equal <RoutePattern>(expected, actual, new RoutePatternEqualityComparer());
    }
예제 #7
0
    public void Parse_MultipleParameters()
    {
        // Arrange
        var template = "{p1}/{p2}/{*p3}";

        var expected = Pattern(
            template,
            Segment(ParameterPart("p1")),
            Segment(ParameterPart("p2")),
            Segment(ParameterPart("p3", null, RoutePatternParameterKind.CatchAll)));

        // Act
        var actual = RoutePatternParser.Parse(template);

        // Assert
        Assert.Equal <RoutePattern>(expected, actual, new RoutePatternEqualityComparer());
    }
예제 #8
0
    public void Parse_ComplexSegment_LP()
    {
        // Arrange
        var template = "cool-{p1}";

        var expected = Pattern(
            template,
            Segment(
                LiteralPart("cool-"),
                ParameterPart("p1")));

        // Act
        var actual = RoutePatternParser.Parse(template);

        // Assert
        Assert.Equal <RoutePattern>(expected, actual, new RoutePatternEqualityComparer());
    }
예제 #9
0
    [InlineData(@"{p1:regex(([{{(])\w+)}", @"regex(([{(])\w+)")]                                      // Not balanced {
    public void Parse_RegularExpressions(string template, string constraint)
    {
        // Arrange
        var expected = Pattern(
            template,
            Segment(
                ParameterPart(
                    "p1",
                    null,
                    RoutePatternParameterKind.Standard,
                    Constraint(constraint))));

        // Act
        var actual = RoutePatternParser.Parse(template);

        // Assert
        Assert.Equal <RoutePattern>(expected, actual, new RoutePatternEqualityComparer());
    }
예제 #10
0
    public void Parse_ComplexSegment_OptionalParameterFollowingPeriod_PeriodAfterSlash()
    {
        // Arrange
        var template = "{p2}/.{p3?}";

        var expected = Pattern(
            template,
            Segment(ParameterPart("p2")),
            Segment(
                SeparatorPart("."),
                ParameterPart("p3", null, RoutePatternParameterKind.Optional)));

        // Act
        var actual = RoutePatternParser.Parse(template);

        // Assert
        Assert.Equal <RoutePattern>(expected, actual, new RoutePatternEqualityComparer());
    }
예제 #11
0
    public void Parse_ComplexSegment_ParametersFollowingPeriod()
    {
        // Arrange
        var template = "{p1}.{p2}";

        var expected = Pattern(
            template,
            Segment(
                ParameterPart("p1"),
                LiteralPart("."),
                ParameterPart("p2")));

        // Act
        var actual = RoutePatternParser.Parse(template);

        // Assert
        Assert.Equal <RoutePattern>(expected, actual, new RoutePatternEqualityComparer());
    }
예제 #12
0
        private ServiceEntry Create(MethodInfo method, string serviceName, string routeTemplate)
        {
            var serviceId         = _serviceIdGenerator.GenerateServiceId(method);
            var attributes        = method.GetCustomAttributes().ToList();
            var serviceDescriptor = new ServiceDescriptor
            {
                Id        = serviceId,
                RoutePath = RoutePatternParser.Parse(routeTemplate, serviceName, method.Name)
            };

            return(new ServiceEntry
            {
                Descriptor = serviceDescriptor,
                RoutePath = serviceDescriptor.RoutePath,
                MethodName = method.Name,
                Type = method.DeclaringType,
                Attributes = attributes,
            });
        }
예제 #13
0
        private ServiceEntry Create(MethodInfo method, string serviceName, string routeTemplate)
        {
            var serviceId         = _serviceIdGenerator.GenerateServiceId(method);
            var attributes        = method.GetCustomAttributes().ToList();
            var serviceDescriptor = new ServiceDescriptor
            {
                Id        = serviceId,
                RoutePath = RoutePatternParser.Parse(routeTemplate, serviceName, method.Name)
            };

            var descriptorAttributes = method.GetCustomAttributes <ServiceDescriptorAttribute>();

            foreach (var descriptorAttribute in descriptorAttributes)
            {
                descriptorAttribute.Apply(serviceDescriptor);
            }
            serviceDescriptor.EnableAuthorization(!serviceDescriptor.EnableAuthorization()
                ? attributes.Any(p => p is AuthorizationFilterAttribute) :
                                                  serviceDescriptor.EnableAuthorization());
            var fastInvoker = FastInvoke.GetMethodInvoker(method);

            return(new ServiceEntry
            {
                Descriptor = serviceDescriptor,
                Attributes = attributes,
                Func = (key, parameters) =>
                {
                    var instance = _serviceProvider.GetInstances(key, method.DeclaringType);
                    var list = new List <object>();

                    foreach (var parameterInfo in method.GetParameters())
                    {
                        var value = parameters[parameterInfo.Name];
                        var parameterType = parameterInfo.ParameterType;
                        var parameter = _typeConvertibleService.Convert(value, parameterType);
                        list.Add(parameter);
                    }
                    var result = fastInvoker(instance, list.ToArray()); //method.Invoke(instance, list.ToArray());
                    return Task.FromResult(result);
                }
            });
        }
        /// <summary>
        /// Creates the service entry.
        /// </summary>
        /// <param name="service">The service.</param>
        /// <returns>DnsServiceEntry.</returns>
        public DnsServiceEntry CreateServiceEntry(Type service)
        {
            DnsServiceEntry result        = null;
            var             routeTemplate = service.GetCustomAttribute <ServiceBundleAttribute>();
            var             objInstance   = _serviceProvider.GetInstances(service);
            var             behavior      = objInstance as DnsBehavior;
            var             path          = RoutePatternParser.Parse(routeTemplate.RouteTemplate, service.Name);

            if (path.Length > 0 && path[0] != '/')
            {
                path = $"/{path}";
            }
            if (behavior != null)
            {
                result = new DnsServiceEntry
                {
                    Behavior = behavior,
                    Type     = behavior.GetType(),
                    Path     = path
                }
            }
            ;
            return(result);
        }
예제 #15
0
 private RoutePatternMatcher CreateMatcher(string template, object defaults = null)
 {
     return(new RoutePatternMatcher(
                RoutePatternParser.Parse(template),
                new RouteValueDictionary(defaults)));
 }
예제 #16
0
 public void InvalidTemplate_WithRepeatedParameter()
 {
     var ex = ExceptionAssert.Throws <RoutePatternException>(
         () => RoutePatternParser.Parse("{Controller}.mvc/{id}/{controller}"),
         "The route parameter name 'controller' appears more than one time in the route template.");
 }
        private ServiceEntry Create(MethodInfo method, string serviceName, string routeTemplate, bool routeIsReWriteByServiceRoute = false)
        {
            var serviceId         = _serviceIdGenerator.GenerateServiceId(method);
            var attributes        = method.GetCustomAttributes().ToList();
            var serviceDescriptor = new ServiceDescriptor
            {
                Id        = serviceId,
                RoutePath = RoutePatternParser.Parse(routeTemplate, serviceName, method.Name, routeIsReWriteByServiceRoute)
            };
            var httpMethodAttributes = attributes.Where(p => p is HttpMethodAttribute).Select(p => p as HttpMethodAttribute).ToList();
            var httpMethods          = new List <string>();

            foreach (var httpAttribute in httpMethodAttributes)
            {
                httpMethods.AddRange(httpAttribute.HttpMethods);
            }
            if (!httpMethods.Any())
            {
                var paramTypes = GetParamTypes(method);
                if (paramTypes.All(p => p.Value.IsValueType || p.Value == typeof(string) || p.Value.IsEnum))
                {
                    httpMethods.Add(HttpMethod.GET.ToString());
                }
                else
                {
                    httpMethods.Add(HttpMethod.POST.ToString());
                }
            }
            serviceDescriptor.HttpMethod(httpMethods);
            var authorization = attributes.Where(p => p is AuthorizationFilterAttribute).FirstOrDefault();

            if (authorization != null)
            {
                serviceDescriptor.EnableAuthorization(true);
            }
            if (authorization != null)
            {
                serviceDescriptor.AuthType(((authorization as AuthorizationAttribute)?.AuthType)
                                           ?? AuthorizationType.AppSecret);
            }
            else
            {
                serviceDescriptor.EnableAuthorization(true);
                serviceDescriptor.AuthType(AuthorizationType.JWT);
            }

            var descriptorAttributes = method.GetCustomAttributes <ServiceDescriptorAttribute>();

            foreach (var descriptorAttribute in descriptorAttributes)
            {
                descriptorAttribute.Apply(serviceDescriptor);
            }
            var fastInvoker = GetHandler(serviceId, method);

            return(new ServiceEntry
            {
                Descriptor = serviceDescriptor,
                RoutePath = serviceDescriptor.RoutePath,
                Methods = httpMethods,
                MethodName = method.Name,
                Type = method.DeclaringType,
                Attributes = attributes,
                ParamTypes = GetParamTypes(method),
                CacheKeys = GetCackeKeys(method),
                Func = (key, parameters) =>
                {
                    object instance = null;
                    if (AppConfig.ServerOptions.IsModulePerLifetimeScope)
                    {
                        instance = _serviceProvider.GetInstancePerLifetimeScope(key, method.DeclaringType);
                    }
                    else
                    {
                        instance = _serviceProvider.GetInstances(key, method.DeclaringType);
                    }
                    var list = new List <object>();

                    foreach (var parameterInfo in method.GetParameters())
                    {
                        if (parameters.ContainsKey(parameterInfo.Name))
                        {
                            var value = parameters[parameterInfo.Name];
                            var parameterType = parameterInfo.ParameterType;
                            var parameter = _typeConvertibleService.Convert(value, parameterType);
                            list.Add(parameter);
                        }
                        //加入是否有默认值的判断,有默认值,并且用户没传,取默认值
                        else if (parameterInfo.HasDefaultValue && !parameters.ContainsKey(parameterInfo.Name))
                        {
                            list.Add(parameterInfo.DefaultValue);
                        }
                        else
                        {
                            list.Add(null);
                        }
                    }
                    var result = fastInvoker(instance, list.ToArray());
                    return Task.FromResult(result);
                }
            });
        }
예제 #18
0
 public void InvalidTemplate_CannotContainQuestionMark()
 {
     ExceptionAssert.Throws <RoutePatternException>(
         () => RoutePatternParser.Parse("foor?bar"),
         "The literal section 'foor?bar' is invalid. Literal sections cannot contain the '?' character.");
 }
예제 #19
0
 public void InvalidTemplate_CatchAllMarkedOptional()
 {
     ExceptionAssert.Throws <RoutePatternException>(
         () => RoutePatternParser.Parse("{a}/{*b?}"),
         "A catch-all parameter cannot be marked optional.");
 }
예제 #20
0
 public void InvalidTemplate_CannotStartWithTilde()
 {
     ExceptionAssert.Throws <RoutePatternException>(
         () => RoutePatternParser.Parse("~foo"),
         "The route template cannot start with a '~' character unless followed by a '/'.");
 }
예제 #21
0
 public void InvalidTemplate_CannotHaveMoreThanOneCatchAll()
 {
     ExceptionAssert.Throws <RoutePatternException>(
         () => RoutePatternParser.Parse("{*p1}/{*p2}"),
         "A catch-all parameter can only appear as the last segment of the route template.");
 }
예제 #22
0
 public void InvalidTemplate_WithCatchAllNotAtTheEndThrows()
 {
     ExceptionAssert.Throws <RoutePatternException>(
         () => RoutePatternParser.Parse("foo/{p1}/{*p2}/{p3}"),
         "A catch-all parameter can only appear as the last segment of the route template.");
 }
예제 #23
0
 public void InvalidTemplate_InvalidParameterNameWithOpenBracketThrows()
 {
     ExceptionAssert.Throws <RoutePatternException>(
         () => RoutePatternParser.Parse("{a}/{a{aa}/{z}"),
         "In a route parameter, '{' and '}' must be escaped with '{{' and '}}'.");
 }
        private ServiceEntry Create(MethodInfo method, string serviceName, string routeTemplate)
        {
            var serviceId         = _serviceIdGenerator.GenerateServiceId(method);
            var attributes        = method.GetCustomAttributes().ToList();
            var serviceDescriptor = new ServiceDescriptor
            {
                Id        = serviceId,
                RoutePath = RoutePatternParser.Parse(routeTemplate, serviceName, method.Name)
            };

            serviceDescriptor = SetPorts(serviceDescriptor);
            serviceDescriptor.EnableAuthorization(true);
            serviceDescriptor.AuthType(AuthorizationType.JWT);

            var descriptorAttributes = method.GetCustomAttributes <ServiceDescriptorAttribute>();

            foreach (var descriptorAttribute in descriptorAttributes)
            {
                descriptorAttribute.Apply(serviceDescriptor);
            }
            //var authorization = attributes.Where(p => p is AuthorizationFilterAttribute).FirstOrDefault();
            //if (authorization != null)
            //{
            //    serviceDescriptor.EnableAuthorization(true);
            //    serviceDescriptor.AuthType(((authorization as AuthorizationAttribute)?.AuthType)
            //        ?? AuthorizationType.AppSecret);
            //}
            var fastInvoker = GetHandler(serviceId, method);

            return(new ServiceEntry
            {
                Descriptor = serviceDescriptor,
                RoutePath = serviceDescriptor.RoutePath,
                MethodName = method.Name,
                Type = method.DeclaringType,
                Attributes = attributes,
                Func = (key, parameters) =>
                {
                    var instance = _serviceProvider.GetInstances(key, method.DeclaringType);
                    var list = new List <object>();

                    foreach (var parameterInfo in method.GetParameters())
                    {
                        if (parameterInfo.HasDefaultValue && !parameters.ContainsKey(parameterInfo.Name))
                        {
                            list.Add(parameterInfo.DefaultValue);
                            continue;
                        }
                        var value = parameters[parameterInfo.Name];
                        var parameterType = parameterInfo.ParameterType;
                        var parameter = _typeConvertibleService.Convert(value, parameterType);
                        list.Add(parameter);
                    }

                    if (parameters.ContainsKey("payload"))
                    {
                        if (RpcContext.GetContext().GetAttachment("payload") == null)
                        {
                            var serializer = ServiceLocator.GetService <ISerializer <string> >();
                            var payloadString = serializer.Serialize(parameters["payload"], true);
                            RpcContext.GetContext().SetAttachment("payload", payloadString);
                        }
                    }

                    var result = fastInvoker(instance, list.ToArray());
                    return Task.FromResult(result);
                }
            });
        }
예제 #25
0
        private ServiceEntry Create(MethodInfo method, string serviceName, string routeTemplate)
        {
            var serviceId         = _serviceIdGenerator.GenerateServiceId(method);
            var attributes        = method.GetCustomAttributes().ToList();
            var serviceDescriptor = new ServiceDescriptor
            {
                Id        = serviceId,
                RoutePath = RoutePatternParser.Parse(routeTemplate, serviceName, method.Name)
            };
            var           httpMethodAttributes = attributes.Where(p => p is HttpMethodAttribute).Select(p => p as HttpMethodAttribute).ToList();
            var           httpMethods          = new List <string>();
            StringBuilder httpMethod           = new StringBuilder();

            foreach (var attribute in httpMethodAttributes)
            {
                httpMethods.AddRange(attribute.HttpMethods);
                if (attribute.IsRegisterMetadata)
                {
                    httpMethod.AppendJoin(',', attribute.HttpMethods).Append(",");
                }
            }
            if (httpMethod.Length > 0)
            {
                httpMethod.Length = httpMethod.Length - 1;
                serviceDescriptor.HttpMethod(httpMethod.ToString());
            }
            var authorization = attributes.Where(p => p is AuthorizationFilterAttribute).FirstOrDefault();

            if (authorization != null)
            {
                serviceDescriptor.EnableAuthorization(true);
            }
            if (authorization != null)
            {
                serviceDescriptor.AuthType(((authorization as AuthorizationAttribute)?.AuthType)
                                           ?? AuthorizationType.AppSecret);
            }
            else
            {
                serviceDescriptor.EnableAuthorization(true);
                serviceDescriptor.AuthType(AuthorizationType.JWT);
            }

            var descriptorAttributes = method.GetCustomAttributes <ServiceDescriptorAttribute>();

            foreach (var descriptorAttribute in descriptorAttributes)
            {
                descriptorAttribute.Apply(serviceDescriptor);
            }
            var fastInvoker = GetHandler(serviceId, method);

            return(new ServiceEntry
            {
                Descriptor = serviceDescriptor,
                RoutePath = serviceDescriptor.RoutePath,
                Methods = httpMethods,
                MethodName = method.Name,
                Type = method.DeclaringType,
                Attributes = attributes,
                Func = (key, parameters) =>
                {
                    object instance = null;
                    if (AppConfig.ServerOptions.IsModulePerLifetimeScope)
                    {
                        instance = _serviceProvider.GetInstancePerLifetimeScope(key, method.DeclaringType);
                    }
                    else
                    {
                        instance = _serviceProvider.GetInstances(key, method.DeclaringType);
                    }
                    var list = new List <object>();

                    foreach (var parameterInfo in method.GetParameters())
                    {
                        //加入是否有默认值的判断,有默认值,并且用户没传,取默认值
                        if (parameterInfo.HasDefaultValue && !parameters.ContainsKey(parameterInfo.Name))
                        {
                            list.Add(parameterInfo.DefaultValue);
                            continue;
                        }
                        var value = parameters[parameterInfo.Name];
                        var parameterType = parameterInfo.ParameterType;
                        var parameter = _typeConvertibleService.Convert(value, parameterType);
                        list.Add(parameter);
                    }
                    var result = fastInvoker(instance, list.ToArray());
                    return Task.FromResult(result);
                }
            });
        }
예제 #26
0
 public void InvalidTemplate_SameParameterTwiceAndOneCatchAllThrows()
 {
     ExceptionAssert.Throws <RoutePatternException>(
         () => RoutePatternParser.Parse("{aaa}/{*AAA}"),
         "The route parameter name 'AAA' appears more than one time in the route template.");
 }