예제 #1
0
        /// <summary>
        /// Generates an OData link using the given OData route name, path handler, and segments.
        /// </summary>
        /// <param name="request">The Http request.</param>
        /// <param name="segments">The OData path segments.</param>
        /// <returns>The generated OData link.</returns>
        public static string CreateODataLink(this HttpRequest request, IList <ODataPathSegment> segments)
        {
            if (request == null)
            {
                throw Error.ArgumentNull(nameof(request));
            }

            IODataFeature oDataFeature = request.ODataFeature();
            string        odataPath    = segments.GetPathString();

            // retrieve the cached base address
            string baseAddress = oDataFeature.BaseAddress;

            if (baseAddress != null)
            {
                return(CombinePath(baseAddress, odataPath));
            }

            // if no, calculate the base address
            string uriString = UriHelper.BuildAbsolute(request.Scheme, request.Host, request.PathBase);
            string prefix    = oDataFeature.RoutePrefix;

            if (string.IsNullOrEmpty(prefix))
            {
                baseAddress = uriString;
            }
            else
            {
                // Construct the prefix template if it's a template
                RoutePattern routePattern = RoutePatternFactory.Parse(prefix);
                if (!routePattern.Parameters.Any())
                {
                    baseAddress = CombinePath(uriString, prefix);
                }
                else
                {
                    if (TryProcessPrefixTemplate(request, routePattern, out var path))
                    {
                        baseAddress = CombinePath(uriString, path);
                    }
                    else
                    {
                        throw new ODataException(Error.Format(SRResources.CannotProcessPrefixTemplate, prefix));
                    }
                }
            }

            // cache the base address
            oDataFeature.BaseAddress = baseAddress;
            return(CombinePath(baseAddress, odataPath));
        }
        private static (RoutePattern resolvedRoutePattern, IDictionary <string, string> resolvedRequiredValues) ResolveDefaultsAndRequiredValues(ActionDescriptor action, RoutePattern attributeRoutePattern)
        {
            RouteValueDictionary         updatedDefaults        = null;
            IDictionary <string, string> resolvedRequiredValues = null;

            foreach (var routeValue in action.RouteValues)
            {
                var parameter = attributeRoutePattern.GetParameter(routeValue.Key);

                if (!RouteValueEqualityComparer.Default.Equals(routeValue.Value, string.Empty))
                {
                    if (parameter == null)
                    {
                        // The attribute route has a required value with no matching parameter
                        // Add the required values without a parameter as a default
                        // e.g.
                        //   Template: "Login/{action}"
                        //   Required values: { controller = "Login", action = "Index" }
                        //   Updated defaults: { controller = "Login" }

                        if (updatedDefaults == null)
                        {
                            updatedDefaults = new RouteValueDictionary(attributeRoutePattern.Defaults);
                        }

                        updatedDefaults[routeValue.Key] = routeValue.Value;
                    }
                }
                else
                {
                    if (parameter != null)
                    {
                        // The attribute route has a null or empty required value with a matching parameter
                        // Remove the required value from the route

                        if (resolvedRequiredValues == null)
                        {
                            resolvedRequiredValues = new Dictionary <string, string>(action.RouteValues);
                        }

                        resolvedRequiredValues.Remove(parameter.Name);
                    }
                }
            }
            if (updatedDefaults != null)
            {
                attributeRoutePattern = RoutePatternFactory.Parse(action.AttributeRouteInfo.Template, updatedDefaults, parameterPolicies: null);
            }

            return(attributeRoutePattern, resolvedRequiredValues ?? action.RouteValues);
        }
예제 #3
0
 internal static MatcherEndpoint CreateEndpoint(
     string template,
     object defaults    = null,
     object constraints = null,
     int?order          = null)
 {
     return(new MatcherEndpoint(
                MatcherEndpoint.EmptyInvoker,
                RoutePatternFactory.Parse(template, defaults, constraints),
                new RouteValueDictionary(),
                order ?? 0,
                EndpointMetadataCollection.Empty,
                "endpoint: " + template));
 }
