From f63afbf1b6dd4711514d0dbb9dd3fd6d6d9fd121 Mon Sep 17 00:00:00 2001 From: Samir Syed Date: Sun, 22 Mar 2020 22:36:23 +0530 Subject: [PATCH 1/2] Added UpstreamHost placeholder to identify host from which request origination --- src/Ocelot/Infrastructure/Placeholders.cs | 26 ++++++++++++++++++- .../Infrastructure/PlaceholdersTests.cs | 11 ++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/Ocelot/Infrastructure/Placeholders.cs b/src/Ocelot/Infrastructure/Placeholders.cs index 3c319e6d..58b4c5d4 100644 --- a/src/Ocelot/Infrastructure/Placeholders.cs +++ b/src/Ocelot/Infrastructure/Placeholders.cs @@ -7,6 +7,7 @@ namespace Ocelot.Infrastructure using Ocelot.Responses; using System; using System.Collections.Generic; + using System.Linq; public class Placeholders : IPlaceholders { @@ -25,7 +26,8 @@ namespace Ocelot.Infrastructure { { "{BaseUrl}", GetBaseUrl() }, { "{TraceId}", GetTraceId() }, - { "{RemoteIpAddress}", GetRemoteIpAddress() } + { "{RemoteIpAddress}", GetRemoteIpAddress() }, + { "{UpstreamHost}", GetUpstreamHost() }, }; _requestPlaceholders = new Dictionary> @@ -130,5 +132,27 @@ namespace Ocelot.Infrastructure { return () => new OkResponse(_finder.Find()); } + + private Func> GetUpstreamHost() + { + return () => + { + try + { + if (_httpContextAccessor.HttpContext.Request.Headers.TryGetValue("Host", out var upstreamHost)) + { + return new OkResponse(upstreamHost.First()); + } + else + { + return new ErrorResponse(new CouldNotFindPlaceholderError("{UpstreamHost}")); + } + } + catch + { + return new ErrorResponse(new CouldNotFindPlaceholderError("{UpstreamHost}")); + } + }; + } } } diff --git a/test/Ocelot.UnitTests/Infrastructure/PlaceholdersTests.cs b/test/Ocelot.UnitTests/Infrastructure/PlaceholdersTests.cs index ccd48902..d12f4ea7 100644 --- a/test/Ocelot.UnitTests/Infrastructure/PlaceholdersTests.cs +++ b/test/Ocelot.UnitTests/Infrastructure/PlaceholdersTests.cs @@ -123,5 +123,16 @@ namespace Ocelot.UnitTests.Infrastructure result.IsError.ShouldBeTrue(); result.Errors[0].Message.ShouldBe("Unable to remove placeholder: {Test}, placeholder does not exists"); } + + [Fact] + public void should_return_upstreamHost() + { + var upstreamHost = "UpstreamHostA"; + var httpContext = new DefaultHttpContext(); + httpContext.Request.Headers.Add("Host", upstreamHost); + _accessor.Setup(x => x.HttpContext).Returns(httpContext); + var result = _placeholders.Get("{UpstreamHost}"); + result.Data.ShouldBe(upstreamHost); + } } } From b7cfac9336c7e54a5a403f186d891bf5cb7003d8 Mon Sep 17 00:00:00 2001 From: TomPallister Date: Mon, 13 Apr 2020 16:48:28 +0100 Subject: [PATCH 2/2] more tests and docs --- docs/features/headerstransformation.rst | 1 + src/Ocelot/Infrastructure/Placeholders.cs | 8 +++----- .../Infrastructure/PlaceholdersTests.cs | 17 +++++++++++++++++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/docs/features/headerstransformation.rst b/docs/features/headerstransformation.rst index ed772d61..41c93f5d 100644 --- a/docs/features/headerstransformation.rst +++ b/docs/features/headerstransformation.rst @@ -85,6 +85,7 @@ Ocelot allows placeholders that can be used in header transformation. {BaseUrl} - This will use Ocelot's base url e.g. http://localhost:5000 as its value. {DownstreamBaseUrl} - This will use the downstream services base url e.g. http://localhost:5000 as its value. This only works for DownstreamHeaderTransform at the moment. {TraceId} - This will use the Butterfly APM Trace Id. This only works for DownstreamHeaderTransform at the moment. +{UpstreamHost} - This will look for the incoming Host header. Handling 302 Redirects ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/Ocelot/Infrastructure/Placeholders.cs b/src/Ocelot/Infrastructure/Placeholders.cs index 58b4c5d4..fc7dffd3 100644 --- a/src/Ocelot/Infrastructure/Placeholders.cs +++ b/src/Ocelot/Infrastructure/Placeholders.cs @@ -32,7 +32,7 @@ namespace Ocelot.Infrastructure _requestPlaceholders = new Dictionary> { - { "{DownstreamBaseUrl}", GetDownstreamBaseUrl() } + { "{DownstreamBaseUrl}", GetDownstreamBaseUrl() }, }; } @@ -143,10 +143,8 @@ namespace Ocelot.Infrastructure { return new OkResponse(upstreamHost.First()); } - else - { - return new ErrorResponse(new CouldNotFindPlaceholderError("{UpstreamHost}")); - } + + return new ErrorResponse(new CouldNotFindPlaceholderError("{UpstreamHost}")); } catch { diff --git a/test/Ocelot.UnitTests/Infrastructure/PlaceholdersTests.cs b/test/Ocelot.UnitTests/Infrastructure/PlaceholdersTests.cs index d12f4ea7..f8ee5ac6 100644 --- a/test/Ocelot.UnitTests/Infrastructure/PlaceholdersTests.cs +++ b/test/Ocelot.UnitTests/Infrastructure/PlaceholdersTests.cs @@ -134,5 +134,22 @@ namespace Ocelot.UnitTests.Infrastructure var result = _placeholders.Get("{UpstreamHost}"); result.Data.ShouldBe(upstreamHost); } + + [Fact] + public void should_return_error_when_finding_upstbecause_Host_not_set() + { + var httpContext = new DefaultHttpContext(); + _accessor.Setup(x => x.HttpContext).Returns(httpContext); + var result = _placeholders.Get("{UpstreamHost}"); + result.IsError.ShouldBeTrue(); + } + + [Fact] + public void should_return_error_when_finding_upstream_host_because_exception_thrown() + { + _accessor.Setup(x => x.HttpContext).Throws(new Exception()); + var result = _placeholders.Get("{UpstreamHost}"); + result.IsError.ShouldBeTrue(); + } } }