-
Notifications
You must be signed in to change notification settings - Fork 855
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for adding metadata to proxy routes
- Loading branch information
Showing
17 changed files
with
845 additions
and
589 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
121 changes: 121 additions & 0 deletions
121
src/ReverseProxy/Service/DynamicEndpoint/ProxyEndpointFactory.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Authorization; | ||
using Microsoft.AspNetCore.Builder; | ||
using Microsoft.AspNetCore.Cors; | ||
using Microsoft.AspNetCore.Cors.Infrastructure; | ||
using Microsoft.AspNetCore.Http; | ||
using Microsoft.AspNetCore.Routing; | ||
using Microsoft.ReverseProxy.Abstractions.RouteDiscovery.Contract; | ||
using Microsoft.ReverseProxy.RuntimeModel; | ||
using Microsoft.ReverseProxy.Service.Routing; | ||
using CorsConstants = Microsoft.ReverseProxy.Abstractions.RouteDiscovery.Contract.CorsConstants; | ||
|
||
namespace Microsoft.ReverseProxy | ||
{ | ||
internal class ProxyEndpointFactory | ||
{ | ||
private static readonly IAuthorizeData _defaultAuthorization = new AuthorizeAttribute(); | ||
private static readonly IEnableCorsAttribute _defaultCors = new EnableCorsAttribute(); | ||
private static readonly IDisableCorsAttribute _disableCors = new DisableCorsAttribute(); | ||
|
||
private RequestDelegate _pipeline; | ||
|
||
public void AddEndpoint(List<Endpoint> endpoints, | ||
RouteConfig route, | ||
IReadOnlyList<Action<EndpointBuilder>> conventions) | ||
{ | ||
var proxyRoute = route.ProxyRoute; | ||
var proxyMatch = proxyRoute.Match; | ||
|
||
// Catch-all pattern when no path was specified | ||
var pathPattern = string.IsNullOrEmpty(proxyMatch.Path) ? "/{**catchall}" : proxyMatch.Path; | ||
|
||
var endpointBuilder = new AspNetCore.Routing.RouteEndpointBuilder( | ||
requestDelegate: _pipeline ?? Invoke, | ||
routePattern: AspNetCore.Routing.Patterns.RoutePatternFactory.Parse(pathPattern), | ||
order: proxyRoute.Order.GetValueOrDefault()) | ||
{ | ||
DisplayName = proxyRoute.RouteId | ||
}; | ||
|
||
endpointBuilder.Metadata.Add(route); | ||
|
||
if (proxyMatch.Hosts != null && proxyMatch.Hosts.Count != 0) | ||
{ | ||
endpointBuilder.Metadata.Add(new HostAttribute(proxyMatch.Hosts.ToArray())); | ||
} | ||
|
||
if (proxyRoute.Match.Headers != null && proxyRoute.Match.Headers.Count > 0) | ||
{ | ||
var matchers = new List<HeaderMatcher>(proxyRoute.Match.Headers.Count); | ||
foreach (var header in proxyRoute.Match.Headers) | ||
{ | ||
matchers.Add(new HeaderMatcher(header.Name, header.Values, header.Mode, header.IsCaseSensitive)); | ||
} | ||
|
||
endpointBuilder.Metadata.Add(new HeaderMetadata(matchers)); | ||
} | ||
|
||
bool acceptCorsPreflight; | ||
if (string.Equals(CorsConstants.Default, proxyRoute.CorsPolicy, StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
endpointBuilder.Metadata.Add(_defaultCors); | ||
acceptCorsPreflight = true; | ||
} | ||
else if (string.Equals(CorsConstants.Disable, proxyRoute.CorsPolicy, StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
endpointBuilder.Metadata.Add(_disableCors); | ||
acceptCorsPreflight = true; | ||
} | ||
else if (!string.IsNullOrEmpty(proxyRoute.CorsPolicy)) | ||
{ | ||
endpointBuilder.Metadata.Add(new EnableCorsAttribute(proxyRoute.CorsPolicy)); | ||
acceptCorsPreflight = true; | ||
} | ||
else | ||
{ | ||
acceptCorsPreflight = false; | ||
} | ||
|
||
if (proxyMatch.Methods != null && proxyMatch.Methods.Count > 0) | ||
{ | ||
endpointBuilder.Metadata.Add(new HttpMethodMetadata(proxyMatch.Methods, acceptCorsPreflight)); | ||
} | ||
|
||
if (string.Equals(AuthorizationConstants.Default, proxyRoute.AuthorizationPolicy, StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
endpointBuilder.Metadata.Add(_defaultAuthorization); | ||
} | ||
else if (!string.IsNullOrEmpty(proxyRoute.AuthorizationPolicy)) | ||
{ | ||
endpointBuilder.Metadata.Add(new AuthorizeAttribute(proxyRoute.AuthorizationPolicy)); | ||
} | ||
|
||
for (var i = 0; i < conventions.Count; i++) | ||
{ | ||
conventions[i](endpointBuilder); | ||
} | ||
|
||
endpoints.Add(endpointBuilder.Build()); | ||
} | ||
|
||
// This indirection is needed because on startup the routes are loaded from config and built before the | ||
// proxy pipeline gets built. | ||
private Task Invoke(HttpContext context) | ||
{ | ||
var pipeline = _pipeline ?? throw new InvalidOperationException("The pipeline hasn't been provided yet."); | ||
return pipeline(context); | ||
} | ||
|
||
public void SetProxyPipeline(RequestDelegate pipeline) | ||
{ | ||
_pipeline = pipeline ?? throw new ArgumentNullException(nameof(pipeline)); | ||
} | ||
} | ||
} |
Oops, something went wrong.