예제 #4
0
        private static IEndpointConventionBuilder CreateUnimplementedEndpoint(IEndpointRouteBuilder endpointRouteBuilder, string pattern, string displayName, RequestDelegate requestDelegate)
        {
            var routePattern    = RoutePatternFactory.Parse(pattern, defaults: null, new { contentType = GrpcUnimplementedConstraint.Instance });
            var endpointBuilder = endpointRouteBuilder.Map(routePattern, requestDelegate);

            endpointBuilder.Add(ep =>
            {
                ep.DisplayName = $"gRPC - {displayName}";
                // Don't add POST metadata here. It will return 405 status for other HTTP methods which isn't
                // what we want. That check is made in a constraint instead.
            });

            return(endpointBuilder);
        }
예제 #5
0
        public CustomEndpointDataSource(EndpointDataSource source)
        {
            Source = source;
            var endpoints = Source.Endpoints.Cast <RouteEndpoint>();

            Endpoints = endpoints
                        .Where(r =>
            {
                var attr = r.Metadata.OfType <CustomHttpMethodAttribute>().FirstOrDefault();
                return(attr == null || !attr.DisableFormat);
            })
                        .Select(r => new RouteEndpoint(r.RequestDelegate, RoutePatternFactory.Parse(r.RoutePattern.RawText + ".{format}"), r.Order, r.Metadata, r.DisplayName))
                        .ToList();
        }
예제 #6
0
        public static void Main()
        {
            var template = @"weather/{city:regex(^0\d{{2,3}}$)=010}/{days:int:range(1,4)=4}/{detailed?}";
            var pattern  = RoutePatternFactory.Parse(
                pattern: template,
                defaults: null,
                parameterPolicies: null,
                requiredValues: new { city = "010", days = 4 });

            Host.CreateDefaultBuilder()
            .ConfigureWebHostDefaults(builder => builder.Configure(app => app.Run(context => context.Response.WriteAsync(Format(pattern)))))
            .Build()
            .Run();
        }
예제 #7
0
        public PathRouteValuesTransform(string pattern, TemplateBinderFactory binderFactory)
        {
            if (pattern is null)
            {
                throw new System.ArgumentNullException(nameof(pattern));
            }

            if (binderFactory is null)
            {
                throw new System.ArgumentNullException(nameof(binderFactory));
            }

            _binder = binderFactory.Create(RoutePatternFactory.Parse(pattern));
        }
        private static StaticFilesEndpointConventionBuilder MapStaticFilesCore(IEndpointRouteBuilder endpoints, PathString requestPath, StaticFileEndpointOptions options)
        {
            StaticFileOptions staticFileOptions;

            if (options == null)
            {
                var original = endpoints.ServiceProvider.GetRequiredService <IOptions <StaticFileOptions> >();
                staticFileOptions = new StaticFileOptions()
                {
                    ContentTypeProvider   = original.Value.ContentTypeProvider,
                    DefaultContentType    = original.Value.DefaultContentType,
                    FileProvider          = original.Value.FileProvider,
                    HttpsCompression      = original.Value.HttpsCompression,
                    OnPrepareResponse     = original.Value.OnPrepareResponse,
                    ServeUnknownFileTypes = original.Value.ServeUnknownFileTypes,
                };
            }
            else
            {
                staticFileOptions = new StaticFileOptions()
                {
                    ContentTypeProvider   = options.ContentTypeProvider,
                    DefaultContentType    = options.DefaultContentType,
                    FileProvider          = options.FileProvider,
                    HttpsCompression      = options.HttpsCompression,
                    OnPrepareResponse     = options.OnPrepareResponse,
                    ServeUnknownFileTypes = options.ServeUnknownFileTypes,
                };
            }

            staticFileOptions.ContentTypeProvider ??= new FileExtensionContentTypeProvider();
            staticFileOptions.FileProvider ??= endpoints.ServiceProvider.GetRequiredService <IWebHostEnvironment>().WebRootFileProvider;

            staticFileOptions.RequestPath = requestPath;

            var pattern = RoutePatternFactory.Parse(requestPath + "/{**path}", defaults: null, parameterPolicies: new { path = new FileExistsConstraint(options.FileProvider), });

            var app = endpoints.CreateApplicationBuilder();

            // Temporary hack
            app.Use(next => httpContext =>
            {
                httpContext.SetEndpoint(null);
                return(next(httpContext));
            });

            app.UseStaticFiles(staticFileOptions);

            return(new StaticFilesEndpointConventionBuilder(endpoints.Map(pattern, app.Build())));
        }
