diff --git a/WireMock.Net Solution.sln b/WireMock.Net Solution.sln
index 60f552d1a..4c4c83599 100644
--- a/WireMock.Net Solution.sln
+++ b/WireMock.Net Solution.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
-VisualStudioVersion = 15.0.27004.2002
+VisualStudioVersion = 15.0.27004.2005
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{EF242EDF-7133-4277-9A0C-18744DE08707}"
EndProject
@@ -14,6 +14,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{F0C22C47-DF71-463C-9B04-B4E0F3B8708A}"
+ ProjectSection(SolutionItems) = preProject
+ examples\WireMock.Net.Console.Record.NETCoreApp\__admin\mappings\ab38efae-4e4d-4f20-8afe-635533ec2535.json = examples\WireMock.Net.Console.Record.NETCoreApp\__admin\mappings\ab38efae-4e4d-4f20-8afe-635533ec2535.json
+ EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{890A1DED-C229-4FA1-969E-AAC3BBFC05E5}"
EndProject
diff --git a/examples/WireMock.Net.Console.Record.NETCoreApp/WireMock.Net.Console.Record.NETCoreApp.csproj b/examples/WireMock.Net.Console.Record.NETCoreApp/WireMock.Net.Console.Record.NETCoreApp.csproj
index 61a866e77..7e9abd17e 100644
--- a/examples/WireMock.Net.Console.Record.NETCoreApp/WireMock.Net.Console.Record.NETCoreApp.csproj
+++ b/examples/WireMock.Net.Console.Record.NETCoreApp/WireMock.Net.Console.Record.NETCoreApp.csproj
@@ -15,4 +15,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/examples/WireMock.Net.Console.Record.NETCoreApp/__admin/mappings/791a3f31-6946-4ce7-8e6f-0237c7443275.json b/examples/WireMock.Net.Console.Record.NETCoreApp/__admin/mappings/791a3f31-6946-4ce7-8e6f-0237c7443275.json
deleted file mode 100644
index f360d25de..000000000
--- a/examples/WireMock.Net.Console.Record.NETCoreApp/__admin/mappings/791a3f31-6946-4ce7-8e6f-0237c7443275.json
+++ /dev/null
@@ -1,36 +0,0 @@
-{
- "Guid": "791a3f31-6946-4ce7-8e6f-0237c7443275",
- "Title": "",
- "Priority": 0,
- "Request": {
- "Path": {
- "Matchers": [
- {
- "Name": "WildcardMatcher",
- "Pattern": "/proxy-google-test-post"
- }
- ]
- },
- "Methods": [
- "post"
- ],
- "Body": {}
- },
- "Response": {
- "StatusCode": 404,
- "Body": "\n\n \n \n
Error 404 (Not Found)!!1\n \n \n 404. That’s an error.\n
The requested URL /proxy-google-test-post
was not found on this server. That’s all we know.\n",
- "BodyAsBytes": "PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ZW4+CiAgPG1ldGEgY2hhcnNldD11dGYtOD4KICA8bWV0YSBuYW1lPXZpZXdwb3J0IGNvbnRlbnQ9ImluaXRpYWwtc2NhbGU9MSwgbWluaW11bS1zY2FsZT0xLCB3aWR0aD1kZXZpY2Utd2lkdGgiPgogIDx0aXRsZT5FcnJvciA0MDQgKE5vdCBGb3VuZCkhITE8L3RpdGxlPgogIDxzdHlsZT4KICAgICp7bWFyZ2luOjA7cGFkZGluZzowfWh0bWwsY29kZXtmb250OjE1cHgvMjJweCBhcmlhbCxzYW5zLXNlcmlmfWh0bWx7YmFja2dyb3VuZDojZmZmO2NvbG9yOiMyMjI7cGFkZGluZzoxNXB4fWJvZHl7bWFyZ2luOjclIGF1dG8gMDttYXgtd2lkdGg6MzkwcHg7bWluLWhlaWdodDoxODBweDtwYWRkaW5nOjMwcHggMCAxNXB4fSogPiBib2R5e2JhY2tncm91bmQ6dXJsKC8vd3d3Lmdvb2dsZS5jb20vaW1hZ2VzL2Vycm9ycy9yb2JvdC5wbmcpIDEwMCUgNXB4IG5vLXJlcGVhdDtwYWRkaW5nLXJpZ2h0OjIwNXB4fXB7bWFyZ2luOjExcHggMCAyMnB4O292ZXJmbG93OmhpZGRlbn1pbnN7Y29sb3I6Izc3Nzt0ZXh0LWRlY29yYXRpb246bm9uZX1hIGltZ3tib3JkZXI6MH1AbWVkaWEgc2NyZWVuIGFuZCAobWF4LXdpZHRoOjc3MnB4KXtib2R5e2JhY2tncm91bmQ6bm9uZTttYXJnaW4tdG9wOjA7bWF4LXdpZHRoOm5vbmU7cGFkZGluZy1yaWdodDowfX0jbG9nb3tiYWNrZ3JvdW5kOnVybCgvL3d3dy5nb29nbGUuY29tL2ltYWdlcy9icmFuZGluZy9nb29nbGVsb2dvLzF4L2dvb2dsZWxvZ29fY29sb3JfMTUweDU0ZHAucG5nKSBuby1yZXBlYXQ7bWFyZ2luLWxlZnQ6LTVweH1AbWVkaWEgb25seSBzY3JlZW4gYW5kIChtaW4tcmVzb2x1dGlvbjoxOTJkcGkpeyNsb2dve2JhY2tncm91bmQ6dXJsKC8vd3d3Lmdvb2dsZS5jb20vaW1hZ2VzL2JyYW5kaW5nL2dvb2dsZWxvZ28vMngvZ29vZ2xlbG9nb19jb2xvcl8xNTB4NTRkcC5wbmcpIG5vLXJlcGVhdCAwJSAwJS8xMDAlIDEwMCU7LW1vei1ib3JkZXItaW1hZ2U6dXJsKC8vd3d3Lmdvb2dsZS5jb20vaW1hZ2VzL2JyYW5kaW5nL2dvb2dsZWxvZ28vMngvZ29vZ2xlbG9nb19jb2xvcl8xNTB4NTRkcC5wbmcpIDB9fUBtZWRpYSBvbmx5IHNjcmVlbiBhbmQgKC13ZWJraXQtbWluLWRldmljZS1waXhlbC1yYXRpbzoyKXsjbG9nb3tiYWNrZ3JvdW5kOnVybCgvL3d3dy5nb29nbGUuY29tL2ltYWdlcy9icmFuZGluZy9nb29nbGVsb2dvLzJ4L2dvb2dsZWxvZ29fY29sb3JfMTUweDU0ZHAucG5nKSBuby1yZXBlYXQ7LXdlYmtpdC1iYWNrZ3JvdW5kLXNpemU6MTAwJSAxMDAlfX0jbG9nb3tkaXNwbGF5OmlubGluZS1ibG9jaztoZWlnaHQ6NTRweDt3aWR0aDoxNTBweH0KICA8L3N0eWxlPgogIDxhIGhyZWY9Ly93d3cuZ29vZ2xlLmNvbS8+PHNwYW4gaWQ9bG9nbyBhcmlhLWxhYmVsPUdvb2dsZT48L3NwYW4+PC9hPgogIDxwPjxiPjQwNC48L2I+IDxpbnM+VGhhdOKAmXMgYW4gZXJyb3IuPC9pbnM+CiAgPHA+VGhlIHJlcXVlc3RlZCBVUkwgPGNvZGU+L3Byb3h5LWdvb2dsZS10ZXN0LXBvc3Q8L2NvZGU+IHdhcyBub3QgZm91bmQgb24gdGhpcyBzZXJ2ZXIuICA8aW5zPlRoYXTigJlzIGFsbCB3ZSBrbm93LjwvaW5zPgo=",
- "BodyEncoding": {
- "CodePage": 65001,
- "EncodingName": "Unicode (UTF-8)",
- "WebName": "utf-8"
- },
- "UseTransformer": false,
- "Headers": {
- "Date": "Wed, 25 Oct 2017 18:57:40 GMT",
- "Alt-Svc": "quic=\":443\"; ma=2592000; v=\"39,38,37,35\"",
- "Referrer-Policy": "no-referrer",
- "Connection": "close"
- }
- }
-}
\ No newline at end of file
diff --git a/examples/WireMock.Net.Console.Record.NETCoreApp/__admin/mappings/ab38efae-4e4d-4f20-8afe-635533ec2535.json b/examples/WireMock.Net.Console.Record.NETCoreApp/__admin/mappings/ab38efae-4e4d-4f20-8afe-635533ec2535.json
deleted file mode 100644
index 8f3d57112..000000000
--- a/examples/WireMock.Net.Console.Record.NETCoreApp/__admin/mappings/ab38efae-4e4d-4f20-8afe-635533ec2535.json
+++ /dev/null
@@ -1,41 +0,0 @@
-{
- "Guid": "ab38efae-4e4d-4f20-8afe-635533ec2535",
- "Title": "",
- "Priority": 0,
- "Request": {
- "Path": {
- "Matchers": [
- {
- "Name": "WildcardMatcher",
- "Pattern": "/earth/story/20170510-terrifying-20m-tall-rogue-waves-are-actually-real"
- }
- ]
- },
- "Methods": [
- "get"
- ]
- },
- "Response": {
- "StatusCode": 200,
- "Body": "
BBC - Homepage \n\n\n\n\n\n\n \n\n\n\n\n \n \n\n\n\n \n\n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n\n \n \n \n\n \n \n \n \n \n \n \n\n \r\n\r\n\r\n \n \n \n \n\n\n\n\n
BBC Homepage
\n\n
\n \n
\r\n
\r\n
\n Featured video\n
\n - \n \n \n\n \n
- \n \n \n\n \n
- \n \n \n\n \n
- \n \n \n\n \n
- \n \n \n\n \n
- \n \n \n\n \n
- \n \n \n\n \n
- \n \n \n\n \n
\r\n
\n More from around the BBC\n
\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n \n\n \n ",
- "BodyEncoding": {
- "CodePage": 65001,
- "EncodingName": "Unicode (UTF-8)",
- "WebName": "utf-8"
- },
- "UseTransformer": false,
- "Headers": {
- "X-LB-NoCache": "true",
- "X-Cache-Age": "0",
- "ETag": "\"07931511980b88249a64e043d5f5341d\"",
- "Connection": "keep-alive",
- "Cache-Control": "max-age=60, private",
- "X-PAL-Host": "pal128.back.live.telhc.local:80",
- "Date": "Fri, 12 May 2017 20:20:25 GMT",
- "Server": "Apache",
- "Vary": "X-CDN",
- "Set-Cookie": "BBC-UID=c58921a6d13960c8991318b121db82a089b7948f332826838beba493b8b8c4880PostmanRuntime/3.0.11-hotfix.2; expires=Tue, 11-May-21 20:20:25 GMT; path=/; domain=.bbc.com",
- "X-Cache-Action": "MISS"
- }
- }
-}
\ No newline at end of file
diff --git a/src/WireMock.Net/Http/HttpClientHelper.cs b/src/WireMock.Net/Http/HttpClientHelper.cs
index 9a9794d42..224410cb0 100644
--- a/src/WireMock.Net/Http/HttpClientHelper.cs
+++ b/src/WireMock.Net/Http/HttpClientHelper.cs
@@ -2,17 +2,24 @@
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
+using WireMock.Validation;
namespace WireMock.Http
{
internal static class HttpClientHelper
{
- private static HttpClient CreateHttpClient(string clientX509Certificate2ThumbprintOrSubjectName = null)
+ public static HttpClient CreateHttpClient(string clientX509Certificate2ThumbprintOrSubjectName = null)
{
- if (!string.IsNullOrEmpty(clientX509Certificate2ThumbprintOrSubjectName))
+ HttpClientHandler handler;
+
+ if (string.IsNullOrEmpty(clientX509Certificate2ThumbprintOrSubjectName))
+ {
+ handler = new HttpClientHandler();
+ }
+ else
{
#if NETSTANDARD || NET46
- var handler = new HttpClientHandler
+ handler = new HttpClientHandler
{
ClientCertificateOptions = ClientCertificateOption.Manual,
SslProtocols = System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls11 | System.Security.Authentication.SslProtocols.Tls,
@@ -22,7 +29,8 @@ private static HttpClient CreateHttpClient(string clientX509Certificate2Thumbpri
var x509Certificate2 = CertificateUtil.GetCertificate(clientX509Certificate2ThumbprintOrSubjectName);
handler.ClientCertificates.Add(x509Certificate2);
#else
- var handler = new WebRequestHandler
+
+ var webRequestHandler = new WebRequestHandler
{
ClientCertificateOptions = ClientCertificateOption.Manual,
ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true,
@@ -30,38 +38,51 @@ private static HttpClient CreateHttpClient(string clientX509Certificate2Thumbpri
};
var x509Certificate2 = CertificateUtil.GetCertificate(clientX509Certificate2ThumbprintOrSubjectName);
- handler.ClientCertificates.Add(x509Certificate2);
- return new HttpClient(handler);
+ webRequestHandler.ClientCertificates.Add(x509Certificate2);
+ handler = webRequestHandler;
#endif
}
- return new HttpClient();
+ // For proxy we shouldn't follow auto redirects
+ handler.AllowAutoRedirect = false;
+
+ // If UseCookies enabled, httpClient ignores Cookie header
+ handler.UseCookies = false;
+
+ return new HttpClient(handler);
}
- public static async Task SendAsync(RequestMessage requestMessage, string url, string clientX509Certificate2ThumbprintOrSubjectName = null)
+ public static async Task SendAsync(HttpClient client, RequestMessage requestMessage, string url)
{
- var client = CreateHttpClient(clientX509Certificate2ThumbprintOrSubjectName);
+ Check.NotNull(client, nameof(client));
+
+ var originalUri = new Uri(requestMessage.Url);
+ var requiredUri = new Uri(url);
var httpRequestMessage = new HttpRequestMessage(new HttpMethod(requestMessage.Method), url);
+ // Set Body if present
+ if (requestMessage.BodyAsBytes != null && requestMessage.BodyAsBytes.Length > 0)
+ {
+ httpRequestMessage.Content = new ByteArrayContent(requestMessage.BodyAsBytes);
+ }
+
// Overwrite the host header
- httpRequestMessage.Headers.Host = new Uri(url).Authority;
+ httpRequestMessage.Headers.Host = requiredUri.Authority;
// Set headers if present
if (requestMessage.Headers != null)
{
- foreach (var headerName in requestMessage.Headers.Keys.Where(k => k.ToUpper() != "HOST"))
+ foreach (var header in requestMessage.Headers.Where(header => !string.Equals(header.Key, "HOST", StringComparison.OrdinalIgnoreCase)))
{
- httpRequestMessage.Headers.TryAddWithoutValidation(headerName, requestMessage.Headers[headerName]);
+ // Try to add to request headers. If failed - try to add to content headers
+ if (!httpRequestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value))
+ {
+ httpRequestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value);
+ }
}
}
- // Set Body if present
- if (requestMessage.BodyAsBytes != null && requestMessage.BodyAsBytes.Length > 0)
- {
- httpRequestMessage.Content = new ByteArrayContent(requestMessage.BodyAsBytes);
- }
-
// Call the URL
var httpResponseMessage = await client.SendAsync(httpRequestMessage, HttpCompletionOption.ResponseContentRead);
@@ -74,9 +95,24 @@ public static async Task SendAsync(RequestMessage requestMessag
Body = await httpResponseMessage.Content.ReadAsStringAsync()
};
- foreach (var header in httpResponseMessage.Headers)
+ // Set both content and response headers, replacing URLs in values
+ var headers = httpResponseMessage.Content?.Headers.Union(httpResponseMessage.Headers);
+
+ foreach (var header in headers)
{
- responseMessage.AddHeader(header.Key, header.Value.FirstOrDefault());
+ // if Location header contains absolute redirect URL, and base URL is one that we proxy to,
+ // we need to replace it to original one.
+ if (string.Equals(header.Key, "Location", StringComparison.OrdinalIgnoreCase)
+ && Uri.TryCreate(header.Value.First(), UriKind.Absolute, out Uri absoluteLocationUri)
+ && string.Equals(absoluteLocationUri.Host, requiredUri.Host, StringComparison.OrdinalIgnoreCase))
+ {
+ var replacedLocationUri = new Uri(originalUri, absoluteLocationUri.PathAndQuery);
+ responseMessage.AddHeader(header.Key, replacedLocationUri.ToString());
+ }
+ else
+ {
+ responseMessage.AddHeader(header.Key, header.Value.ToArray());
+ }
}
return responseMessage;
diff --git a/src/WireMock.Net/ResponseBuilders/Response.cs b/src/WireMock.Net/ResponseBuilders/Response.cs
index 53f7152d4..34db3f53e 100644
--- a/src/WireMock.Net/ResponseBuilders/Response.cs
+++ b/src/WireMock.Net/ResponseBuilders/Response.cs
@@ -3,6 +3,7 @@
using System.IO;
using System.Linq;
using System.Net;
+using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using JetBrains.Annotations;
@@ -19,6 +20,8 @@ namespace WireMock.ResponseBuilders
///
public class Response : IResponseBuilder
{
+ private HttpClient httpClientForProxy;
+
///
/// The delay
///
@@ -317,6 +320,7 @@ public IResponseBuilder WithProxy(string proxyUrl, string clientX509Certificate2
ProxyUrl = proxyUrl;
X509Certificate2ThumbprintOrSubjectName = clientX509Certificate2ThumbprintOrSubjectName;
+ httpClientForProxy = HttpClientHelper.CreateHttpClient(clientX509Certificate2ThumbprintOrSubjectName);
return this;
}
@@ -332,12 +336,12 @@ public async Task ProvideResponseAsync(RequestMessage requestMe
if (Delay != null)
await Task.Delay(Delay.Value);
- if (ProxyUrl != null)
+ if (ProxyUrl != null && httpClientForProxy != null)
{
var requestUri = new Uri(requestMessage.Url);
var proxyUri = new Uri(ProxyUrl);
var proxyUriWithRequestPathAndQuery = new Uri(proxyUri, requestUri.PathAndQuery);
- return await HttpClientHelper.SendAsync(requestMessage, proxyUriWithRequestPathAndQuery.AbsoluteUri, X509Certificate2ThumbprintOrSubjectName);
+ return await HttpClientHelper.SendAsync(httpClientForProxy, requestMessage, proxyUriWithRequestPathAndQuery.AbsoluteUri);
}
if (UseTransformer)
diff --git a/src/WireMock.Net/Server/FluentMockServer.Admin.cs b/src/WireMock.Net/Server/FluentMockServer.Admin.cs
index 5081c4e8c..a4bf2ad28 100644
--- a/src/WireMock.Net/Server/FluentMockServer.Admin.cs
+++ b/src/WireMock.Net/Server/FluentMockServer.Admin.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using JetBrains.Annotations;
@@ -129,8 +130,11 @@ private void InitAdmin()
}
#region Proxy and Record
+ private HttpClient httpClientForProxy;
+
private void InitProxyAndRecord(ProxyAndRecordSettings settings)
{
+ httpClientForProxy = HttpClientHelper.CreateHttpClient(settings.X509Certificate2ThumbprintOrSubjectName);
Given(Request.Create().WithPath("/*").UsingAnyVerb()).RespondWith(new ProxyAsyncResponseProvider(ProxyAndRecordAsync, settings));
}
@@ -140,7 +144,7 @@ private async Task ProxyAndRecordAsync(RequestMessage requestMe
var proxyUri = new Uri(settings.Url);
var proxyUriWithRequestPathAndQuery = new Uri(proxyUri, requestUri.PathAndQuery);
- var responseMessage = await HttpClientHelper.SendAsync(requestMessage, proxyUriWithRequestPathAndQuery.AbsoluteUri, settings.X509Certificate2ThumbprintOrSubjectName);
+ var responseMessage = await HttpClientHelper.SendAsync(httpClientForProxy, requestMessage, proxyUriWithRequestPathAndQuery.AbsoluteUri);
if (settings.SaveMapping)
{
diff --git a/test/WireMock.Net.Tests/FluentMockServerTests.Proxy.cs b/test/WireMock.Net.Tests/FluentMockServerTests.Proxy.cs
new file mode 100644
index 000000000..ab63b69db
--- /dev/null
+++ b/test/WireMock.Net.Tests/FluentMockServerTests.Proxy.cs
@@ -0,0 +1,157 @@
+using System;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Threading.Tasks;
+using NFluent;
+using WireMock.RequestBuilders;
+using WireMock.ResponseBuilders;
+using WireMock.Server;
+using Xunit;
+
+namespace WireMock.Net.Tests
+{
+ public partial class FluentMockServerTests
+ {
+ private FluentMockServer _serverForProxyForwarding;
+
+ [Fact]
+ public async Task FluentMockServer_Should_proxy_responses()
+ {
+ // given
+ _server = FluentMockServer.Start();
+ _server
+ .Given(Request.Create().WithPath("/*"))
+ .RespondWith(Response.Create().WithProxy("http://www.google.com"));
+
+ // when
+ var result = await new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + "/search?q=test");
+
+ // then
+ Check.That(result).Contains("google");
+ }
+
+ [Fact]
+ public async Task FluentMockServer_Should_preserve_content_header_in_proxied_request()
+ {
+ // given
+ _serverForProxyForwarding = FluentMockServer.Start();
+ _serverForProxyForwarding
+ .Given(Request.Create().WithPath("/*"))
+ .RespondWith(Response.Create());
+
+ _server = FluentMockServer.Start();
+ _server
+ .Given(Request.Create().WithPath("/*"))
+ .RespondWith(Response.Create().WithProxy(_serverForProxyForwarding.Urls[0]));
+
+ // when
+ var requestMessage = new HttpRequestMessage
+ {
+ Method = HttpMethod.Post,
+ RequestUri = new Uri(_server.Urls[0]),
+ Content = new StringContent("stringContent")
+ };
+ requestMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
+ await new HttpClient().SendAsync(requestMessage);
+
+ // then
+ var receivedRequest = _serverForProxyForwarding.LogEntries.First().RequestMessage;
+ Check.That(receivedRequest.Body).IsEqualTo("stringContent");
+ Check.That(receivedRequest.Headers).ContainsKey("Content-Type");
+ Check.That(receivedRequest.Headers["Content-Type"]).ContainsExactly("text/plain");
+ }
+
+ [Fact]
+ public async Task FluentMockServer_Should_preserve_content_header_in_proxied_response()
+ {
+ // given
+ _serverForProxyForwarding = FluentMockServer.Start();
+ _serverForProxyForwarding
+ .Given(Request.Create().WithPath("/*"))
+ .RespondWith(Response.Create()
+ .WithBody("body")
+ .WithHeader("Content-Type", "text/plain"));
+
+ _server = FluentMockServer.Start();
+ _server
+ .Given(Request.Create().WithPath("/*"))
+ .RespondWith(Response.Create().WithProxy(_serverForProxyForwarding.Urls[0]));
+
+ // when
+ var requestMessage = new HttpRequestMessage
+ {
+ Method = HttpMethod.Get,
+ RequestUri = new Uri(_server.Urls[0])
+ };
+ var response = await new HttpClient().SendAsync(requestMessage);
+
+ // then
+ Check.That(await response.Content.ReadAsStringAsync()).IsEqualTo("body");
+ Check.That(response.Content.Headers.Contains("Content-Type")).IsTrue();
+ Check.That(response.Content.Headers.GetValues("Content-Type")).ContainsExactly("text/plain");
+ }
+
+ [Fact]
+ public async Task FluentMockServer_Should_change_absolute_location_header_in_proxied_response()
+ {
+ // given
+ _serverForProxyForwarding = FluentMockServer.Start();
+ _serverForProxyForwarding
+ .Given(Request.Create().WithPath("/*"))
+ .RespondWith(Response.Create()
+ .WithStatusCode(HttpStatusCode.Redirect)
+ .WithHeader("Location", _serverForProxyForwarding.Urls[0] + "testpath"));
+
+ _server = FluentMockServer.Start();
+ _server
+ .Given(Request.Create().WithPath("/*"))
+ .RespondWith(Response.Create().WithProxy(_serverForProxyForwarding.Urls[0]));
+
+ // when
+ var requestMessage = new HttpRequestMessage
+ {
+ Method = HttpMethod.Get,
+ RequestUri = new Uri(_server.Urls[0])
+ };
+ var httpClientHandler = new HttpClientHandler { AllowAutoRedirect = false };
+ var response = await new HttpClient(httpClientHandler).SendAsync(requestMessage);
+
+ // then
+ Check.That(response.Headers.Contains("Location")).IsTrue();
+ Check.That(response.Headers.GetValues("Location")).ContainsExactly(_server.Urls[0] + "testpath");
+ }
+
+ [Fact]
+ public async Task FluentMockServer_Should_preserve_cookie_header_in_proxied_request()
+ {
+ // given
+ _serverForProxyForwarding = FluentMockServer.Start();
+ _serverForProxyForwarding
+ .Given(Request.Create().WithPath("/*"))
+ .RespondWith(Response.Create());
+
+ _server = FluentMockServer.Start();
+ _server
+ .Given(Request.Create().WithPath("/*"))
+ .RespondWith(Response.Create().WithProxy(_serverForProxyForwarding.Urls[0]));
+
+ // when
+ var requestUri = new Uri(_server.Urls[0]);
+ var requestMessage = new HttpRequestMessage
+ {
+ Method = HttpMethod.Get,
+ RequestUri = requestUri
+ };
+ var clientHandler = new HttpClientHandler();
+ clientHandler.CookieContainer.Add(requestUri, new Cookie("name", "value"));
+ await new HttpClient(clientHandler).SendAsync(requestMessage);
+
+ // then
+ var receivedRequest = _serverForProxyForwarding.LogEntries.First().RequestMessage;
+ Check.That(receivedRequest.Cookies).IsNotNull();
+ Check.That(receivedRequest.Cookies).ContainsPair("name", "value");
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/WireMock.Net.Tests/FluentMockServerTests.cs b/test/WireMock.Net.Tests/FluentMockServerTests.cs
index cb8b31ae5..343256d0e 100644
--- a/test/WireMock.Net.Tests/FluentMockServerTests.cs
+++ b/test/WireMock.Net.Tests/FluentMockServerTests.cs
@@ -6,17 +6,15 @@
using System.Net.Http;
using System.Threading.Tasks;
using NFluent;
-using Xunit;
using WireMock.Matchers;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
using WireMock.Server;
+using Xunit;
namespace WireMock.Net.Tests
{
- //[TestFixture]
- //[Timeout(5000)]
- public class FluentMockServerTests : IDisposable
+ public partial class FluentMockServerTests : IDisposable
{
private FluentMockServer _server;
@@ -178,7 +176,7 @@ public async Task FluentMockServer_Admin_Requests_Get()
}
[Fact]
- public async Task Should_respond_to_request_bodyAsString()
+ public async Task FluentMockServer_Should_respond_to_request_bodyAsString()
{
// given
_server = FluentMockServer.Start();
@@ -199,7 +197,7 @@ public async Task Should_respond_to_request_bodyAsString()
}
[Fact]
- public async Task Should_respond_to_request_bodyAsBase64()
+ public async Task FluentMockServer_Should_respond_to_request_bodyAsBase64()
{
// given
_server = FluentMockServer.Start();
@@ -214,7 +212,7 @@ public async Task Should_respond_to_request_bodyAsBase64()
}
[Fact]
- public async Task Should_respond_to_request_bodyAsBytes()
+ public async Task FluentMockServer_Should_respond_to_request_bodyAsBytes()
{
// given
_server = FluentMockServer.Start();
@@ -231,7 +229,7 @@ public async Task Should_respond_to_request_bodyAsBytes()
}
[Fact]
- public async Task Should_respond_404_for_unexpected_request()
+ public async Task FluentMockServer_Should_respond_404_for_unexpected_request()
{
// given
_server = FluentMockServer.Start();
@@ -245,7 +243,7 @@ public async Task Should_respond_404_for_unexpected_request()
}
[Fact]
- public async Task Should_find_a_request_satisfying_a_request_spec()
+ public async Task FluentMockServer_Should_find_a_request_satisfying_a_request_spec()
{
// given
_server = FluentMockServer.Start();
@@ -264,7 +262,7 @@ public async Task Should_find_a_request_satisfying_a_request_spec()
}
[Fact]
- public async Task Should_reset_requestlogs()
+ public async Task FluentMockServer_Should_reset_requestlogs()
{
// given
_server = FluentMockServer.Start();
@@ -278,7 +276,7 @@ public async Task Should_reset_requestlogs()
}
[Fact]
- public void Should_reset_mappings()
+ public void FluentMockServer_Should_reset_mappings()
{
// given
_server = FluentMockServer.Start();
@@ -300,7 +298,7 @@ public void Should_reset_mappings()
}
[Fact]
- public async Task Should_respond_a_redirect_without_body()
+ public async Task FluentMockServer_Should_respond_a_redirect_without_body()
{
// given
_server = FluentMockServer.Start();
@@ -328,7 +326,7 @@ public async Task Should_respond_a_redirect_without_body()
}
[Fact]
- public async Task Should_delay_responses_for_a_given_route()
+ public async Task FluentMockServer_Should_delay_responses_for_a_given_route()
{
// given
_server = FluentMockServer.Start();
@@ -351,7 +349,7 @@ public async Task Should_delay_responses_for_a_given_route()
}
[Fact]
- public async Task Should_delay_responses()
+ public async Task FluentMockServer_Should_delay_responses()
{
// given
_server = FluentMockServer.Start();
@@ -370,22 +368,6 @@ public async Task Should_delay_responses()
Check.That(watch.ElapsedMilliseconds).IsStrictlyGreaterThan(200);
}
- [Fact]
- public async Task Should_proxy_responses()
- {
- // given
- _server = FluentMockServer.Start();
- _server
- .Given(Request.Create().WithPath("/*"))
- .RespondWith(Response.Create().WithProxy("http://www.google.com"));
-
- // when
- var result = await new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + "/search?q=test");
-
- // then
- Check.That(result).Contains("google");
- }
-
//Leaving commented as this requires an actual certificate with password, along with a service that expects a client certificate
//[Fact]
//public async Task Should_proxy_responses_with_client_certificate()
@@ -429,6 +411,7 @@ public async Task FluentMockServer_Logging_SetMaxRequestLogCount()
public void Dispose()
{
_server?.Stop();
+ _serverForProxyForwarding?.Stop();
}
}
}
\ No newline at end of file