mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-04-17 22:50:05 +02:00
Fix proxy headers handling (#60)
* Fix proxy headers handling * Small refactor and moved proxy tests to new test-file.
This commit is contained in:
committed by
Stef Heyenrath
parent
d134684bcb
commit
c8c9ab99c5
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 15
|
# Visual Studio 15
|
||||||
VisualStudioVersion = 15.0.27004.2002
|
VisualStudioVersion = 15.0.27004.2005
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{EF242EDF-7133-4277-9A0C-18744DE08707}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{EF242EDF-7133-4277-9A0C-18744DE08707}"
|
||||||
EndProject
|
EndProject
|
||||||
@@ -14,6 +14,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{F0C22C47-DF71-463C-9B04-B4E0F3B8708A}"
|
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
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{890A1DED-C229-4FA1-969E-AAC3BBFC05E5}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{890A1DED-C229-4FA1-969E-AAC3BBFC05E5}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|||||||
@@ -15,4 +15,8 @@
|
|||||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="10.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="__admin\mappings\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -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": "<!DOCTYPE html>\n<html lang=en>\n <meta charset=utf-8>\n <meta name=viewport content=\"initial-scale=1, minimum-scale=1, width=device-width\">\n <title>Error 404 (Not Found)!!1</title>\n <style>\n *{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}\n </style>\n <a href=//www.google.com/><span id=logo aria-label=Google></span></a>\n <p><b>404.</b> <ins>That’s an error.</ins>\n <p>The requested URL <code>/proxy-google-test-post</code> was not found on this server. <ins>That’s all we know.</ins>\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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -2,17 +2,24 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using WireMock.Validation;
|
||||||
|
|
||||||
namespace WireMock.Http
|
namespace WireMock.Http
|
||||||
{
|
{
|
||||||
internal static class HttpClientHelper
|
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
|
#if NETSTANDARD || NET46
|
||||||
var handler = new HttpClientHandler
|
handler = new HttpClientHandler
|
||||||
{
|
{
|
||||||
ClientCertificateOptions = ClientCertificateOption.Manual,
|
ClientCertificateOptions = ClientCertificateOption.Manual,
|
||||||
SslProtocols = System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls11 | System.Security.Authentication.SslProtocols.Tls,
|
SslProtocols = System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls11 | System.Security.Authentication.SslProtocols.Tls,
|
||||||
@@ -22,7 +29,8 @@ namespace WireMock.Http
|
|||||||
var x509Certificate2 = CertificateUtil.GetCertificate(clientX509Certificate2ThumbprintOrSubjectName);
|
var x509Certificate2 = CertificateUtil.GetCertificate(clientX509Certificate2ThumbprintOrSubjectName);
|
||||||
handler.ClientCertificates.Add(x509Certificate2);
|
handler.ClientCertificates.Add(x509Certificate2);
|
||||||
#else
|
#else
|
||||||
var handler = new WebRequestHandler
|
|
||||||
|
var webRequestHandler = new WebRequestHandler
|
||||||
{
|
{
|
||||||
ClientCertificateOptions = ClientCertificateOption.Manual,
|
ClientCertificateOptions = ClientCertificateOption.Manual,
|
||||||
ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true,
|
ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true,
|
||||||
@@ -30,38 +38,51 @@ namespace WireMock.Http
|
|||||||
};
|
};
|
||||||
|
|
||||||
var x509Certificate2 = CertificateUtil.GetCertificate(clientX509Certificate2ThumbprintOrSubjectName);
|
var x509Certificate2 = CertificateUtil.GetCertificate(clientX509Certificate2ThumbprintOrSubjectName);
|
||||||
handler.ClientCertificates.Add(x509Certificate2);
|
webRequestHandler.ClientCertificates.Add(x509Certificate2);
|
||||||
return new HttpClient(handler);
|
handler = webRequestHandler;
|
||||||
#endif
|
#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<ResponseMessage> SendAsync(RequestMessage requestMessage, string url, string clientX509Certificate2ThumbprintOrSubjectName = null)
|
public static async Task<ResponseMessage> 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);
|
var httpRequestMessage = new HttpRequestMessage(new HttpMethod(requestMessage.Method), url);
|
||||||
|
|
||||||
// Overwrite the host header
|
|
||||||
httpRequestMessage.Headers.Host = new Uri(url).Authority;
|
|
||||||
|
|
||||||
// Set headers if present
|
|
||||||
if (requestMessage.Headers != null)
|
|
||||||
{
|
|
||||||
foreach (var headerName in requestMessage.Headers.Keys.Where(k => k.ToUpper() != "HOST"))
|
|
||||||
{
|
|
||||||
httpRequestMessage.Headers.TryAddWithoutValidation(headerName, requestMessage.Headers[headerName]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set Body if present
|
// Set Body if present
|
||||||
if (requestMessage.BodyAsBytes != null && requestMessage.BodyAsBytes.Length > 0)
|
if (requestMessage.BodyAsBytes != null && requestMessage.BodyAsBytes.Length > 0)
|
||||||
{
|
{
|
||||||
httpRequestMessage.Content = new ByteArrayContent(requestMessage.BodyAsBytes);
|
httpRequestMessage.Content = new ByteArrayContent(requestMessage.BodyAsBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Overwrite the host header
|
||||||
|
httpRequestMessage.Headers.Host = requiredUri.Authority;
|
||||||
|
|
||||||
|
// Set headers if present
|
||||||
|
if (requestMessage.Headers != null)
|
||||||
|
{
|
||||||
|
foreach (var header in requestMessage.Headers.Where(header => !string.Equals(header.Key, "HOST", StringComparison.OrdinalIgnoreCase)))
|
||||||
|
{
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Call the URL
|
// Call the URL
|
||||||
var httpResponseMessage = await client.SendAsync(httpRequestMessage, HttpCompletionOption.ResponseContentRead);
|
var httpResponseMessage = await client.SendAsync(httpRequestMessage, HttpCompletionOption.ResponseContentRead);
|
||||||
|
|
||||||
@@ -74,9 +95,24 @@ namespace WireMock.Http
|
|||||||
Body = await httpResponseMessage.Content.ReadAsStringAsync()
|
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;
|
return responseMessage;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
@@ -19,6 +20,8 @@ namespace WireMock.ResponseBuilders
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class Response : IResponseBuilder
|
public class Response : IResponseBuilder
|
||||||
{
|
{
|
||||||
|
private HttpClient httpClientForProxy;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The delay
|
/// The delay
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -317,6 +320,7 @@ namespace WireMock.ResponseBuilders
|
|||||||
|
|
||||||
ProxyUrl = proxyUrl;
|
ProxyUrl = proxyUrl;
|
||||||
X509Certificate2ThumbprintOrSubjectName = clientX509Certificate2ThumbprintOrSubjectName;
|
X509Certificate2ThumbprintOrSubjectName = clientX509Certificate2ThumbprintOrSubjectName;
|
||||||
|
httpClientForProxy = HttpClientHelper.CreateHttpClient(clientX509Certificate2ThumbprintOrSubjectName);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -332,12 +336,12 @@ namespace WireMock.ResponseBuilders
|
|||||||
if (Delay != null)
|
if (Delay != null)
|
||||||
await Task.Delay(Delay.Value);
|
await Task.Delay(Delay.Value);
|
||||||
|
|
||||||
if (ProxyUrl != null)
|
if (ProxyUrl != null && httpClientForProxy != null)
|
||||||
{
|
{
|
||||||
var requestUri = new Uri(requestMessage.Url);
|
var requestUri = new Uri(requestMessage.Url);
|
||||||
var proxyUri = new Uri(ProxyUrl);
|
var proxyUri = new Uri(ProxyUrl);
|
||||||
var proxyUriWithRequestPathAndQuery = new Uri(proxyUri, requestUri.PathAndQuery);
|
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)
|
if (UseTransformer)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
@@ -129,8 +130,11 @@ namespace WireMock.Server
|
|||||||
}
|
}
|
||||||
|
|
||||||
#region Proxy and Record
|
#region Proxy and Record
|
||||||
|
private HttpClient httpClientForProxy;
|
||||||
|
|
||||||
private void InitProxyAndRecord(ProxyAndRecordSettings settings)
|
private void InitProxyAndRecord(ProxyAndRecordSettings settings)
|
||||||
{
|
{
|
||||||
|
httpClientForProxy = HttpClientHelper.CreateHttpClient(settings.X509Certificate2ThumbprintOrSubjectName);
|
||||||
Given(Request.Create().WithPath("/*").UsingAnyVerb()).RespondWith(new ProxyAsyncResponseProvider(ProxyAndRecordAsync, settings));
|
Given(Request.Create().WithPath("/*").UsingAnyVerb()).RespondWith(new ProxyAsyncResponseProvider(ProxyAndRecordAsync, settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,7 +144,7 @@ namespace WireMock.Server
|
|||||||
var proxyUri = new Uri(settings.Url);
|
var proxyUri = new Uri(settings.Url);
|
||||||
var proxyUriWithRequestPathAndQuery = new Uri(proxyUri, requestUri.PathAndQuery);
|
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)
|
if (settings.SaveMapping)
|
||||||
{
|
{
|
||||||
|
|||||||
157
test/WireMock.Net.Tests/FluentMockServerTests.Proxy.cs
Normal file
157
test/WireMock.Net.Tests/FluentMockServerTests.Proxy.cs
Normal file
@@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,17 +6,15 @@ using System.Net;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NFluent;
|
using NFluent;
|
||||||
using Xunit;
|
|
||||||
using WireMock.Matchers;
|
using WireMock.Matchers;
|
||||||
using WireMock.RequestBuilders;
|
using WireMock.RequestBuilders;
|
||||||
using WireMock.ResponseBuilders;
|
using WireMock.ResponseBuilders;
|
||||||
using WireMock.Server;
|
using WireMock.Server;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
namespace WireMock.Net.Tests
|
namespace WireMock.Net.Tests
|
||||||
{
|
{
|
||||||
//[TestFixture]
|
public partial class FluentMockServerTests : IDisposable
|
||||||
//[Timeout(5000)]
|
|
||||||
public class FluentMockServerTests : IDisposable
|
|
||||||
{
|
{
|
||||||
private FluentMockServer _server;
|
private FluentMockServer _server;
|
||||||
|
|
||||||
@@ -178,7 +176,7 @@ namespace WireMock.Net.Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Should_respond_to_request_bodyAsString()
|
public async Task FluentMockServer_Should_respond_to_request_bodyAsString()
|
||||||
{
|
{
|
||||||
// given
|
// given
|
||||||
_server = FluentMockServer.Start();
|
_server = FluentMockServer.Start();
|
||||||
@@ -199,7 +197,7 @@ namespace WireMock.Net.Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Should_respond_to_request_bodyAsBase64()
|
public async Task FluentMockServer_Should_respond_to_request_bodyAsBase64()
|
||||||
{
|
{
|
||||||
// given
|
// given
|
||||||
_server = FluentMockServer.Start();
|
_server = FluentMockServer.Start();
|
||||||
@@ -214,7 +212,7 @@ namespace WireMock.Net.Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Should_respond_to_request_bodyAsBytes()
|
public async Task FluentMockServer_Should_respond_to_request_bodyAsBytes()
|
||||||
{
|
{
|
||||||
// given
|
// given
|
||||||
_server = FluentMockServer.Start();
|
_server = FluentMockServer.Start();
|
||||||
@@ -231,7 +229,7 @@ namespace WireMock.Net.Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Should_respond_404_for_unexpected_request()
|
public async Task FluentMockServer_Should_respond_404_for_unexpected_request()
|
||||||
{
|
{
|
||||||
// given
|
// given
|
||||||
_server = FluentMockServer.Start();
|
_server = FluentMockServer.Start();
|
||||||
@@ -245,7 +243,7 @@ namespace WireMock.Net.Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[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
|
// given
|
||||||
_server = FluentMockServer.Start();
|
_server = FluentMockServer.Start();
|
||||||
@@ -264,7 +262,7 @@ namespace WireMock.Net.Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Should_reset_requestlogs()
|
public async Task FluentMockServer_Should_reset_requestlogs()
|
||||||
{
|
{
|
||||||
// given
|
// given
|
||||||
_server = FluentMockServer.Start();
|
_server = FluentMockServer.Start();
|
||||||
@@ -278,7 +276,7 @@ namespace WireMock.Net.Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Should_reset_mappings()
|
public void FluentMockServer_Should_reset_mappings()
|
||||||
{
|
{
|
||||||
// given
|
// given
|
||||||
_server = FluentMockServer.Start();
|
_server = FluentMockServer.Start();
|
||||||
@@ -300,7 +298,7 @@ namespace WireMock.Net.Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Should_respond_a_redirect_without_body()
|
public async Task FluentMockServer_Should_respond_a_redirect_without_body()
|
||||||
{
|
{
|
||||||
// given
|
// given
|
||||||
_server = FluentMockServer.Start();
|
_server = FluentMockServer.Start();
|
||||||
@@ -328,7 +326,7 @@ namespace WireMock.Net.Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Should_delay_responses_for_a_given_route()
|
public async Task FluentMockServer_Should_delay_responses_for_a_given_route()
|
||||||
{
|
{
|
||||||
// given
|
// given
|
||||||
_server = FluentMockServer.Start();
|
_server = FluentMockServer.Start();
|
||||||
@@ -351,7 +349,7 @@ namespace WireMock.Net.Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Should_delay_responses()
|
public async Task FluentMockServer_Should_delay_responses()
|
||||||
{
|
{
|
||||||
// given
|
// given
|
||||||
_server = FluentMockServer.Start();
|
_server = FluentMockServer.Start();
|
||||||
@@ -370,22 +368,6 @@ namespace WireMock.Net.Tests
|
|||||||
Check.That(watch.ElapsedMilliseconds).IsStrictlyGreaterThan(200);
|
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
|
//Leaving commented as this requires an actual certificate with password, along with a service that expects a client certificate
|
||||||
//[Fact]
|
//[Fact]
|
||||||
//public async Task Should_proxy_responses_with_client_certificate()
|
//public async Task Should_proxy_responses_with_client_certificate()
|
||||||
@@ -429,6 +411,7 @@ namespace WireMock.Net.Tests
|
|||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_server?.Stop();
|
_server?.Stop();
|
||||||
|
_serverForProxyForwarding?.Stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user