Skip to content

Commit

Permalink
feature written, tests passed
Browse files Browse the repository at this point in the history
  • Loading branch information
ibnuda authored and raman-m committed Feb 20, 2024
1 parent d54836d commit a45e255
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 31 deletions.
10 changes: 9 additions & 1 deletion src/Ocelot/Configuration/Builder/DownstreamRouteBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public class DownstreamRouteBuilder
private SecurityOptions _securityOptions;
private string _downstreamHttpMethod;
private Version _downstreamHttpVersion;
private HttpVersionPolicy _downstreamVersionPolicy;

public DownstreamRouteBuilder()
{
Expand Down Expand Up @@ -259,6 +260,12 @@ public DownstreamRouteBuilder WithDownstreamHttpVersion(Version downstreamHttpVe
return this;
}

public DownstreamRouteBuilder WithDownstreamPolicyBuilder(HttpVersionPolicy downstreamVersionPolicy)
{
_downstreamVersionPolicy = downstreamVersionPolicy;
return this;
}

public DownstreamRoute Build()
{
return new DownstreamRoute(
Expand Down Expand Up @@ -295,6 +302,7 @@ public DownstreamRoute Build()
_dangerousAcceptAnyServerCertificateValidator,
_securityOptions,
_downstreamHttpMethod,
_downstreamHttpVersion);
_downstreamHttpVersion,
_downstreamVersionPolicy);
}
}
14 changes: 14 additions & 0 deletions src/Ocelot/Configuration/Creator/IVersionPolicyCreator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace Ocelot.Configuration.Creator
{
public interface IVersionPolicyCreator
{
HttpVersionPolicy Create(string downstreamVersionPolicy);
}
}
8 changes: 7 additions & 1 deletion src/Ocelot/Configuration/Creator/RoutesCreator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public class RoutesCreator : IRoutesCreator
private readonly IRouteKeyCreator _routeKeyCreator;
private readonly ISecurityOptionsCreator _securityOptionsCreator;
private readonly IVersionCreator _versionCreator;
private readonly IVersionPolicyCreator _versionPolicyCreator;

