Exemplo n.º 1
0
        /// <summary>
        /// Adds a <see cref="RouteEndpoint"/> to the <see cref="IEndpointRouteBuilder"/> that matches HTTP requests
        /// for the specified pattern.
        /// </summary>
        /// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add the route to.</param>
        /// <param name="pattern">The route pattern.</param>
        /// <param name="requestDelegate">The delegate executed when the endpoint is matched.</param>
        public static IEndpointRouteBuilder Map(this IEndpointRouteBuilder endpoints, string pattern, RequestDelegate requestDelegate)
        {
            if (endpoints == null)
            {
                throw new ArgumentNullException(nameof(endpoints));
            }

            if (string.IsNullOrEmpty(pattern))
            {
                throw new ArgumentNullException(nameof(pattern));
            }

            if (requestDelegate == null)
            {
                throw new ArgumentNullException(nameof(requestDelegate));
            }

            // Route pattern should never include leading or trailing slashes
            var routePattern = pattern.TrimStart('/').TrimEnd('/').ToLower();

            var builder = new RouteEndpointBuilder(requestDelegate, routePattern)
            {
                DisplayName = pattern,
            };

            // Catch error and log when same endpoint is used.  Endpoints must have unique pattern. key exists
            endpoints.DataSources.Add(routePattern, builder.Build());

            return(endpoints);
        }
    public void RequireAuthorization_PolicyCallback()
    {
        // Arrange
        var builder     = new TestEndpointConventionBuilder();
        var requirement = new TestRequirement();

        // Act
        builder.RequireAuthorization(policyBuilder => policyBuilder.Requirements.Add(requirement));

        // Assert
        var convention = Assert.Single(builder.Conventions);

        var endpointModel = new RouteEndpointBuilder((context) => Task.CompletedTask, RoutePatternFactory.Parse("/"), 0);

        convention(endpointModel);

        Assert.Equal(2, endpointModel.Metadata.Count);
        var authMetadata = Assert.IsAssignableFrom <IAuthorizeData>(endpointModel.Metadata[0]);

        Assert.Null(authMetadata.Policy);

        var policy = Assert.IsAssignableFrom <AuthorizationPolicy>(endpointModel.Metadata[1]);

        Assert.Equal(1, policy.Requirements.Count);
        Assert.Equal(requirement, policy.Requirements[0]);
    }
        /// <summary>
        /// Adds Easy.Endpoints routes to EndpointRouteBuilder
        /// </summary>
        /// <param name="endpoints">Microsoft.AspNetCore.Routing.IEndpointRouteBuilder to add Easy.Endpoints to</param>
        /// <returns>Returns Microsoft.AspNetCore.Builder.IEndpointConventionBuilder for endpoints</returns>
        public static IEndpointConventionBuilder MapEasyEndpoints(
            this IEndpointRouteBuilder endpoints)
        {
            var requestEndPoints = endpoints.ServiceProvider.GetRequiredService <IEndpointManifest>().ToArray();
            var dataSource       = endpoints.DataSources.OfType <EasyEndpointDataSource>().FirstOrDefault();

            if (dataSource is null)
            {
                dataSource = new EasyEndpointDataSource();
                endpoints.DataSources.Add(dataSource);
            }
            var results = new IEndpointConventionBuilder[requestEndPoints.Length];
            var i       = 0;

            foreach (var endPoint in requestEndPoints)
            {
                var builder = new RouteEndpointBuilder(
                    BuildDelegate(endPoint),
                    endPoint.Pattern, endPoint.Order)
                {
                    DisplayName = endPoint.Name,
                };
                foreach (var meta in endPoint.Meta)
                {
                    builder.Metadata.Add(meta);
                }
                results[i] = dataSource.AddEndpointBuilder(builder);
                i++;
            }
            return(new GroupedEasyEndpointConventionBuilder(results));
        }
    public void RequireAuthorization_PolicyCallbackWithAuthorize()
    {
        // Arrange
        var builder     = new TestEndpointConventionBuilder();
        var authorize   = new AuthorizeAttribute();
        var requirement = new TestRequirement();

        // Act
        builder.RequireAuthorization(policyBuilder => policyBuilder.Requirements.Add(requirement));

        // Assert
        var convention = Assert.Single(builder.Conventions);

        var endpointModel = new RouteEndpointBuilder((context) => Task.CompletedTask, RoutePatternFactory.Parse("/"), 0);

        endpointModel.Metadata.Add(authorize);
        convention(endpointModel);

        // Confirm that we don't add another authorize if one already exists
        Assert.Equal(2, endpointModel.Metadata.Count);
        Assert.Equal(authorize, endpointModel.Metadata[0]);
        var policy = Assert.IsAssignableFrom <AuthorizationPolicy>(endpointModel.Metadata[1]);

        Assert.Equal(1, policy.Requirements.Count);
        Assert.Equal(requirement, policy.Requirements[0]);
    }
