Feature/#623 (#632)

* #630 only set status code if response hasnt started, otherwise exception

* #623 made {RemoteIpAddress} available as placeholder so you can do x-forwarded-for

* #623 local address different on mac, windows and linux for integration test
This commit is contained in:
Tom Pallister
2018-09-24 08:22:44 +01:00
committed by GitHub
parent 54cdc74293
commit aa14b2f877
14 changed files with 487 additions and 112 deletions

View File

@ -70,6 +70,28 @@ namespace Ocelot.UnitTests.Configuration
.BDDfy();
}
[Fact]
public void should_create_with_add_headers_to_request()
{
const string key = "X-Forwarded-For";
const string value = "{RemoteIpAddress}";
var reRoute = new FileReRoute
{
UpstreamHeaderTransform = new Dictionary<string, string>
{
{key, value},
}
};
var expected = new AddHeader(key, value);
this.Given(x => GivenTheReRoute(reRoute))
.When(x => WhenICreate())
.Then(x => ThenTheFollowingAddHeaderToUpstreamIsReturned(expected))
.BDDfy();
}
[Fact]
public void should_use_base_url_placeholder()
{

View File

@ -15,6 +15,9 @@ using Ocelot.Request.Middleware;
namespace Ocelot.UnitTests.Headers
{
using Ocelot.Infrastructure;
using Ocelot.Logging;
public class AddHeadersToRequestClaimToThingTests
{
private readonly AddHeadersToRequest _addHeadersToRequest;
@ -24,11 +27,15 @@ namespace Ocelot.UnitTests.Headers
private List<ClaimToThing> _configuration;
private Response _result;
private Response<string> _claimValue;
private Mock<IPlaceholders> _placeholders;
private Mock<IOcelotLoggerFactory> _factory;
public AddHeadersToRequestClaimToThingTests()
{
_parser = new Mock<IClaimsParser>();
_addHeadersToRequest = new AddHeadersToRequest(_parser.Object);
_placeholders = new Mock<IPlaceholders>();
_factory = new Mock<IOcelotLoggerFactory>();
_addHeadersToRequest = new AddHeadersToRequest(_parser.Object, _placeholders.Object, _factory.Object);
_downstreamRequest = new DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "http://test.com"));
}

View File

@ -1,23 +1,56 @@
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
namespace Ocelot.UnitTests.Headers
{
using Ocelot.Infrastructure;
using Ocelot.Logging;
using Microsoft.AspNetCore.Http;
using Moq;
using Ocelot.Configuration.Creator;
using Ocelot.Headers;
using Ocelot.Infrastructure.Claims.Parser;
using Responder;
using Responses;
using Shouldly;
using TestStack.BDDfy;
using Xunit;
public class AddHeadersToRequestPlainTests
{
private readonly AddHeadersToRequest _addHeadersToRequest;
private HttpContext _context;
private AddHeader _addedHeader;
private readonly Mock<IPlaceholders> _placeholders;
private Mock<IOcelotLoggerFactory> _factory;
private readonly Mock<IOcelotLogger> _logger;
public AddHeadersToRequestPlainTests()
{
_addHeadersToRequest = new AddHeadersToRequest(Mock.Of<IClaimsParser>());
_placeholders = new Mock<IPlaceholders>();
_factory = new Mock<IOcelotLoggerFactory>();
_logger = new Mock<IOcelotLogger>();
_factory.Setup(x => x.CreateLogger<AddHeadersToRequest>()).Returns(_logger.Object);
_addHeadersToRequest = new AddHeadersToRequest(Mock.Of<IClaimsParser>(), _placeholders.Object, _factory.Object);
}
[Fact]
public void should_log_error_if_cannot_find_placeholder()
{
_placeholders.Setup(x => x.Get(It.IsAny<string>())).Returns(new ErrorResponse<string>(new AnyError()));
this.Given(_ => GivenHttpRequestWithoutHeaders())
.When(_ => WhenAddingHeader("X-Forwarded-For", "{RemoteIdAddress}"))
.Then(_ => ThenAnErrorIsLogged("X-Forwarded-For", "{RemoteIdAddress}"))
.BDDfy();
}
[Fact]
public void should_add_placeholder_to_downstream_request()
{
_placeholders.Setup(x => x.Get(It.IsAny<string>())).Returns(new OkResponse<string>("replaced"));
this.Given(_ => GivenHttpRequestWithoutHeaders())
.When(_ => WhenAddingHeader("X-Forwarded-For", "{RemoteIdAddress}"))
.Then(_ => ThenTheHeaderGetsTakenOverToTheRequestHeaders("replaced"))
.BDDfy();
}
[Fact]
@ -38,9 +71,23 @@ namespace Ocelot.UnitTests.Headers
.BDDfy();
}
private void ThenAnErrorIsLogged(string key, string value)
{
_logger.Verify(x => x.LogWarning($"Unable to add header to response {key}: {value}"), Times.Once);
}
private void GivenHttpRequestWithoutHeaders()
{
_context = new DefaultHttpContext();
_context = new DefaultHttpContext
{
Request =
{
Headers =
{
}
}
};
}
private void GivenHttpRequestWithHeader(string headerKey, string headerValue)
@ -71,5 +118,12 @@ namespace Ocelot.UnitTests.Headers
value.ShouldNotBeNull($"Value of header {_addedHeader.Key} was expected to not be null.");
value.ToString().ShouldBe(_addedHeader.Value);
}
private void ThenTheHeaderGetsTakenOverToTheRequestHeaders(string expected)
{
var requestHeaders = _context.Request.Headers;
var value = requestHeaders[_addedHeader.Key];
value.ToString().ShouldBe(expected);
}
}
}