public RoutesCreator(
IClaimsToThingCreator claimsToThingCreator,
Expand All @@ -37,7 +38,8 @@ public RoutesCreator(
ILoadBalancerOptionsCreator loadBalancerOptionsCreator,
IRouteKeyCreator routeKeyCreator,
ISecurityOptionsCreator securityOptionsCreator,
IVersionCreator versionCreator
IVersionCreator versionCreator,
IVersionPolicyCreator versionPolicyCreator
)
{
_routeKeyCreator = routeKeyCreator;
Expand All @@ -56,6 +58,7 @@ IVersionCreator versionCreator
_loadBalancerOptionsCreator = loadBalancerOptionsCreator;
_securityOptionsCreator = securityOptionsCreator;
_versionCreator = versionCreator;
_versionPolicyCreator = versionPolicyCreator;
}

public List<Route> Create(FileConfiguration fileConfiguration)
Expand Down Expand Up @@ -106,6 +109,8 @@ private DownstreamRoute SetUpDownstreamRoute(FileRoute fileRoute, FileGlobalConf
var securityOptions = _securityOptionsCreator.Create(fileRoute.SecurityOptions);

var downstreamHttpVersion = _versionCreator.Create(fileRoute.DownstreamHttpVersion);

var downstreamVersionPolicy = _versionPolicyCreator.Create(fileRoute.DownstreamVersionPolicy);

var route = new DownstreamRouteBuilder()
.WithKey(fileRoute.Key)
Expand Down Expand Up @@ -142,6 +147,7 @@ private DownstreamRoute SetUpDownstreamRoute(FileRoute fileRoute, FileGlobalConf
.WithDangerousAcceptAnyServerCertificateValidator(fileRoute.DangerousAcceptAnyServerCertificateValidator)
.WithSecurityOptions(securityOptions)
.WithDownstreamHttpVersion(downstreamHttpVersion)
.WithDownstreamPolicyBuilder(downstreamVersionPolicy)
.WithDownStreamHttpMethod(fileRoute.DownstreamHttpMethod)
.Build();

Expand Down
18 changes: 18 additions & 0 deletions src/Ocelot/Configuration/Creator/VersionPolicyCreator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System.Net.Http;

namespace Ocelot.Configuration.Creator
{
public class VersionPolicyCreator : IVersionPolicyCreator
{
public HttpVersionPolicy Create(string downstreamVersionPolicy)
{
return downstreamVersionPolicy switch
{
"exact" => HttpVersionPolicy.RequestVersionExact,
"upgradeable" => HttpVersionPolicy.RequestVersionOrHigher,
"downgradeable" => HttpVersionPolicy.RequestVersionOrLower,
_ => HttpVersionPolicy.RequestVersionOrLower,
};
}
}
}
5 changes: 4 additions & 1 deletion src/Ocelot/Configuration/DownstreamRoute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ public DownstreamRoute(
bool dangerousAcceptAnyServerCertificateValidator,
SecurityOptions securityOptions,
string downstreamHttpMethod,
Version downstreamHttpVersion)
Version downstreamHttpVersion,
HttpVersionPolicy downstreamVersionPolicy)
{
DangerousAcceptAnyServerCertificateValidator = dangerousAcceptAnyServerCertificateValidator;
AddHeadersToDownstream = addHeadersToDownstream;
Expand Down Expand Up @@ -75,6 +76,7 @@ public DownstreamRoute(
SecurityOptions = securityOptions;
DownstreamHttpMethod = downstreamHttpMethod;
DownstreamHttpVersion = downstreamHttpVersion;
DownstreamVersionPolicy = downstreamVersionPolicy;
}

public string Key { get; }
Expand Down Expand Up @@ -111,5 +113,6 @@ public DownstreamRoute(
public SecurityOptions SecurityOptions { get; }
public string DownstreamHttpMethod { get; }
public Version DownstreamHttpVersion { get; }
public HttpVersionPolicy DownstreamVersionPolicy { get; }
}
}
22 changes: 12 additions & 10 deletions src/Ocelot/Configuration/File/FileRoute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,18 @@ public FileRoute()
SecurityOptions = new FileSecurityOptions();
UpstreamHeaderTransform = new Dictionary<string, string>();
UpstreamHttpMethod = new List<string>();
}

}

public FileRoute(FileRoute from)
{
DeepCopy(from, this);
}

public Dictionary<string, string> AddClaimsToRequest { get; set; }
public Dictionary<string, string> AddClaimsToRequest { get; set; }
public Dictionary<string, string> AddHeadersToRequest { get; set; }
public Dictionary<string, string> AddQueriesToRequest { get; set; }
public Dictionary<string, string> AddQueriesToRequest { get; set; }
public FileAuthenticationOptions AuthenticationOptions { get; set; }
public Dictionary<string, string> ChangeDownstreamPathTemplate { get; set; }
public Dictionary<string, string> ChangeDownstreamPathTemplate { get; set; }
public bool DangerousAcceptAnyServerCertificateValidator { get; set; }
public List<string> DelegatingHandlers { get; set; }
public Dictionary<string, string> DownstreamHeaderTransform { get; set; }
Expand All @@ -42,7 +42,8 @@ public FileRoute(FileRoute from)
public string DownstreamHttpVersion { get; set; }
public string DownstreamPathTemplate { get; set; }
public string DownstreamScheme { get; set; }
public FileCacheOptions FileCacheOptions { get; set; }
public string DownstreamVersionPolicy { get; set; }
public FileCacheOptions FileCacheOptions { get; set; }
public FileHttpHandlerOptions HttpHandlerOptions { get; set; }
public string Key { get; set; }
public FileLoadBalancerOptions LoadBalancerOptions { get; set; }
Expand All @@ -51,13 +52,13 @@ public FileRoute(FileRoute from)
public FileRateLimitRule RateLimitOptions { get; set; }
public string RequestIdKey { get; set; }
public Dictionary<string, string> RouteClaimsRequirement { get; set; }
public bool RouteIsCaseSensitive { get; set; }
public bool RouteIsCaseSensitive { get; set; }
public FileSecurityOptions SecurityOptions { get; set; }
public string ServiceName { get; set; }
public string ServiceNamespace { get; set; }
public string ServiceName { get; set; }
public string ServiceNamespace { get; set; }
public int Timeout { get; set; }
public Dictionary<string, string> UpstreamHeaderTransform { get; set; }
public string UpstreamHost { get; set; }
public string UpstreamHost { get; set; }
public List<string> UpstreamHttpMethod { get; set; }
public string UpstreamPathTemplate { get; set; }