Exemplo n.º 5
0
        public MvcEndpointDataSource(IActionInvokerFactory actionInvokerFactory,
                                     IActionDescriptorProvider actionDiscriptorProvider,
                                     RoutePatternTransformer transformer)
        {
            _actionInvokerFactory = actionInvokerFactory;

            _endpoints = new Lazy <IReadOnlyList <Endpoint> >(Create());

            List <Endpoint> Create()
            {
                var Descriptors = actionDiscriptorProvider.GetActionDescriptors;

                return(Descriptors.Select(CreateEndpoint).ToList());
            }

            Endpoint CreateEndpoint(ActionDescriptor actionDiscriptor)
            {
                var routePattern    = RoutePatternFactory.Parse(actionDiscriptor.RouteInfo.Template);
                var newRoutePattern = transformer.SubstituteRequiredValues(routePattern, new Dictionary <string, string>
                {
                    ["controller"] = actionDiscriptor.ControllerName,
                    ["action"]     = actionDiscriptor.ActionName
                });

                routePattern = routePattern ?? newRoutePattern;
                var endPointBuilder = new RouteEndpointBuilder(InvokeAsync, routePattern, actionDiscriptor.RouteInfo.Order ?? 0);

                endPointBuilder.Metadata.Add(actionDiscriptor);
                return(endPointBuilder.Build());
            }
        }
Exemplo n.º 6
0
        protected override List <Endpoint> CreateEndpoints(IReadOnlyList <ActionDescriptor> actions, IReadOnlyList <Action <EndpointBuilder> > conventions)
        {
            var endpoints = new List <Endpoint>();

            foreach (var action in actions)
            {
                var attributeInfo = action.AttributeRouteInfo;
                if (attributeInfo == null) //Conventional Routing
                {
                    foreach (var route in _conventionalRoutes)
                    {
                        var pattern = _routePatternTransformer.SubstituteRequiredValues(route.Pattern, action.RouteValues);
                        if (pattern != null)
                        {
                            RouteEndpointBuilder builder = new RouteEndpointBuilder(_requestDelegate, pattern, route.Order);
                            builder.Metadata.Add(action);
                            endpoints.Add(builder.Build());
                        }
                    }
                }
                else //Attribute Routing
                {
                    var original = RoutePatternFactory.Parse(attributeInfo.Template);
                    var pattern  = _routePatternTransformer.SubstituteRequiredValues(original, action.RouteValues);
                    if (pattern != null)
                    {
                        RouteEndpointBuilder builder = new RouteEndpointBuilder(_requestDelegate, pattern, attributeInfo.Order);
                        builder.Metadata.Add(action);
                        endpoints.Add(builder.Build());
                    }
                }
            }
            return(endpoints);
        }
    private List <Endpoint> BuildEndpoints()
    {
        List <Endpoint> endpoints = new List <Endpoint>();

        foreach (var hubMethod in HubMethods)
        {
            var requiredValues = new { hub = hubMethod.Hub, method = hubMethod.Method };
            var order          = 1;

            foreach (var pattern in Patterns)
            {
                var resolvedPattern = _routePatternTransformer.SubstituteRequiredValues(pattern, requiredValues);
                if (resolvedPattern == null)
                {
                    continue;
                }

                var endpointBuilder = new RouteEndpointBuilder(
                    hubMethod.RequestDelegate,
                    resolvedPattern,
                    order++);
                endpointBuilder.DisplayName = $"{hubMethod.Hub}.{hubMethod.Method}";

                foreach (var convention in _conventions)
                {
                    convention(endpointBuilder);
                }

                endpoints.Add(endpointBuilder.Build());
            }
        }

        return(endpoints);
    }
