mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-22 06:22:50 +08:00
Support adding custom plaintext headers to downstream requests (#314)
This commit is contained in:
parent
b46ef1945d
commit
fa09e4cf7a
@ -1,15 +1,31 @@
|
|||||||
Headers Transformation
|
Headers Transformation
|
||||||
=====================
|
======================
|
||||||
|
|
||||||
Ocelot allows the user to transform headers pre and post downstream request. At the moment Ocelot only supports find and replace. This feature was requested `GitHub #190 <https://github.com/TomPallister/Ocelot/issues/190>`_ and I decided that it was going to be useful in various ways.
|
Ocelot allows the user to transform headers pre and post downstream request. At the moment Ocelot only supports find and replace. This feature was requested `GitHub #190 <https://github.com/TomPallister/Ocelot/issues/190>`_ and I decided that it was going to be useful in various ways.
|
||||||
|
|
||||||
|
Add to Request
|
||||||
|
^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
This feature was requestes in `GitHub #313 <https://github.com/ThreeMammals/Ocelot/issues/313>`_.
|
||||||
|
|
||||||
|
If you want to add a header to your upstream request please add the following to a ReRoute in your configuration.json:
|
||||||
|
|
||||||
|
.. code-block:: json
|
||||||
|
|
||||||
|
"UpstreamHeaderTransform": {
|
||||||
|
"Uncle": "Bob"
|
||||||
|
}
|
||||||
|
|
||||||
|
In the example above a header with the key Uncle and value Bob would be send to to the upstream service.
|
||||||
|
|
||||||
|
Placeholders are supported too (see below).
|
||||||
|
|
||||||
Add to Response
|
Add to Response
|
||||||
^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
This feature was requested in `GitHub #280 <https://github.com/TomPallister/Ocelot/issues/280>`_. I have only implemented
|
This feature was requested in `GitHub #280 <https://github.com/TomPallister/Ocelot/issues/280>`_.
|
||||||
for responses but could add for requests in the future.
|
|
||||||
|
|
||||||
If you want to add a header to your downstream response please add the following to a ReRoute in configuration.json..
|
If you want to add a header to your downstream response please add the following to a ReRoute in configuration.json.
|
||||||
|
|
||||||
.. code-block:: json
|
.. code-block:: json
|
||||||
|
|
||||||
@ -50,7 +66,7 @@ Add the following to a ReRoute in configuration.json in order to replace http://
|
|||||||
},
|
},
|
||||||
|
|
||||||
Post Downstream Request
|
Post Downstream Request
|
||||||
^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Add the following to a ReRoute in configuration.json in order to replace http://www.bbc.co.uk/ with http://ocelot.com/. This transformation will take place after Ocelot has received the response from the downstream service.
|
Add the following to a ReRoute in configuration.json in order to replace http://www.bbc.co.uk/ with http://ocelot.com/. This transformation will take place after Ocelot has received the response from the downstream service.
|
||||||
|
|
||||||
|
@ -39,12 +39,14 @@ namespace Ocelot.Configuration.Builder
|
|||||||
private string _key;
|
private string _key;
|
||||||
private List<string> _delegatingHandlers;
|
private List<string> _delegatingHandlers;
|
||||||
private List<AddHeader> _addHeadersToDownstream;
|
private List<AddHeader> _addHeadersToDownstream;
|
||||||
|
private List<AddHeader> _addHeadersToUpstream;
|
||||||
|
|
||||||
public DownstreamReRouteBuilder()
|
public DownstreamReRouteBuilder()
|
||||||
{
|
{
|
||||||
_downstreamAddresses = new List<DownstreamHostAndPort>();
|
_downstreamAddresses = new List<DownstreamHostAndPort>();
|
||||||
_delegatingHandlers = new List<string>();
|
_delegatingHandlers = new List<string>();
|
||||||
_addHeadersToDownstream = new List<AddHeader>();
|
_addHeadersToDownstream = new List<AddHeader>();
|
||||||
|
_addHeadersToUpstream = new List<AddHeader>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public DownstreamReRouteBuilder WithDownstreamAddresses(List<DownstreamHostAndPort> downstreamAddresses)
|
public DownstreamReRouteBuilder WithDownstreamAddresses(List<DownstreamHostAndPort> downstreamAddresses)
|
||||||
@ -233,6 +235,12 @@ namespace Ocelot.Configuration.Builder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DownstreamReRouteBuilder WithAddHeadersToUpstream(List<AddHeader> addHeadersToUpstream)
|
||||||
|
{
|
||||||
|
_addHeadersToUpstream = addHeadersToUpstream;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public DownstreamReRoute Build()
|
public DownstreamReRoute Build()
|
||||||
{
|
{
|
||||||
return new DownstreamReRoute(
|
return new DownstreamReRoute(
|
||||||
@ -263,7 +271,8 @@ namespace Ocelot.Configuration.Builder
|
|||||||
new PathTemplate(_downstreamPathTemplate),
|
new PathTemplate(_downstreamPathTemplate),
|
||||||
_reRouteKey,
|
_reRouteKey,
|
||||||
_delegatingHandlers,
|
_delegatingHandlers,
|
||||||
_addHeadersToDownstream);
|
_addHeadersToDownstream,
|
||||||
|
_addHeadersToUpstream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -215,6 +215,7 @@ namespace Ocelot.Configuration.Creator
|
|||||||
.WithUpstreamHost(fileReRoute.UpstreamHost)
|
.WithUpstreamHost(fileReRoute.UpstreamHost)
|
||||||
.WithDelegatingHandlers(fileReRoute.DelegatingHandlers)
|
.WithDelegatingHandlers(fileReRoute.DelegatingHandlers)
|
||||||
.WithAddHeadersToDownstream(hAndRs.AddHeadersToDownstream)
|
.WithAddHeadersToDownstream(hAndRs.AddHeadersToDownstream)
|
||||||
|
.WithAddHeadersToUpstream(hAndRs.AddHeadersToUpstream)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
return reRoute;
|
return reRoute;
|
||||||
|
@ -22,8 +22,11 @@ namespace Ocelot.Configuration.Creator
|
|||||||
public HeaderTransformations Create(FileReRoute fileReRoute)
|
public HeaderTransformations Create(FileReRoute fileReRoute)
|
||||||
{
|
{
|
||||||
var upstream = new List<HeaderFindAndReplace>();
|
var upstream = new List<HeaderFindAndReplace>();
|
||||||
|
var addHeadersToUpstream = new List<AddHeader>();
|
||||||
|
|
||||||
foreach(var input in fileReRoute.UpstreamHeaderTransform)
|
foreach(var input in fileReRoute.UpstreamHeaderTransform)
|
||||||
|
{
|
||||||
|
if (input.Value.Contains(","))
|
||||||
{
|
{
|
||||||
var hAndr = Map(input);
|
var hAndr = Map(input);
|
||||||
if (!hAndr.IsError)
|
if (!hAndr.IsError)
|
||||||
@ -35,6 +38,11 @@ namespace Ocelot.Configuration.Creator
|
|||||||
_logger.LogWarning($"Unable to add UpstreamHeaderTransform {input.Key}: {input.Value}");
|
_logger.LogWarning($"Unable to add UpstreamHeaderTransform {input.Key}: {input.Value}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addHeadersToUpstream.Add(new AddHeader(input.Key, input.Value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var downstream = new List<HeaderFindAndReplace>();
|
var downstream = new List<HeaderFindAndReplace>();
|
||||||
var addHeadersToDownstream = new List<AddHeader>();
|
var addHeadersToDownstream = new List<AddHeader>();
|
||||||
@ -59,7 +67,7 @@ namespace Ocelot.Configuration.Creator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new HeaderTransformations(upstream, downstream, addHeadersToDownstream);
|
return new HeaderTransformations(upstream, downstream, addHeadersToDownstream, addHeadersToUpstream);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Response<HeaderFindAndReplace> Map(KeyValuePair<string,string> input)
|
private Response<HeaderFindAndReplace> Map(KeyValuePair<string,string> input)
|
||||||
|
@ -7,9 +7,11 @@ namespace Ocelot.Configuration.Creator
|
|||||||
public HeaderTransformations(
|
public HeaderTransformations(
|
||||||
List<HeaderFindAndReplace> upstream,
|
List<HeaderFindAndReplace> upstream,
|
||||||
List<HeaderFindAndReplace> downstream,
|
List<HeaderFindAndReplace> downstream,
|
||||||
List<AddHeader> addHeader)
|
List<AddHeader> addHeaderToDownstream,
|
||||||
|
List<AddHeader> addHeaderToUpstream)
|
||||||
{
|
{
|
||||||
AddHeadersToDownstream = addHeader;
|
AddHeadersToDownstream = addHeaderToDownstream;
|
||||||
|
AddHeadersToUpstream = addHeaderToUpstream;
|
||||||
Upstream = upstream;
|
Upstream = upstream;
|
||||||
Downstream = downstream;
|
Downstream = downstream;
|
||||||
}
|
}
|
||||||
@ -19,5 +21,6 @@ namespace Ocelot.Configuration.Creator
|
|||||||
public List<HeaderFindAndReplace> Downstream { get; }
|
public List<HeaderFindAndReplace> Downstream { get; }
|
||||||
|
|
||||||
public List<AddHeader> AddHeadersToDownstream { get; }
|
public List<AddHeader> AddHeadersToDownstream { get; }
|
||||||
|
public List<AddHeader> AddHeadersToUpstream { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,8 @@ namespace Ocelot.Configuration
|
|||||||
PathTemplate downstreamPathTemplate,
|
PathTemplate downstreamPathTemplate,
|
||||||
string reRouteKey,
|
string reRouteKey,
|
||||||
List<string> delegatingHandlers,
|
List<string> delegatingHandlers,
|
||||||
List<AddHeader> addHeadersToDownstream)
|
List<AddHeader> addHeadersToDownstream,
|
||||||
|
List<AddHeader> addHeadersToUpstream)
|
||||||
{
|
{
|
||||||
AddHeadersToDownstream = addHeadersToDownstream;
|
AddHeadersToDownstream = addHeadersToDownstream;
|
||||||
DelegatingHandlers = delegatingHandlers;
|
DelegatingHandlers = delegatingHandlers;
|
||||||
@ -64,6 +65,7 @@ namespace Ocelot.Configuration
|
|||||||
AuthenticationOptions = authenticationOptions;
|
AuthenticationOptions = authenticationOptions;
|
||||||
DownstreamPathTemplate = downstreamPathTemplate;
|
DownstreamPathTemplate = downstreamPathTemplate;
|
||||||
ReRouteKey = reRouteKey;
|
ReRouteKey = reRouteKey;
|
||||||
|
AddHeadersToUpstream = addHeadersToUpstream;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Key { get; private set; }
|
public string Key { get; private set; }
|
||||||
@ -94,5 +96,6 @@ namespace Ocelot.Configuration
|
|||||||
public string ReRouteKey { get; private set; }
|
public string ReRouteKey { get; private set; }
|
||||||
public List<string> DelegatingHandlers {get;private set;}
|
public List<string> DelegatingHandlers {get;private set;}
|
||||||
public List<AddHeader> AddHeadersToDownstream {get;private set;}
|
public List<AddHeader> AddHeadersToDownstream {get;private set;}
|
||||||
|
public List<AddHeader> AddHeadersToUpstream { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ using Ocelot.Configuration;
|
|||||||
using Ocelot.Infrastructure.Claims.Parser;
|
using Ocelot.Infrastructure.Claims.Parser;
|
||||||
using Ocelot.Responses;
|
using Ocelot.Responses;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using Ocelot.Configuration.Creator;
|
using Ocelot.Configuration.Creator;
|
||||||
using Ocelot.Request.Middleware;
|
using Ocelot.Request.Middleware;
|
||||||
|
|
||||||
@ -41,5 +42,19 @@ namespace Ocelot.Headers
|
|||||||
|
|
||||||
return new OkResponse();
|
return new OkResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetHeadersOnDownstreamRequest(IEnumerable<AddHeader> headers, HttpContext context)
|
||||||
|
{
|
||||||
|
var requestHeader = context.Request.Headers;
|
||||||
|
foreach (var header in headers)
|
||||||
|
{
|
||||||
|
if (requestHeader.ContainsKey(header.Key))
|
||||||
|
{
|
||||||
|
requestHeader.Remove(header.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
requestHeader.Add(header.Key, header.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,6 @@
|
|||||||
namespace Ocelot.Headers
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
|
namespace Ocelot.Headers
|
||||||
{
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
@ -12,5 +14,6 @@
|
|||||||
public interface IAddHeadersToRequest
|
public interface IAddHeadersToRequest
|
||||||
{
|
{
|
||||||
Response SetHeadersOnDownstreamRequest(List<ClaimToThing> claimsToThings, IEnumerable<System.Security.Claims.Claim> claims, DownstreamRequest downstreamRequest);
|
Response SetHeadersOnDownstreamRequest(List<ClaimToThing> claimsToThings, IEnumerable<System.Security.Claims.Claim> claims, DownstreamRequest downstreamRequest);
|
||||||
|
void SetHeadersOnDownstreamRequest(IEnumerable<AddHeader> headers, HttpContext context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,16 +9,19 @@ namespace Ocelot.Headers.Middleware
|
|||||||
private readonly OcelotRequestDelegate _next;
|
private readonly OcelotRequestDelegate _next;
|
||||||
private readonly IHttpContextRequestHeaderReplacer _preReplacer;
|
private readonly IHttpContextRequestHeaderReplacer _preReplacer;
|
||||||
private readonly IHttpResponseHeaderReplacer _postReplacer;
|
private readonly IHttpResponseHeaderReplacer _postReplacer;
|
||||||
private readonly IAddHeadersToResponse _addHeaders;
|
private readonly IAddHeadersToResponse _addHeadersToResponse;
|
||||||
|
private readonly IAddHeadersToRequest _addHeadersToRequest;
|
||||||
|
|
||||||
public HttpHeadersTransformationMiddleware(OcelotRequestDelegate next,
|
public HttpHeadersTransformationMiddleware(OcelotRequestDelegate next,
|
||||||
IOcelotLoggerFactory loggerFactory,
|
IOcelotLoggerFactory loggerFactory,
|
||||||
IHttpContextRequestHeaderReplacer preReplacer,
|
IHttpContextRequestHeaderReplacer preReplacer,
|
||||||
IHttpResponseHeaderReplacer postReplacer,
|
IHttpResponseHeaderReplacer postReplacer,
|
||||||
IAddHeadersToResponse addHeaders)
|
IAddHeadersToResponse addHeadersToResponse,
|
||||||
|
IAddHeadersToRequest addHeadersToRequest)
|
||||||
:base(loggerFactory.CreateLogger<HttpHeadersTransformationMiddleware>())
|
:base(loggerFactory.CreateLogger<HttpHeadersTransformationMiddleware>())
|
||||||
{
|
{
|
||||||
_addHeaders = addHeaders;
|
_addHeadersToResponse = addHeadersToResponse;
|
||||||
|
_addHeadersToRequest = addHeadersToRequest;
|
||||||
_next = next;
|
_next = next;
|
||||||
_postReplacer = postReplacer;
|
_postReplacer = postReplacer;
|
||||||
_preReplacer = preReplacer;
|
_preReplacer = preReplacer;
|
||||||
@ -31,13 +34,15 @@ namespace Ocelot.Headers.Middleware
|
|||||||
//todo - this should be on httprequestmessage not httpcontext?
|
//todo - this should be on httprequestmessage not httpcontext?
|
||||||
_preReplacer.Replace(context.HttpContext, preFAndRs);
|
_preReplacer.Replace(context.HttpContext, preFAndRs);
|
||||||
|
|
||||||
|
_addHeadersToRequest.SetHeadersOnDownstreamRequest(context.DownstreamReRoute.AddHeadersToUpstream, context.HttpContext);
|
||||||
|
|
||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
|
|
||||||
var postFAndRs = context.DownstreamReRoute.DownstreamHeadersFindAndReplace;
|
var postFAndRs = context.DownstreamReRoute.DownstreamHeadersFindAndReplace;
|
||||||
|
|
||||||
_postReplacer.Replace(context.DownstreamResponse, postFAndRs, context.DownstreamRequest);
|
_postReplacer.Replace(context.DownstreamResponse, postFAndRs, context.DownstreamRequest);
|
||||||
|
|
||||||
_addHeaders.Add(context.DownstreamReRoute.AddHeadersToDownstream, context.DownstreamResponse);
|
_addHeadersToResponse.Add(context.DownstreamReRoute.AddHeadersToDownstream, context.DownstreamResponse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -829,6 +829,7 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
result.DownstreamReRoute[0].RequestIdKey.ShouldBe(expected.DownstreamReRoute[0].RequestIdKey);
|
result.DownstreamReRoute[0].RequestIdKey.ShouldBe(expected.DownstreamReRoute[0].RequestIdKey);
|
||||||
result.DownstreamReRoute[0].DelegatingHandlers.ShouldBe(expected.DownstreamReRoute[0].DelegatingHandlers);
|
result.DownstreamReRoute[0].DelegatingHandlers.ShouldBe(expected.DownstreamReRoute[0].DelegatingHandlers);
|
||||||
result.DownstreamReRoute[0].AddHeadersToDownstream.ShouldBe(expected.DownstreamReRoute[0].AddHeadersToDownstream);
|
result.DownstreamReRoute[0].AddHeadersToDownstream.ShouldBe(expected.DownstreamReRoute[0].AddHeadersToDownstream);
|
||||||
|
result.DownstreamReRoute[0].AddHeadersToUpstream.ShouldBe(expected.DownstreamReRoute[0].AddHeadersToUpstream, "AddHeadersToUpstream should be set");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -911,7 +912,7 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
|
|
||||||
private void GivenTheHeaderFindAndReplaceCreatorReturns()
|
private void GivenTheHeaderFindAndReplaceCreatorReturns()
|
||||||
{
|
{
|
||||||
_headerFindAndReplaceCreator.Setup(x => x.Create(It.IsAny<FileReRoute>())).Returns(new HeaderTransformations(new List<HeaderFindAndReplace>(), new List<HeaderFindAndReplace>(), new List<AddHeader>()));
|
_headerFindAndReplaceCreator.Setup(x => x.Create(It.IsAny<FileReRoute>())).Returns(new HeaderTransformations(new List<HeaderFindAndReplace>(), new List<HeaderFindAndReplace>(), new List<AddHeader>(), new List<AddHeader>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenTheFollowingIsReturned(ServiceProviderConfiguration serviceProviderConfiguration)
|
private void GivenTheFollowingIsReturned(ServiceProviderConfiguration serviceProviderConfiguration)
|
||||||
|
@ -149,7 +149,6 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
.Then(x => ThenTheFollowingDownstreamIsReturned(downstream))
|
.Then(x => ThenTheFollowingDownstreamIsReturned(downstream))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_add_trace_id_header()
|
public void should_add_trace_id_header()
|
||||||
{
|
{
|
||||||
@ -166,7 +165,45 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
this.Given(x => GivenTheReRoute(reRoute))
|
this.Given(x => GivenTheReRoute(reRoute))
|
||||||
.And(x => GivenTheBaseUrlIs("http://ocelot.com/"))
|
.And(x => GivenTheBaseUrlIs("http://ocelot.com/"))
|
||||||
.When(x => WhenICreate())
|
.When(x => WhenICreate())
|
||||||
.Then(x => ThenTheFollowingAddHeaderIsReturned(expected))
|
.Then(x => ThenTheFollowingAddHeaderToDownstreamIsReturned(expected))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_add_downstream_header_as_is_when_no_replacement_is_given()
|
||||||
|
{
|
||||||
|
var reRoute = new FileReRoute
|
||||||
|
{
|
||||||
|
DownstreamHeaderTransform = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{"X-Custom-Header", "Value"},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var expected = new AddHeader("X-Custom-Header", "Value");
|
||||||
|
|
||||||
|
this.Given(x => GivenTheReRoute(reRoute))
|
||||||
|
.And(x => WhenICreate())
|
||||||
|
.Then(x => x.ThenTheFollowingAddHeaderToDownstreamIsReturned(expected))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_add_upstream_header_as_is_when_no_replacement_is_given()
|
||||||
|
{
|
||||||
|
var reRoute = new FileReRoute
|
||||||
|
{
|
||||||
|
UpstreamHeaderTransform = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{"X-Custom-Header", "Value"},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var expected = new AddHeader("X-Custom-Header", "Value");
|
||||||
|
|
||||||
|
this.Given(x => GivenTheReRoute(reRoute))
|
||||||
|
.And(x => WhenICreate())
|
||||||
|
.Then(x => x.ThenTheFollowingAddHeaderToUpstreamIsReturned(expected))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,12 +217,18 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
_placeholders.Setup(x => x.Get(It.IsAny<string>())).Returns(new ErrorResponse<string>(new AnyError()));
|
_placeholders.Setup(x => x.Get(It.IsAny<string>())).Returns(new ErrorResponse<string>(new AnyError()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheFollowingAddHeaderIsReturned(AddHeader addHeader)
|
private void ThenTheFollowingAddHeaderToDownstreamIsReturned(AddHeader addHeader)
|
||||||
{
|
{
|
||||||
_result.AddHeadersToDownstream[0].Key.ShouldBe(addHeader.Key);
|
_result.AddHeadersToDownstream[0].Key.ShouldBe(addHeader.Key);
|
||||||
_result.AddHeadersToDownstream[0].Value.ShouldBe(addHeader.Value);
|
_result.AddHeadersToDownstream[0].Value.ShouldBe(addHeader.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ThenTheFollowingAddHeaderToUpstreamIsReturned(AddHeader addHeader)
|
||||||
|
{
|
||||||
|
_result.AddHeadersToUpstream[0].Key.ShouldBe(addHeader.Key);
|
||||||
|
_result.AddHeadersToUpstream[0].Value.ShouldBe(addHeader.Value);
|
||||||
|
}
|
||||||
|
|
||||||
private void ThenTheFollowingDownstreamIsReturned(List<HeaderFindAndReplace> downstream)
|
private void ThenTheFollowingDownstreamIsReturned(List<HeaderFindAndReplace> downstream)
|
||||||
{
|
{
|
||||||
_result.Downstream.Count.ShouldBe(downstream.Count);
|
_result.Downstream.Count.ShouldBe(downstream.Count);
|
||||||
|
@ -15,7 +15,7 @@ using Ocelot.Request.Middleware;
|
|||||||
|
|
||||||
namespace Ocelot.UnitTests.Headers
|
namespace Ocelot.UnitTests.Headers
|
||||||
{
|
{
|
||||||
public class AddHeadersToRequestTests
|
public class AddHeadersToRequestClaimToThingTests
|
||||||
{
|
{
|
||||||
private readonly AddHeadersToRequest _addHeadersToRequest;
|
private readonly AddHeadersToRequest _addHeadersToRequest;
|
||||||
private readonly Mock<IClaimsParser> _parser;
|
private readonly Mock<IClaimsParser> _parser;
|
||||||
@ -25,7 +25,7 @@ namespace Ocelot.UnitTests.Headers
|
|||||||
private Response _result;
|
private Response _result;
|
||||||
private Response<string> _claimValue;
|
private Response<string> _claimValue;
|
||||||
|
|
||||||
public AddHeadersToRequestTests()
|
public AddHeadersToRequestClaimToThingTests()
|
||||||
{
|
{
|
||||||
_parser = new Mock<IClaimsParser>();
|
_parser = new Mock<IClaimsParser>();
|
||||||
_addHeadersToRequest = new AddHeadersToRequest(_parser.Object);
|
_addHeadersToRequest = new AddHeadersToRequest(_parser.Object);
|
@ -0,0 +1,75 @@
|
|||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Moq;
|
||||||
|
using Ocelot.Configuration.Creator;
|
||||||
|
using Ocelot.Headers;
|
||||||
|
using Ocelot.Infrastructure.Claims.Parser;
|
||||||
|
using Shouldly;
|
||||||
|
using TestStack.BDDfy;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Ocelot.UnitTests.Headers
|
||||||
|
{
|
||||||
|
public class AddHeadersToRequestPlainTests
|
||||||
|
{
|
||||||
|
private readonly AddHeadersToRequest _addHeadersToRequest;
|
||||||
|
private HttpContext _context;
|
||||||
|
private AddHeader _addedHeader;
|
||||||
|
|
||||||
|
public AddHeadersToRequestPlainTests()
|
||||||
|
{
|
||||||
|
_addHeadersToRequest = new AddHeadersToRequest(Mock.Of<IClaimsParser>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_add_plain_text_header_to_downstream_request()
|
||||||
|
{
|
||||||
|
this.Given(_ => GivenHttpRequestWithoutHeaders())
|
||||||
|
.When(_ => WhenAddingHeader("X-Custom-Header", "PlainValue"))
|
||||||
|
.Then(_ => ThenTheHeaderGetsTakenOverToTheRequestHeaders())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_overwrite_existing_header_with_added_header()
|
||||||
|
{
|
||||||
|
this.Given(_ => GivenHttpRequestWithHeader("X-Custom-Header", "This should get overwritten"))
|
||||||
|
.When(_ => WhenAddingHeader("X-Custom-Header", "PlainValue"))
|
||||||
|
.Then(_ => ThenTheHeaderGetsTakenOverToTheRequestHeaders())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenHttpRequestWithoutHeaders()
|
||||||
|
{
|
||||||
|
_context = new DefaultHttpContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenHttpRequestWithHeader(string headerKey, string headerValue)
|
||||||
|
{
|
||||||
|
_context = new DefaultHttpContext
|
||||||
|
{
|
||||||
|
Request =
|
||||||
|
{
|
||||||
|
Headers =
|
||||||
|
{
|
||||||
|
{ headerKey, headerValue }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WhenAddingHeader(string headerKey, string headerValue)
|
||||||
|
{
|
||||||
|
_addedHeader = new AddHeader(headerKey, headerValue);
|
||||||
|
_addHeadersToRequest.SetHeadersOnDownstreamRequest(new[] { _addedHeader }, _context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheHeaderGetsTakenOverToTheRequestHeaders()
|
||||||
|
{
|
||||||
|
var requestHeaders = _context.Request.Headers;
|
||||||
|
requestHeaders.ContainsKey(_addedHeader.Key).ShouldBeTrue($"Header {_addedHeader.Key} was expected but not there.");
|
||||||
|
var value = requestHeaders[_addedHeader.Key];
|
||||||
|
value.ShouldNotBeNull($"Value of header {_addedHeader.Key} was expected to not be null.");
|
||||||
|
value.ToString().ShouldBe(_addedHeader.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -27,7 +27,8 @@ namespace Ocelot.UnitTests.Headers
|
|||||||
private readonly HttpHeadersTransformationMiddleware _middleware;
|
private readonly HttpHeadersTransformationMiddleware _middleware;
|
||||||
private readonly DownstreamContext _downstreamContext;
|
private readonly DownstreamContext _downstreamContext;
|
||||||
private OcelotRequestDelegate _next;
|
private OcelotRequestDelegate _next;
|
||||||
private readonly Mock<IAddHeadersToResponse> _addHeaders;
|
private readonly Mock<IAddHeadersToResponse> _addHeadersToResponse;
|
||||||
|
private readonly Mock<IAddHeadersToRequest> _addHeadersToRequest;
|
||||||
|
|
||||||
public HttpHeadersTransformationMiddlewareTests()
|
public HttpHeadersTransformationMiddlewareTests()
|
||||||
{
|
{
|
||||||
@ -38,8 +39,11 @@ namespace Ocelot.UnitTests.Headers
|
|||||||
_logger = new Mock<IOcelotLogger>();
|
_logger = new Mock<IOcelotLogger>();
|
||||||
_loggerFactory.Setup(x => x.CreateLogger<AuthorisationMiddleware>()).Returns(_logger.Object);
|
_loggerFactory.Setup(x => x.CreateLogger<AuthorisationMiddleware>()).Returns(_logger.Object);
|
||||||
_next = context => Task.CompletedTask;
|
_next = context => Task.CompletedTask;
|
||||||
_addHeaders = new Mock<IAddHeadersToResponse>();
|
_addHeadersToResponse = new Mock<IAddHeadersToResponse>();
|
||||||
_middleware = new HttpHeadersTransformationMiddleware(_next, _loggerFactory.Object, _preReplacer.Object, _postReplacer.Object, _addHeaders.Object);
|
_addHeadersToRequest = new Mock<IAddHeadersToRequest>();
|
||||||
|
_middleware = new HttpHeadersTransformationMiddleware(
|
||||||
|
_next, _loggerFactory.Object, _preReplacer.Object,
|
||||||
|
_postReplacer.Object, _addHeadersToResponse.Object, _addHeadersToRequest.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -51,17 +55,24 @@ namespace Ocelot.UnitTests.Headers
|
|||||||
.And(x => GivenTheHttpResponseMessageIs())
|
.And(x => GivenTheHttpResponseMessageIs())
|
||||||
.When(x => WhenICallTheMiddleware())
|
.When(x => WhenICallTheMiddleware())
|
||||||
.Then(x => ThenTheIHttpContextRequestHeaderReplacerIsCalledCorrectly())
|
.Then(x => ThenTheIHttpContextRequestHeaderReplacerIsCalledCorrectly())
|
||||||
|
.Then(x => ThenAddHeadersToRequestIsCalledCorrectly())
|
||||||
.And(x => ThenTheIHttpResponseHeaderReplacerIsCalledCorrectly())
|
.And(x => ThenTheIHttpResponseHeaderReplacerIsCalledCorrectly())
|
||||||
.And(x => ThenAddHeadersIsCalledCorrectly())
|
.And(x => ThenAddHeadersToResponseIsCalledCorrectly())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenAddHeadersIsCalledCorrectly()
|
private void ThenAddHeadersToResponseIsCalledCorrectly()
|
||||||
{
|
{
|
||||||
_addHeaders
|
_addHeadersToResponse
|
||||||
.Verify(x => x.Add(_downstreamContext.DownstreamReRoute.AddHeadersToDownstream, _downstreamContext.DownstreamResponse), Times.Once);
|
.Verify(x => x.Add(_downstreamContext.DownstreamReRoute.AddHeadersToDownstream, _downstreamContext.DownstreamResponse), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ThenAddHeadersToRequestIsCalledCorrectly()
|
||||||
|
{
|
||||||
|
_addHeadersToRequest
|
||||||
|
.Verify(x => x.SetHeadersOnDownstreamRequest(_downstreamContext.DownstreamReRoute.AddHeadersToUpstream, _downstreamContext.HttpContext), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
private void WhenICallTheMiddleware()
|
private void WhenICallTheMiddleware()
|
||||||
{
|
{
|
||||||
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
|
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user