Expand Down Expand Up @@ -87,6 +88,7 @@ public static void DeepCopy(FileRoute from, FileRoute to)
to.DownstreamHttpVersion = from.DownstreamHttpVersion;
to.DownstreamPathTemplate = from.DownstreamPathTemplate;
to.DownstreamScheme = from.DownstreamScheme;
to.DownstreamVersionPolicy = from.DownstreamVersionPolicy;
to.FileCacheOptions = new(from.FileCacheOptions);
to.HttpHandlerOptions = new(from.HttpHandlerOptions);
to.Key = from.Key;
Expand Down
5 changes: 5 additions & 0 deletions src/Ocelot/Configuration/Validator/RouteFluentValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ public RouteFluentValidator(IAuthenticationSchemeProvider authenticationSchemePr
{
RuleFor(r => r.DownstreamHttpVersion).Matches("^[0-9]([.,][0-9]{1,1})?$");
});

When(route => !string.IsNullOrEmpty(route.DownstreamVersionPolicy), () =>
{
RuleFor(r => r.DownstreamVersionPolicy).Matches("^(exact|upgradeable|downgradeable)$");
});
}

private async Task<bool> IsSupportedAuthenticationProviders(FileAuthenticationOptions options, CancellationToken cancellationToken)
Expand Down
35 changes: 18 additions & 17 deletions src/Ocelot/Request/Mapper/RequestMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
using Ocelot.Configuration;

namespace Ocelot.Request.Mapper;


public class RequestMapper : IRequestMapper
{
private static readonly HashSet<string> UnsupportedHeaders = new(StringComparer.OrdinalIgnoreCase) { "host" };
private static readonly string[] ContentHeaders = { "Content-Length", "Content-Language", "Content-Location", "Content-Range", "Content-MD5", "Content-Disposition", "Content-Encoding" };


public HttpRequestMessage Map(HttpRequest request, DownstreamRoute downstreamRoute)
{
var requestMessage = new HttpRequestMessage
Expand All @@ -18,13 +18,14 @@ public HttpRequestMessage Map(HttpRequest request, DownstreamRoute downstreamRou
Method = MapMethod(request, downstreamRoute),
RequestUri = MapUri(request),
Version = downstreamRoute.DownstreamHttpVersion,
VersionPolicy = downstreamRoute.DownstreamVersionPolicy,
};


MapHeaders(request, requestMessage);


return requestMessage;
}


private static HttpContent MapContent(HttpRequest request)
{
// TODO We should check if we really need to call HttpRequest.Body.Length
Expand All @@ -33,14 +34,14 @@ private static HttpContent MapContent(HttpRequest request)
{
return null;
}


var content = new StreamHttpContent(request.HttpContext);


AddContentHeaders(request, content);


return content;
}


private static void AddContentHeaders(HttpRequest request, HttpContent content)
{
if (!string.IsNullOrEmpty(request.ContentType))
Expand All @@ -52,25 +53,25 @@ private static void AddContentHeaders(HttpRequest request, HttpContent content)
// The performance might be improved by retrieving the matching headers from the request
// instead of calling request.Headers.TryGetValue for each used content header
var matchingHeaders = ContentHeaders.Where(header => request.Headers.ContainsKey(header));


foreach (var key in matchingHeaders)
{
{
if (!request.Headers.TryGetValue(key, out var value))
{
{
continue;
}

}

content.Headers.TryAddWithoutValidation(key, value.ToArray());
}
}


private static HttpMethod MapMethod(HttpRequest request, DownstreamRoute downstreamRoute) =>
!string.IsNullOrEmpty(downstreamRoute?.DownstreamHttpMethod) ?
new HttpMethod(downstreamRoute.DownstreamHttpMethod) : new HttpMethod(request.Method);

// TODO Review this method, request.GetEncodedUrl() could throw a NullReferenceException
private static Uri MapUri(HttpRequest request) => new(request.GetEncodedUrl());


private static void MapHeaders(HttpRequest request, HttpRequestMessage requestMessage)
{
foreach (var header in request.Headers)
Expand All @@ -81,7 +82,7 @@ private static void MapHeaders(HttpRequest request, HttpRequestMessage requestMe
}
}
}


private static bool IsSupportedHeader(KeyValuePair<string, StringValues> header) =>
!UnsupportedHeaders.Contains(header.Key);
}
9 changes: 8 additions & 1 deletion test/Ocelot.UnitTests/Configuration/RoutesCreatorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class RoutesCreatorTests
private readonly Mock<IRouteKeyCreator> _rrkCreator;
private readonly Mock<ISecurityOptionsCreator> _soCreator;
private readonly Mock<IVersionCreator> _versionCreator;
private readonly Mock<IVersionPolicyCreator> _versionPolicyCreator;
private FileConfiguration _fileConfig;
private RouteOptions _rro;
private string _requestId;
Expand All @@ -41,6 +42,7 @@ public class RoutesCreatorTests
private LoadBalancerOptions _lbo;
private List<Route> _result;
private Version _expectedVersion;
private HttpVersionPolicy _expectedVersionPolicy;