Exemplo n.º 8
0
        /// <summary>
        /// Adds a <see cref="RouteEndpoint"/> to the <see cref="IEndpointRouteBuilder"/> that matches HTTP requests
        /// for the specified pattern.
        /// </summary>
        /// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add the route to.</param>
        /// <param name="pattern">The route pattern.</param>
        /// <param name="action">The delegate executed when the endpoint is matched.</param>
        /// <returns>A <see cref="IEndpointConventionBuilder"/> that can be used to further customize the endpoint.</returns>
        public static MinimalActionEndpointConventionBuilder Map(
            this IEndpointRouteBuilder endpoints,
            RoutePattern pattern,
            Delegate action)
        {
            if (endpoints is null)
            {
                throw new ArgumentNullException(nameof(endpoints));
            }

            if (pattern is null)
            {
                throw new ArgumentNullException(nameof(pattern));
            }

            if (action is null)
            {
                throw new ArgumentNullException(nameof(action));
            }

            const int defaultOrder = 0;

            var builder = new RouteEndpointBuilder(
                RequestDelegateFactory.Create(action, endpoints.ServiceProvider),
                pattern,
                defaultOrder)
            {
                DisplayName = pattern.RawText ?? pattern.DebuggerToString(),
            };

            // REVIEW: Should we add an IActionMethodMetadata with just MethodInfo on it so we are
            // explicit about the MethodInfo representing the "action" and not the RequestDelegate?

            // Add MethodInfo as metadata to assist with OpenAPI generation for the endpoint.
            builder.Metadata.Add(action.Method);

            // Add delegate attributes as metadata
            var attributes = action.Method.GetCustomAttributes();

            // This can be null if the delegate is a dynamic method or compiled from an expression tree
            if (attributes is not null)
            {
                foreach (var attribute in attributes)
                {
                    builder.Metadata.Add(attribute);
                }
            }

            var dataSource = endpoints.DataSources.OfType <ModelEndpointDataSource>().FirstOrDefault();

            if (dataSource is null)
            {
                dataSource = new ModelEndpointDataSource();
                endpoints.DataSources.Add(dataSource);
            }

            return(new MinimalActionEndpointConventionBuilder(dataSource.AddEndpointBuilder(builder)));
        }
 private static RouteEndpointBuilder CreateEndpointBuilder(ProxyRoute proxyRoute, Cluster cluster)
 {
     var endpointBuilder = new RouteEndpointBuilder(context => Task.CompletedTask, RoutePatternFactory.Parse(""), 0);
     var routeConfig     = new RouteConfig(
         proxyRoute,
         new ClusterInfo("cluster-1")
     {
         Config = new ClusterConfig(cluster, default)
     },
        /// <summary>
        /// Adds a <see cref="RouteEndpoint"/> to the <see cref="IEndpointRouteBuilder"/> that matches HTTP requests
        /// for the specified pattern.
        /// </summary>
        /// <param name="builder">The <see cref="IEndpointRouteBuilder"/> to add the route to.</param>
        /// <param name="pattern">The route pattern.</param>
        /// <param name="displayName">The display name for the endpoint.</param>
        /// <param name="requestDelegate">The delegate executed when the endpoint is matched.</param>
        /// <param name="metadata">Metadata that is added to the endpoint.</param>
        /// <returns>A <see cref="IEndpointConventionBuilder"/> that can be used to further customize the endpoint.</returns>
        public static IEndpointConventionBuilder Map(
            this IEndpointRouteBuilder builder,
            RoutePattern pattern,
            string displayName,
            RequestDelegate requestDelegate,
            params object[] metadata)
        {
            if (builder == null)
            {
                throw new ArgumentNullException(nameof(builder));
            }

            if (pattern == null)
            {
                throw new ArgumentNullException(nameof(pattern));
            }

            if (requestDelegate == null)
            {
                throw new ArgumentNullException(nameof(requestDelegate));
            }

            const int defaultOrder = 0;

            var routeEndpointBuilder = new RouteEndpointBuilder(
                requestDelegate,
                pattern,
                defaultOrder)
            {
                DisplayName = displayName
            };

            // Add delegate attributes as metadata
            foreach (var attribute in requestDelegate.Method.GetCustomAttributes())
            {
                routeEndpointBuilder.Metadata.Add(attribute);
            }

            if (metadata != null)
            {
                foreach (var item in metadata)
                {
                    routeEndpointBuilder.Metadata.Add(item);
                }
            }

            var modelEndpointDataSource = builder.DataSources.OfType <ModelEndpointDataSource>().FirstOrDefault();

            if (modelEndpointDataSource == null)
            {
                modelEndpointDataSource = new ModelEndpointDataSource();
                builder.DataSources.Add(modelEndpointDataSource);
            }

            return(modelEndpointDataSource.AddEndpointBuilder(routeEndpointBuilder));
        }
        private static Endpoint CreateAspNetCoreEndpoint(RouteConfig routeConfig)
        {
            var endpointBuilder = new RouteEndpointBuilder(
                requestDelegate: httpContext => Task.CompletedTask,
                routePattern: RoutePatternFactory.Parse("/"),
                order: 0);

            endpointBuilder.Metadata.Add(routeConfig);
            return(endpointBuilder.Build());
        }
        /// <summary>
        /// Adds a <see cref="RouteEndpoint"/> to the <see cref="IEndpointRouteBuilder"/> that matches HTTP requests
        /// for the specified pattern.
        /// </summary>
        /// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add the route to.</param>
        /// <param name="pattern">The route pattern.</param>
        /// <param name="action">The delegate executed when the endpoint is matched.</param>
        /// <returns>A <see cref="IEndpointConventionBuilder"/> that can be used to further customize the endpoint.</returns>
        public static MinimalActionEndpointConventionBuilder Map(
            this IEndpointRouteBuilder endpoints,
            RoutePattern pattern,
            Delegate action)
        {
            if (endpoints is null)
            {
                throw new ArgumentNullException(nameof(endpoints));
            }

            if (pattern is null)
            {
                throw new ArgumentNullException(nameof(pattern));
            }

            if (action is null)
            {
                throw new ArgumentNullException(nameof(action));
            }

            const int defaultOrder = 0;

            var builder = new RouteEndpointBuilder(
                RequestDelegateFactory.Create(action),
                pattern,
                defaultOrder)
            {
                DisplayName = pattern.RawText ?? pattern.DebuggerToString(),
            };

            // Add delegate attributes as metadata
            var attributes = action.Method.GetCustomAttributes();

            // This can be null if the delegate is a dynamic method or compiled from an expression tree
            if (attributes is not null)
            {
                foreach (var attribute in attributes)
                {
                    builder.Metadata.Add(attribute);
                }
            }

            var dataSource = endpoints.DataSources.OfType <ModelEndpointDataSource>().FirstOrDefault();

            if (dataSource is null)
            {
                dataSource = new ModelEndpointDataSource();
                endpoints.DataSources.Add(dataSource);
            }

            return(new MinimalActionEndpointConventionBuilder(dataSource.AddEndpointBuilder(builder)));
        }
Exemplo n.º 13
0
        /// <summary>
        /// 生成终结点规则
        /// </summary>
        /// <param name="template"></param>
        /// <param name="areaName"></param>
        /// <param name="defaultsDictionary"></param>
        /// <param name="constraintsDictionary"></param>
        /// <param name="dataTokens"></param>
        public void MapRoute(string template, string areaName, RouteValueDictionary defaultsDictionary, RouteValueDictionary constraintsDictionary, object dataTokens)
        {
            foreach (var keys in _AshxBuilder.RouteDefaults)
            {
                if (true)
                {
                    string DisplayName = $"Ashx:{keys.Value.AshxType.FullName}.default";

                    if (EndpointExists(DisplayName))
                    {
                        continue;
                    }

                    var _routePattern1 = RoutePatternFactory.Parse(template);//"{controller=" + keys.Key + "}/{action}/{id?}"
                    _routePattern1.Defaults.TryGetValue("controller", out object controller);
                    _routePattern1.Defaults.TryGetValue("action", out object action);

                    if (keys.Key.EqualsNotCase(controller.ToString()) && keys.Value.Ashxes.TryGetValue(action.ToString(), out var ashx))
                    {
                        string _template = template;
                        foreach (var item in _routePattern1.Parameters)
                        {
                            _template = _template.Replace($"{{{item.Name}{(item.IsOptional ? "?" : $"={item.Default}")}}}", "").Replace("//", "/");
                        }
                        bool iscontroller = false;
A:
                        if (iscontroller)
                        {
                            DisplayName += $".{controller}";
                            _template    = $"{_template}{controller}";
                        }

                        //string _template = $"{_routePattern1.PathSegments}"; //template.Replace($"{{controller={controller}}}/", controller).Replace($"{{action={action}}}", "");
                        var routePattern = RoutePatternFactory.Parse(_template, defaultsDictionary, null, null); //RoutePatternFactory.Pattern(null, parameterPolicies: null, _routePattern1.PathSegments);//_defaultsDictionary

                        var routeEndpointBuilder = new RouteEndpointBuilder(requestDelegate: InitialLoadAsync, routePattern: routePattern, order: 0)
                        {
                            DisplayName = DisplayName
                        };

                        routeEndpointBuilder.Metadata.Add(keys.Value);
                        routeEndpointBuilder.Metadata.Add(ashx);
                        routeEndpointBuilder.Metadata.Add(new RouteValueDictionary(dataTokens));
                        routeEndpointBuilder.Metadata.Add(new { areaName });

                        _endpointBuilders.Add(routeEndpointBuilder);

                        if (!iscontroller)
                        {
                            iscontroller = true; goto A;
                        }
                    }
Exemplo n.º 14
0
        private List <Endpoint> BuildEndpoints()
        {
            var endpoints = new List <Endpoint>();

            if (!_commandTypes.Any())
            {
                return(endpoints);
            }

            var dispatcherFactory = _serviceProvider.GetRequiredService <ICommandDispatcherFactory>();

            // Step 1: Locate all of the commands
            foreach (var cmdType in _commandTypes)
            {
                var routeAttribute = cmdType.GetCustomAttribute <CommandRouteAttribute>();
                if (routeAttribute == null)
                {
                    _logger.LogTrace($"No routing attributes found for command: {cmdType.Name}");
                    continue;
                }

                var authorizeAttribute = cmdType.GetCustomAttribute <AuthorizeAttribute>();

                var commandDispatcher = dispatcherFactory.GetDispatcher(cmdType);

                var endpointBuilder = new RouteEndpointBuilder(
                    context => commandDispatcher.Dispatch(context),
                    RoutePatternFactory.Parse(routeAttribute.Template),
                    routeAttribute.Order)
                {
                    DisplayName = $"Command: {cmdType.Name}"
                };

                endpointBuilder.Metadata.Add(new HttpMethodMetadata(new[] { routeAttribute.Method }));

                if (authorizeAttribute != null)
                {
                    endpointBuilder.Metadata.Add(authorizeAttribute);
                }

                foreach (var convention in _conventions)
                {
                    convention(endpointBuilder);
                }

                endpoints.Add(endpointBuilder.Build());
            }

            return(endpoints);
        }
Exemplo n.º 15
0
        private static RouteEndpointBuilder CreateEndpointBuilder(RouteConfig routeConfig, ClusterConfig cluster)
        {
            var endpointBuilder = new RouteEndpointBuilder(context => Task.CompletedTask, RoutePatternFactory.Parse(""), 0);
            var routeModel      = new RouteModel(
                routeConfig,
                new ClusterState("cluster-1")
            {
                Model = new ClusterModel(cluster, new HttpMessageInvoker(new HttpClientHandler()))
            },
                HttpTransformer.Default);

            endpointBuilder.Metadata.Add(routeModel);

            return(endpointBuilder);
        }
    public void AllowAnonymous_Default()
    {
        // Arrange
        var builder = new TestEndpointConventionBuilder();

        // Act
        builder.AllowAnonymous();

        // Assert
        var convention = Assert.Single(builder.Conventions);

        var endpointModel = new RouteEndpointBuilder((context) => Task.CompletedTask, RoutePatternFactory.Parse("/"), 0);

        convention(endpointModel);

        Assert.IsAssignableFrom <IAllowAnonymous>(Assert.Single(endpointModel.Metadata));
    }
        public void RequireAuthorization_PolicyName()
        {
            // Arrange
            var builder = new TestEndpointConventionBuilder();

            // Act
            builder.RequireAuthorization("policy");

            // Assert
            var convention = Assert.Single(builder.Conventions);

            var endpointModel = new RouteEndpointBuilder((context) => Task.CompletedTask, RoutePatternFactory.Parse("/"), 0);

            convention(endpointModel);

            Assert.Equal("policy", Assert.IsAssignableFrom <IAuthorizeData>(Assert.Single(endpointModel.Metadata)).Policy);
        }
    public void RequireAuthorization_IAuthorizeData()
    {
        // Arrange
        var builder  = new TestEndpointConventionBuilder();
        var metadata = new AuthorizeAttribute();

        // Act
        builder.RequireAuthorization(metadata);

        // Assert
        var convention = Assert.Single(builder.Conventions);

        var endpointModel = new RouteEndpointBuilder((context) => Task.CompletedTask, RoutePatternFactory.Parse("/"), 0);

        convention(endpointModel);

        Assert.Equal(metadata, Assert.Single(endpointModel.Metadata));
    }
Exemplo n.º 19
0
    private static OpenApiOperation?GetOperationForEndpoint(RouteEndpointBuilder routeEndpointBuilder)
    {
        var pattern         = routeEndpointBuilder.RoutePattern;
        var metadata        = new EndpointMetadataCollection(routeEndpointBuilder.Metadata);
        var methodInfo      = metadata.OfType <MethodInfo>().SingleOrDefault();
        var serviceProvider = routeEndpointBuilder.ServiceProvider;

        if (methodInfo == null || serviceProvider == null)
        {
            return(null);
        }

        var hostEnvironment          = serviceProvider.GetService <IHostEnvironment>();
        var serviceProviderIsService = serviceProvider.GetService <IServiceProviderIsService>();
        var generator = new OpenApiGenerator(hostEnvironment, serviceProviderIsService);

        return(generator.GetOpenApiOperation(methodInfo, metadata, pattern));
    }
Exemplo n.º 20
0
        private RouteEndpoint CreateEndpoint(
            ActionDescriptor action,
            RoutePattern routePattern,
            string routeName,
            int order,
            RouteValueDictionary dataTokens,
            bool suppressLinkGeneration,
            bool suppressPathMatching,
            List <Action <EndpointBuilder> > conventions)
        {
            RequestDelegate requestDelegate = (context) =>
            {
                var routeData = context.GetRouteData();

                var actionContext = new ActionContext(context, routeData, action);

                var invoker = _invokerFactory.CreateInvoker(actionContext);
                return(invoker.InvokeAsync());
            };

            var endpointBuilder = new RouteEndpointBuilder(requestDelegate, routePattern, order);

            AddEndpointMetadata(
                endpointBuilder.Metadata,
                action,
                routeName,
                dataTokens,
                suppressLinkGeneration,
                suppressPathMatching);

            endpointBuilder.DisplayName = action.DisplayName;

            // REVIEW: When should conventions be run
            // Metadata should have lower precedence that data source metadata
            if (conventions != null)
            {
                foreach (var convention in conventions)
                {
                    convention(endpointBuilder);
                }
            }

            return((RouteEndpoint)endpointBuilder.Build());
        }
    public void RequireAuthorization_IAuthorizeData_Empty()
    {
        // Arrange
        var builder = new TestEndpointConventionBuilder();

        // Act
        builder.RequireAuthorization(Array.Empty <IAuthorizeData>());

        // Assert
        var convention = Assert.Single(builder.Conventions);

        var endpointModel = new RouteEndpointBuilder((context) => Task.CompletedTask, RoutePatternFactory.Parse("/"), 0);

        convention(endpointModel);

        var authMetadata = Assert.IsAssignableFrom <IAuthorizeData>(Assert.Single(endpointModel.Metadata));

        Assert.Null(authMetadata.Policy);
    }
    public void RequireHost_HostNames()
    {
        // Arrange
        var builder = new TestEndpointConventionBuilder();

        // Act
        builder.RequireHost("contoso.com:8080");

        // Assert
        var convention = Assert.Single(builder.Conventions);

        var endpointModel = new RouteEndpointBuilder((context) => Task.CompletedTask, RoutePatternFactory.Parse("/"), 0);

        convention(endpointModel);

        var hostMetadata = Assert.IsType <HostAttribute>(Assert.Single(endpointModel.Metadata));

        Assert.Equal("contoso.com:8080", hostMetadata.Hosts.Single());
    }
        private void UpdateEndpoints()
        {
            lock (_locker)
            {
                var endpoints = new List <HttpEndpoint>();
                var order     = 0;

                foreach (var endpoint in _idsendpoints)
                {
                    RequestDelegate handler = context => HandleEndpoint(context, endpoint);
                    var             pattern = RoutePatternFactory.Parse(endpoint.Path.Value);
                    var             builder = new RouteEndpointBuilder(handler, pattern, ++order);
                    _conventions.ForEach(a => a.Invoke(builder));
                    builder.DisplayName = endpoint.Name;
                    endpoints.Add(builder.Build());
                }

                _endpoints = endpoints;
            }
        }
Exemplo n.º 24
0
    public void Build_AllValuesSet_EndpointCreated()
    {
        const int       defaultOrder    = 0;
        var             metadata        = new object();
        RequestDelegate requestDelegate = (d) => null;

        var builder = new RouteEndpointBuilder(requestDelegate, RoutePatternFactory.Parse("/"), defaultOrder)
        {
            DisplayName = "Display name!",
            Metadata    = { metadata }
        };

        var endpoint = Assert.IsType <RouteEndpoint>(builder.Build());

        Assert.Equal("Display name!", endpoint.DisplayName);
        Assert.Equal(defaultOrder, endpoint.Order);
        Assert.Equal(requestDelegate, endpoint.RequestDelegate);
        Assert.Equal("/", endpoint.RoutePattern.RawText);
        Assert.Equal(metadata, Assert.Single(endpoint.Metadata));
    }
Exemplo n.º 25
0
        private void Initialize()
        {
            int i = 0;

            _endpoints = new List <Endpoint>();
            foreach (var item in _options.Value.SwaggerGeneratorOptions.SwaggerDocs)
            {
                var executor = new SwaggerExecutor(item.Value, _asV2, _options.Value.HtmlTemplate);

                var builder = new RouteEndpointBuilder(
                    requestDelegate: _asHtml ? (RequestDelegate)executor.InvokeAsHtml : executor.Invoke,
                    routePattern: RoutePatternFactory.Parse(_routeTemplate.Replace("{documentName}", item.Key)),
                    order: ++i);
                builder.DisplayName = $"Swagger.Document.{item.Key} ({item.Value.Title})";

                foreach (var convention in _conventions)
                {
                    convention.Invoke(builder);
                }

                _endpoints.Add(builder.Build());
            }
        }
    public void RequireAuthorization_Policy()
    {
        // Arrange
        var builder = new TestEndpointConventionBuilder();
        var policy  = new AuthorizationPolicyBuilder().RequireAssertion(_ => true).Build();

        // Act
        builder.RequireAuthorization(policy);

        // Assert
        var convention = Assert.Single(builder.Conventions);

        var endpointModel = new RouteEndpointBuilder((context) => Task.CompletedTask, RoutePatternFactory.Parse("/"), 0);

        convention(endpointModel);

        Assert.Equal(2, endpointModel.Metadata.Count);
        var authMetadata = Assert.IsAssignableFrom <IAuthorizeData>(endpointModel.Metadata[0]);

        Assert.Null(authMetadata.Policy);

        Assert.Equal(policy, endpointModel.Metadata[1]);
    }
    public void RequireAuthorization_PolicyWithAuthorize()
    {
        // Arrange
        var builder   = new TestEndpointConventionBuilder();
        var policy    = new AuthorizationPolicyBuilder().RequireAssertion(_ => true).Build();
        var authorize = new AuthorizeAttribute();

        // Act
        builder.RequireAuthorization(policy);

        // Assert
        var convention = Assert.Single(builder.Conventions);

        var endpointModel = new RouteEndpointBuilder((context) => Task.CompletedTask, RoutePatternFactory.Parse("/"), 0);

        endpointModel.Metadata.Add(authorize);
        convention(endpointModel);

        // Confirm that we don't add another authorize if one already exists
        Assert.Equal(2, endpointModel.Metadata.Count);
        Assert.Equal(authorize, endpointModel.Metadata[0]);
        Assert.Equal(policy, endpointModel.Metadata[1]);
    }
        /// <summary>
        /// Adds a <see cref="RouteEndpoint"/> to the <see cref="IEndpointRouteBuilder"/> that matches HTTP requests
        /// for the specified pattern.
        /// </summary>
        /// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add the route to.</param>
        /// <param name="pattern">The route pattern.</param>
        /// <param name="handler">The delegate executed when the endpoint is matched.</param>
        /// <returns>A <see cref="IEndpointConventionBuilder"/> that can be used to further customize the endpoint.</returns>
        public static DelegateEndpointConventionBuilder Map(
            this IEndpointRouteBuilder endpoints,
            RoutePattern pattern,
            Delegate handler)
        {
            if (endpoints is null)
            {
                throw new ArgumentNullException(nameof(endpoints));
            }

            if (pattern is null)
            {
                throw new ArgumentNullException(nameof(pattern));
            }

            if (handler is null)
            {
                throw new ArgumentNullException(nameof(handler));
            }

            const int defaultOrder = 0;

            var routeParams = new List <string>(pattern.Parameters.Count);

            foreach (var part in pattern.Parameters)
            {
                routeParams.Add(part.Name);
            }

            var routeHandlerOptions = endpoints.ServiceProvider?.GetService <IOptions <RouteHandlerOptions> >();

            var options = new RequestDelegateFactoryOptions
            {
                ServiceProvider     = endpoints.ServiceProvider,
                RouteParameterNames = routeParams,
                ThrowOnBadRequest   = routeHandlerOptions?.Value.ThrowOnBadRequest ?? false,
            };

            var requestDelegateResult = RequestDelegateFactory.Create(handler, options);

            var builder = new RouteEndpointBuilder(
                requestDelegateResult.RequestDelegate,
                pattern,
                defaultOrder)
            {
                DisplayName = pattern.RawText ?? pattern.DebuggerToString(),
            };

            // REVIEW: Should we add an IActionMethodMetadata with just MethodInfo on it so we are
            // explicit about the MethodInfo representing the "handler" and not the RequestDelegate?

            // Add MethodInfo as metadata to assist with OpenAPI generation for the endpoint.
            builder.Metadata.Add(handler.Method);

            // Methods defined in a top-level program are generated as statics so the delegate
            // target will be null. Inline lambdas are compiler generated method so they can
            // be filtered that way.
            if (GeneratedNameParser.TryParseLocalFunctionName(handler.Method.Name, out var endpointName) ||
                !TypeHelper.IsCompilerGeneratedMethod(handler.Method))
            {
                endpointName ??= handler.Method.Name;

                builder.Metadata.Add(new EndpointNameMetadata(endpointName));
                builder.Metadata.Add(new RouteNameMetadata(endpointName));
                builder.DisplayName = $"{builder.DisplayName} => {endpointName}";
            }

            // Add delegate attributes as metadata
            var attributes = handler.Method.GetCustomAttributes();

            // Add add request delegate metadata
            foreach (var metadata in requestDelegateResult.EndpointMetadata)
            {
                builder.Metadata.Add(metadata);
            }

            // This can be null if the delegate is a dynamic method or compiled from an expression tree
            if (attributes is not null)
            {
                foreach (var attribute in attributes)
                {
                    builder.Metadata.Add(attribute);
                }
            }

            var dataSource = endpoints.DataSources.OfType <ModelEndpointDataSource>().FirstOrDefault();

            if (dataSource is null)
            {
                dataSource = new ModelEndpointDataSource();
                endpoints.DataSources.Add(dataSource);
            }

            return(new DelegateEndpointConventionBuilder(dataSource.AddEndpointBuilder(builder)));
        }
Exemplo n.º 29
0
    public void AddEndpoints(
        List <Endpoint> endpoints,
        HashSet <string> routeNames,
        ActionDescriptor action,
        IReadOnlyList <ConventionalRouteEntry> routes,
        IReadOnlyList <Action <EndpointBuilder> > conventions,
        bool createInertEndpoints)
    {
        if (endpoints == null)
        {
            throw new ArgumentNullException(nameof(endpoints));
        }

        if (routeNames == null)
        {
            throw new ArgumentNullException(nameof(routeNames));
        }

        if (action == null)
        {
            throw new ArgumentNullException(nameof(action));
        }

        if (routes == null)
        {
            throw new ArgumentNullException(nameof(routes));
        }

        if (conventions == null)
        {
            throw new ArgumentNullException(nameof(conventions));
        }

        if (createInertEndpoints)
        {
            var builder = new InertEndpointBuilder()
            {
                DisplayName     = action.DisplayName,
                RequestDelegate = _requestDelegate,
            };
            AddActionDataToBuilder(
                builder,
                routeNames,
                action,
                routeName: null,
                dataTokens: null,
                suppressLinkGeneration: false,
                suppressPathMatching: false,
                conventions,
                Array.Empty <Action <EndpointBuilder> >());
            endpoints.Add(builder.Build());
        }

        if (action.AttributeRouteInfo?.Template == null)
        {
            // Check each of the conventional patterns to see if the action would be reachable.
            // If the action and pattern are compatible then create an endpoint with action
            // route values on the pattern.
            foreach (var route in routes)
            {
                // A route is applicable if:
                // 1. It has a parameter (or default value) for 'required' non-null route value
                // 2. It does not have a parameter (or default value) for 'required' null route value
                var updatedRoutePattern = _routePatternTransformer.SubstituteRequiredValues(route.Pattern, action.RouteValues);
                if (updatedRoutePattern == null)
                {
                    continue;
                }

                var requestDelegate = CreateRequestDelegate(action, route.DataTokens) ?? _requestDelegate;

                // We suppress link generation for each conventionally routed endpoint. We generate a single endpoint per-route
                // to handle link generation.
                var builder = new RouteEndpointBuilder(requestDelegate, updatedRoutePattern, route.Order)
                {
                    DisplayName = action.DisplayName,
                };
                AddActionDataToBuilder(
                    builder,
                    routeNames,
                    action,
                    route.RouteName,
                    route.DataTokens,
                    suppressLinkGeneration: true,
                    suppressPathMatching: false,
                    conventions,
                    route.Conventions);
                endpoints.Add(builder.Build());
            }
        }
        else
        {
            var requestDelegate       = CreateRequestDelegate(action) ?? _requestDelegate;
            var attributeRoutePattern = RoutePatternFactory.Parse(action.AttributeRouteInfo.Template);

            // Modify the route and required values to ensure required values can be successfully subsituted.
            // Subsitituting required values into an attribute route pattern should always succeed.
            var(resolvedRoutePattern, resolvedRouteValues) = ResolveDefaultsAndRequiredValues(action, attributeRoutePattern);

            var updatedRoutePattern = _routePatternTransformer.SubstituteRequiredValues(resolvedRoutePattern, resolvedRouteValues);
            if (updatedRoutePattern == null)
            {
                // This kind of thing can happen when a route pattern uses a *reserved* route value such as `action`.
                // See: https://github.com/dotnet/aspnetcore/issues/14789
                var formattedRouteKeys = string.Join(", ", resolvedRouteValues.Keys.Select(k => $"'{k}'"));
                throw new InvalidOperationException(
                          $"Failed to update the route pattern '{resolvedRoutePattern.RawText}' with required route values. " +
                          $"This can occur when the route pattern contains parameters with reserved names such as: {formattedRouteKeys} " +
                          $"and also uses route constraints such as '{{action:int}}'. " +
                          "To fix this error, choose a different parameter name.");
            }

            var builder = new RouteEndpointBuilder(requestDelegate, updatedRoutePattern, action.AttributeRouteInfo.Order)
            {
                DisplayName = action.DisplayName,
            };
            AddActionDataToBuilder(
                builder,
                routeNames,
                action,
                action.AttributeRouteInfo.Name,
                dataTokens: null,
                action.AttributeRouteInfo.SuppressLinkGeneration,
                action.AttributeRouteInfo.SuppressPathMatching,
                conventions,
                perRouteConventions: Array.Empty <Action <EndpointBuilder> >());
            endpoints.Add(builder.Build());
        }
    }
Exemplo n.º 30
0
    public void AddConventionalLinkGenerationRoute(
        List <Endpoint> endpoints,
        HashSet <string> routeNames,
        HashSet <string> keys,
        ConventionalRouteEntry route,
        IReadOnlyList <Action <EndpointBuilder> > conventions)
    {
        if (endpoints == null)
        {
            throw new ArgumentNullException(nameof(endpoints));
        }

        if (keys == null)
        {
            throw new ArgumentNullException(nameof(keys));
        }

        if (conventions == null)
        {
            throw new ArgumentNullException(nameof(conventions));
        }

        var requiredValues = new RouteValueDictionary();

        foreach (var key in keys)
        {
            if (route.Pattern.GetParameter(key) != null)
            {
                // Parameter (allow any)
                requiredValues[key] = RoutePattern.RequiredValueAny;
            }
            else if (route.Pattern.Defaults.TryGetValue(key, out var value))
            {
                requiredValues[key] = value;
            }
            else
            {
                requiredValues[key] = null;
            }
        }

        // We have to do some massaging of the pattern to try and get the
        // required values to be correct.
        var pattern = _routePatternTransformer.SubstituteRequiredValues(route.Pattern, requiredValues);

        if (pattern == null)
        {
            // We don't expect this to happen, but we want to know if it does because it will help diagnose the bug.
            throw new InvalidOperationException("Failed to create a conventional route for pattern: " + route.Pattern);
        }

        var builder = new RouteEndpointBuilder(context => Task.CompletedTask, pattern, route.Order)
        {
            DisplayName = "Route: " + route.Pattern.RawText,
            Metadata    =
            {
                new SuppressMatchingMetadata(),
            },
        };

        if (route.RouteName != null)
        {
            builder.Metadata.Add(new RouteNameMetadata(route.RouteName));
        }

        // See comments on the other usage of EndpointNameMetadata in this class.
        //
        // The set of cases for a conventional route are much simpler. We don't need to check
        // for Endpoint Name already exising here because there's no way to add an attribute to
        // a conventional route.
        if (route.RouteName != null && routeNames.Add(route.RouteName))
        {
            builder.Metadata.Add(new EndpointNameMetadata(route.RouteName));
        }

        for (var i = 0; i < conventions.Count; i++)
        {
            conventions[i](builder);
        }

        for (var i = 0; i < route.Conventions.Count; i++)
        {
            route.Conventions[i](builder);
        }

        endpoints.Add((RouteEndpoint)builder.Build());
    }