예제 #9
0
        public void MapEndpoint_GeneratedDelegateWorks()
        {
            // Arrange
            var builder = new DefaultEndpointRouteBuilder(Mock.Of<IApplicationBuilder>());

            Expression<RequestDelegate> handler = context => Task.CompletedTask;

            // Act
            var endpointBuilder = builder.Map(RoutePatternFactory.Parse("/"), handler.Compile());

            // Assert
            var endpointBuilder1 = GetRouteEndpointBuilder(builder);
            Assert.Equal("/", endpointBuilder1.RoutePattern.RawText);
        }
예제 #10
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);
        }
        private static MatcherEndpoint CreateEndpoint(ActionDescriptor action)
        {
            var metadata = new List <object>()
            {
                action,
            };

            return(new MatcherEndpoint(
                       (r) => null,
                       RoutePatternFactory.Parse("/"),
                       0,
                       new EndpointMetadataCollection(metadata),
                       $"test: {action?.DisplayName}"));
        }
 /// <summary>
 /// Map a route and allow two <see cref="DbContext"/> instances.
 /// </summary>
 /// <typeparam name="T1Context">The type of the first <see cref="DbContext"/>.</typeparam>
 /// <typeparam name="T2Context">The type of the second <see cref="DbContext"/>.</typeparam>
 /// <param name="endpointRouteBuilder">The <see cref="IEndpointRouteBuilder"/>.</param>
 /// <param name="pattern">The root path. The context and controller will be appended.</param>
 /// <param name="rules">The <see cref="IRulesConfiguration"/> to configure serialization rules.</param>
 /// <param name="noDefaultRules">Determines whether the default rule set should be applied.</param>
 /// <param name="options">The <see cref="IConfigurationBuilder"/> to configure options.</param>
 /// <returns>The <see cref="IEndpointConventionBuilder"/>.</returns>
 public static IEndpointConventionBuilder MapPowerToolsEFCore <T1Context, T2Context>(
     this IEndpointRouteBuilder endpointRouteBuilder,
     string pattern = DefaultPattern,
     Action <IRulesConfiguration> rules = null,
     bool noDefaultRules = false,
     Action <IConfigurationBuilder> options = null)
     where T1Context : DbContext
     where T2Context : DbContext => MapPowerToolsEFCore(
     endpointRouteBuilder,
     RoutePatternFactory.Parse(pattern),
     new Type[] { typeof(T1Context), typeof(T2Context) },
     rules,
     noDefaultRules,
     options);
예제 #13
0
 private Endpoint CreateRejectionEndpoint()
 {
     return(new MatcherEndpoint(
                (next) => (context) =>
     {
         context.Response.StatusCode = StatusCodes.Status415UnsupportedMediaType;
         return Task.CompletedTask;
     },
                RoutePatternFactory.Parse("/"),
                new RouteValueDictionary(),
                0,
                EndpointMetadataCollection.Empty,
                Http415EndpointDisplayName));
 }
예제 #14
0
    private OutboundMatch CreateMatch(object requiredValues, string routeTemplate = null)
    {
        var match = new OutboundMatch();

        match.Entry = new OutboundRouteEntry();
        match.Entry.RequiredLinkValues = new RouteValueDictionary(requiredValues);

        if (!string.IsNullOrEmpty(routeTemplate))
        {
            match.Entry.RouteTemplate = new RouteTemplate(RoutePatternFactory.Parse(routeTemplate));
        }

        return(match);
    }