View File

@ -109,7 +109,7 @@ namespace Ocelot.UnitTests.Headers
private void ThenTheIHttpResponseHeaderReplacerIsCalledCorrectly()
{
_postReplacer.Verify(x => x.Replace(It.IsAny<DownstreamResponse>(), It.IsAny<List<HeaderFindAndReplace>>(), It.IsAny<DownstreamRequest>()), Times.Once);
_postReplacer.Verify(x => x.Replace(It.IsAny<DownstreamContext>(), It.IsAny<List<HeaderFindAndReplace>>()), Times.Once);
}
private void GivenTheFollowingRequest()

View File

@ -1,22 +1,22 @@
using Xunit;
using Shouldly;
using TestStack.BDDfy;
using System.Net.Http;
using Ocelot.Headers;
using Ocelot.Configuration;
using System.Collections.Generic;
using Ocelot.Responses;
using System.Linq;
using System.Net;
using Moq;
using Ocelot.Infrastructure;
using Ocelot.Middleware;
using Ocelot.Infrastructure.RequestData;
using Ocelot.Middleware.Multiplexer;
using Ocelot.Request.Middleware;
namespace Ocelot.UnitTests.Headers
{
using Microsoft.AspNetCore.Http;
using Ocelot.Infrastructure;
using Ocelot.Middleware;
using Ocelot.Infrastructure.RequestData;
using Ocelot.Request.Middleware;
using Xunit;
using Shouldly;
using TestStack.BDDfy;
using System.Net.Http;
using Ocelot.Headers;
using Ocelot.Configuration;
using System.Collections.Generic;
using Ocelot.Responses;
using System.Linq;
using System.Net;
using Moq;
public class HttpResponseHeaderReplacerTests
{
private DownstreamResponse _response;
@ -27,12 +27,14 @@ namespace Ocelot.UnitTests.Headers
private DownstreamRequest _request;
private Mock<IBaseUrlFinder> _finder;
private Mock<IRequestScopedDataRepository> _repo;
private Mock<IHttpContextAccessor> _accessor;
public HttpResponseHeaderReplacerTests()
{
_accessor = new Mock<IHttpContextAccessor>();
_repo = new Mock<IRequestScopedDataRepository>();
_finder = new Mock<IBaseUrlFinder>();
_placeholders = new Placeholders(_finder.Object, _repo.Object);
_placeholders = new Placeholders(_finder.Object, _repo.Object, _accessor.Object);
_replacer = new HttpResponseHeaderReplacer(_placeholders);
}
@ -261,7 +263,8 @@ namespace Ocelot.UnitTests.Headers
private void WhenICallTheReplacer()
{
_result = _replacer.Replace(_response, _headerFindAndReplaces, _request);
var context = new DownstreamContext(new DefaultHttpContext()) {DownstreamResponse = _response, DownstreamRequest = _request};
_result = _replacer.Replace(context, _headerFindAndReplaces);
}
private void ThenTheHeaderShouldBe(string key, string value)

View File

@ -1,27 +1,31 @@
using System;
using System.Net.Http;
using Moq;
using Ocelot.Infrastructure;
using Ocelot.Infrastructure.RequestData;
using Ocelot.Middleware;
using Ocelot.Request.Middleware;
using Ocelot.Responses;
using Shouldly;
using Xunit;
namespace Ocelot.UnitTests.Infrastructure
{
using Microsoft.AspNetCore.Http;
using System;
using System.Net;
using System.Net.Http;
using Moq;
using Ocelot.Infrastructure;
using Ocelot.Infrastructure.RequestData;
using Ocelot.Middleware;
using Ocelot.Request.Middleware;
using Ocelot.Responses;
using Shouldly;
using Xunit;
public class PlaceholdersTests
{
private IPlaceholders _placeholders;
private Mock<IBaseUrlFinder> _finder;
private Mock<IRequestScopedDataRepository> _repo;
private readonly IPlaceholders _placeholders;
private readonly Mock<IBaseUrlFinder> _finder;
private readonly Mock<IRequestScopedDataRepository> _repo;
private readonly Mock<IHttpContextAccessor> _accessor;
public PlaceholdersTests()
{
_accessor = new Mock<IHttpContextAccessor>();
_repo = new Mock<IRequestScopedDataRepository>();
_finder = new Mock<IBaseUrlFinder>();
_placeholders = new Placeholders(_finder.Object, _repo.Object);
_placeholders = new Placeholders(_finder.Object, _repo.Object, _accessor.Object);
}
[Fact]
@ -33,6 +37,15 @@ namespace Ocelot.UnitTests.Infrastructure
result.Data.ShouldBe(baseUrl);
}
[Fact]
public void should_return_remote_ip_address()
{
var httpContext = new DefaultHttpContext(){Connection = { RemoteIpAddress = IPAddress.Any}};
_accessor.Setup(x => x.HttpContext).Returns(httpContext);
var result = _placeholders.Get("{RemoteIpAddress}");
result.Data.ShouldBe(httpContext.Connection.RemoteIpAddress.ToString());
}
[Fact]
public void should_return_key_does_not_exist()
{