public RoutesCreatorTests()
{
Expand All @@ -59,6 +61,7 @@ public RoutesCreatorTests()
_rrkCreator = new Mock<IRouteKeyCreator>();
_soCreator = new Mock<ISecurityOptionsCreator>();
_versionCreator = new Mock<IVersionCreator>();
_versionPolicyCreator = new Mock<IVersionPolicyCreator>();

_creator = new RoutesCreator(
_cthCreator.Object,
Expand All @@ -75,7 +78,8 @@ public RoutesCreatorTests()
_lboCreator.Object,
_rrkCreator.Object,
_soCreator.Object,
_versionCreator.Object
_versionCreator.Object,
_versionPolicyCreator.Object
);
}

Expand Down Expand Up @@ -153,6 +157,7 @@ private void ThenTheDependenciesAreCalledCorrectly()
private void GivenTheDependenciesAreSetUpCorrectly()
{
_expectedVersion = new Version("1.1");
_expectedVersionPolicy = HttpVersionPolicy.RequestVersionOrLower;
_rro = new RouteOptions(false, false, false, false, false);
_requestId = "testy";
_rrk = "besty";
Expand Down Expand Up @@ -181,6 +186,7 @@ private void GivenTheDependenciesAreSetUpCorrectly()
_daCreator.Setup(x => x.Create(It.IsAny<FileRoute>())).Returns(_dhp);
_lboCreator.Setup(x => x.Create(It.IsAny<FileLoadBalancerOptions>())).Returns(_lbo);
_versionCreator.Setup(x => x.Create(It.IsAny<string>())).Returns(_expectedVersion);
_versionPolicyCreator.Setup(x => x.Create(It.IsAny<string>())).Returns(_expectedVersionPolicy);
}

private void ThenTheRoutesAreCreated()
Expand Down Expand Up @@ -209,6 +215,7 @@ private void WhenICreate()
private void ThenTheRouteIsSet(FileRoute expected, int routeIndex)
{
_result[routeIndex].DownstreamRoute[0].DownstreamHttpVersion.ShouldBe(_expectedVersion);
_result[routeIndex].DownstreamRoute[0].DownstreamVersionPolicy.ShouldBe(_expectedVersionPolicy);
_result[routeIndex].DownstreamRoute[0].IsAuthenticated.ShouldBe(_rro.IsAuthenticated);
_result[routeIndex].DownstreamRoute[0].IsAuthorized.ShouldBe(_rro.IsAuthorized);
_result[routeIndex].DownstreamRoute[0].IsCached.ShouldBe(_rro.IsCached);
Expand Down
Loading

0 comments on commit a45e255

Please sign in to comment.