예제 #15
0
        private static RouteEndpoint CreateEndpoint(ActionDescriptor action)
        {
            var metadata = new List <object>()
            {
                action,
            };

            return(new RouteEndpoint(
                       (context) => Task.CompletedTask,
                       RoutePatternFactory.Parse("/"),
                       0,
                       new EndpointMetadataCollection(metadata),
                       $"test: {action?.DisplayName}"));
        }
        public RoutePattern GetPattern(string pattern)
        {
            if (pattern == null)
            {
                throw new ArgumentNullException(nameof(pattern));
            }

            var routeValues = new RouteValueDictionary();

            routeValues.TryAdd("action", _action);
            routeValues.TryAdd("controller", _controller);
            routeValues.TryAdd("area", _area);
            return(RoutePatternFactory.Parse(pattern, routeValues, null));
        }
예제 #17
0
 private RouteEndpoint CreateEndpoint(
     string template,
     object defaults       = null,
     object requiredValues = null,
     int order             = 0,
     object[] metadata     = null)
 {
     return(new RouteEndpoint(
                (httpContext) => Task.CompletedTask,
                RoutePatternFactory.Parse(template, defaults, parameterPolicies: null, requiredValues),
                order,
                new EndpointMetadataCollection(metadata ?? Array.Empty <object>()),
                null));
 }
        public void ConfigureServices(IServiceCollection services)
        {
            var endpointDataSource = new DefaultEndpointDataSource(new[]
            {
                new RouteEndpoint((httpContext) =>
                {
                    var response           = httpContext.Response;
                    var payloadLength      = _homePayload.Length;
                    response.StatusCode    = 200;
                    response.ContentType   = "text/plain";
                    response.ContentLength = payloadLength;
                    return(response.Body.WriteAsync(_homePayload, 0, payloadLength));
                },
                                  RoutePatternFactory.Parse("/"),
                                  0,
                                  EndpointMetadataCollection.Empty,
                                  "Home"),
                new RouteEndpoint((httpContext) =>
                {
                    var response           = httpContext.Response;
                    var payloadLength      = _helloWorldPayload.Length;
                    response.StatusCode    = 200;
                    response.ContentType   = "text/plain";
                    response.ContentLength = payloadLength;
                    return(response.Body.WriteAsync(_helloWorldPayload, 0, payloadLength));
                },
                                  RoutePatternFactory.Parse("/plaintext"),
                                  0,
                                  EndpointMetadataCollection.Empty,
                                  "Plaintext"),
                new RouteEndpoint((httpContext) =>
                {
                    using (var writer = new StreamWriter(httpContext.Response.Body, Encoding.UTF8, 1024, leaveOpen: true))
                    {
                        var graphWriter = httpContext.RequestServices.GetRequiredService <DfaGraphWriter>();
                        var dataSource  = httpContext.RequestServices.GetRequiredService <CompositeEndpointDataSource>();
                        graphWriter.Write(dataSource, writer);
                    }

                    return(Task.CompletedTask);
                },
                                  RoutePatternFactory.Parse("/graph"),
                                  0,
                                  new EndpointMetadataCollection(new HttpMethodMetadata(new[] { "GET", })),
                                  "DFA Graph"),
            });

            services.TryAddEnumerable(ServiceDescriptor.Singleton <EndpointDataSource>(endpointDataSource));
        }
예제 #19
0
 private MatcherEndpoint CreateEndpoint(
     string template,
     object defaults       = null,
     object requiredValues = null,
     int order             = 0,
     string routeName      = null)
 {
     return(new MatcherEndpoint(
                MatcherEndpoint.EmptyInvoker,
                RoutePatternFactory.Parse(template, defaults, constraints: null),
                new RouteValueDictionary(requiredValues),
                order,
                EndpointMetadataCollection.Empty,
                null));
 }
예제 #20
0
        public void MapEndpoint_AttributesCollectedAsMetadata()
        {
            // Arrange
            var builder = new DefaultEndpointRouteBuilder(Mock.Of<IApplicationBuilder>());

            // Act
            var endpointBuilder = builder.Map(RoutePatternFactory.Parse("/"), Handle);

            // Assert
            var endpointBuilder1 = GetRouteEndpointBuilder(builder);
            Assert.Equal("/", endpointBuilder1.RoutePattern.RawText);
            Assert.Equal(2, endpointBuilder1.Metadata.Count);
            Assert.IsType<Attribute1>(endpointBuilder1.Metadata[0]);
            Assert.IsType<Attribute2>(endpointBuilder1.Metadata[1]);
        }
예제 #21
0
        public void MapEndpoint_TypedPattern_BuildsEndpoint()
        {
            // Arrange
            var             builder         = new DefaultEndpointDataSourceBuilder();
            RequestDelegate requestDelegate = (d) => null;

            // Act
            var endpointBuilder = builder.MapEndpoint(requestDelegate, RoutePatternFactory.Parse("/"), "Display name!");

            // Assert
            Assert.Equal(endpointBuilder, Assert.Single(builder.Endpoints));
            Assert.Equal(requestDelegate, endpointBuilder.RequestDelegate);
            Assert.Equal("Display name!", endpointBuilder.DisplayName);
            Assert.Equal("/", endpointBuilder.RoutePattern.RawText);
        }
예제 #22
0
        protected void CreateOutboundRouteEntry(TreeRouteBuilder treeRouteBuilder, RouteEndpoint endpoint)
        {
            var routeValuesAddressMetadata = endpoint.Metadata.GetMetadata <IRouteValuesAddressMetadata>();
            var requiredValues             = routeValuesAddressMetadata?.RequiredValues ?? new RouteValueDictionary();

            treeRouteBuilder.MapOutbound(
                NullRouter.Instance,
                new RouteTemplate(RoutePatternFactory.Parse(
                                      endpoint.RoutePattern.RawText,
                                      defaults: endpoint.RoutePattern.Defaults,
                                      parameterPolicies: null)),
                requiredLinkValues: new RouteValueDictionary(requiredValues),
                routeName: null,
                order: 0);
        }
예제 #23
0
        public IEnumerable <Endpoint> FindEndpoints(RouteValuesAddress address)
        {
            if (address.AmbientValues == null || address.ExplicitValues == null)
            {
                return(Enumerable.Empty <Endpoint>());
            }

            string sitemapId = address.ExplicitValues[_options.SitemapIdKey]?.ToString();

            if (string.IsNullOrEmpty(sitemapId) || !_entries.TryGetPathBySitemapId(sitemapId, out var path))
            {
                return(Enumerable.Empty <Endpoint>());
            }

            if (Match(address.ExplicitValues))
            {
                var routeValues = new RouteValueDictionary(address.ExplicitValues);

                if (address.ExplicitValues.Count > _options.GlobalRouteValues.Count + 1)
                {
                    foreach (var entry in address.ExplicitValues)
                    {
                        if (String.Equals(entry.Key, _options.SitemapIdKey, StringComparison.OrdinalIgnoreCase))
                        {
                            continue;
                        }

                        if (!_options.GlobalRouteValues.ContainsKey(entry.Key))
                        {
                            routeValues.Remove(entry.Key);
                        }
                    }
                }

                var endpoint = new RouteEndpoint
                               (
                    c => null,
                    RoutePatternFactory.Parse(path, routeValues, null),
                    0,
                    null,
                    null
                               );

                return(new[] { endpoint });
            }

            return(Enumerable.Empty <Endpoint>());
        }
예제 #24
0
        public void MapEndpoint_TypedPattern_BuildsEndpoint()
        {
            // Arrange
            var             builder         = new DefaultEndpointRouteBuilder(Mock.Of <IApplicationBuilder>());
            RequestDelegate requestDelegate = (d) => null;

            // Act
            var endpointBuilder = builder.Map(RoutePatternFactory.Parse("/"), requestDelegate);

            // Assert
            var endpointBuilder1 = GetRouteEndpointBuilder(builder);

            Assert.Equal(requestDelegate, endpointBuilder1.RequestDelegate);
            Assert.Equal("/", endpointBuilder1.DisplayName);
            Assert.Equal("/", endpointBuilder1.RoutePattern.RawText);
        }
예제 #25
0
        private static RouteEndpoint CreateEndpoint(string template, HttpMethodMetadata httpMethodMetadata)
        {
            var metadata = new List <object>();

            if (httpMethodMetadata != null)
            {
                metadata.Add(httpMethodMetadata);
            }

            return(new RouteEndpoint(
                       TestConstants.EmptyRequestDelegate,
                       RoutePatternFactory.Parse(template),
                       0,
                       new EndpointMetadataCollection(metadata),
                       $"test: {template}"));
        }
예제 #26
0
        private static RouteEndpoint CreateEndpoint(string template, DomainAttribute domainAttribute)
        {
            var metadata = new List <object>();

            if (domainAttribute != null)
            {
                metadata.Add(domainAttribute);
            }

            return(new RouteEndpoint(
                       (context) => Task.CompletedTask,
                       RoutePatternFactory.Parse(template),
                       0,
                       new EndpointMetadataCollection(metadata),
                       $"test: {template} - {string.Join(", ", domainAttribute?.Hosts ?? Array.Empty<string>())}"));
        }
예제 #27
0
        private static MatcherEndpoint CreateEndpoint(string template, ConsumesMetadata consumesMetadata)
        {
            var metadata = new List <object>();

            if (consumesMetadata != null)
            {
                metadata.Add(consumesMetadata);
            }

            return(new MatcherEndpoint(
                       (next) => null,
                       RoutePatternFactory.Parse(template),
                       0,
                       new EndpointMetadataCollection(metadata),
                       $"test: {template} - {string.Join(", ", consumesMetadata?.ContentTypes ?? Array.Empty<string>())}"));
        }
예제 #28
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app)
        {
            app.UseGlobalRouting();
            app.UseEndpoint(builder => {
                builder.AddProxyEndpoint(
                    RoutePatternFactory.Parse("/"),
                    new RouteValueDictionary(),
                    0,
                    EndpointMetadataCollection.Empty,
                    "ProxyEndpoint via Builder",
                    new Uri("http://example.com"));/*AddAuthPolicy("A sled gang")*/
                // TODO make AddProxyEndpoint return a builder to add policies onto
            });

            app.UseEndpointWhen
        }
        // .UseMvc routing setup
        public static void UseRoutes(IList <IRouter> routes)
        {
            ROUTES = new List <RoutePattern>();
            foreach (var buildRoute in routes)
            {
                if (buildRoute is Route route)
                {
                    var routePattern = RoutePatternFactory.Parse(route.RouteTemplate);

                    if (routePattern != null)
                    {
                        ROUTES.Add(routePattern);
                    }
                }
            }
        }
        private static ActionSelectionTable <RouteEndpoint> CreateTableWithEndpoints(IReadOnlyList <ActionDescriptor> actions)
        {
            var endpoints = actions.Select(a =>
            {
                var metadata = new List <object>(a.EndpointMetadata ?? Array.Empty <object>());
                metadata.Add(a);
                return(new RouteEndpoint(
                           requestDelegate: context => Task.CompletedTask,
                           routePattern: RoutePatternFactory.Parse("/", defaults: a.RouteValues, parameterPolicies: null, requiredValues: a.RouteValues),
                           order: 0,
                           metadata: new EndpointMetadataCollection(metadata),
                           a.DisplayName));
            });

            return(ActionSelectionTable <ActionDescriptor> .Create(endpoints));
        }