mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-02-14 22:37:41 +01:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
018d2a904d | ||
|
|
939a5a61ab | ||
|
|
a15e6747b0 | ||
|
|
6c38400827 | ||
|
|
cb1117fdaa | ||
|
|
e25c873765 | ||
|
|
d83f308591 | ||
|
|
c8c9ab99c5 | ||
|
|
d134684bcb | ||
|
|
a96b7bca1e | ||
|
|
cbe6a0a2b4 | ||
|
|
15370a89ca | ||
|
|
656f7f5432 | ||
|
|
bcdc3d646a | ||
|
|
10350fac04 | ||
|
|
37244d5c2f | ||
|
|
07f03997c0 | ||
|
|
7c289d44a7 |
@@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26430.13
|
||||
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
|
||||
@@ -21,11 +24,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net", "src\WireMoc
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Tests", "test\WireMock.Net.Tests\WireMock.Net.Tests.csproj", "{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Console.NETCoreApp", "examples\WireMock.Net.Console.NETCoreApp\WireMock.Net.Console.NETCoreApp.csproj", "{FE281639-B014-4C8A-96FA-141164A74713}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.NETCoreApp", "examples\WireMock.Net.Console.NETCoreApp\WireMock.Net.Console.NETCoreApp.csproj", "{FE281639-B014-4C8A-96FA-141164A74713}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.Record.NETCoreApp", "examples\WireMock.Net.Console.Record.NETCoreApp\WireMock.Net.Console.Record.NETCoreApp.csproj", "{1995E414-F197-4AB4-90C2-68D806B5AF59}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Client", "examples\WireMock.Net.Client\WireMock.Net.Client.csproj", "{058D4B6C-C03E-49D0-91DB-A535B058FA0D}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Client", "examples\WireMock.Net.Client\WireMock.Net.Client.csproj", "{058D4B6C-C03E-49D0-91DB-A535B058FA0D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.StandAlone", "src\WireMock.Net.StandAlone\WireMock.Net.StandAlone.csproj", "{B6269AAC-170A-43D5-8B9A-579DED3D9A95}"
|
||||
EndProject
|
||||
@@ -36,6 +39,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.StandAlone.Net
|
||||
{B6269AAC-170A-43D5-8B9A-579DED3D9A95} = {B6269AAC-170A-43D5-8B9A-579DED3D9A95}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.ConsoleApplication", "examples\WireMock.Net.ConsoleApplication\WireMock.Net.ConsoleApplication.csproj", "{668F689E-57B4-422E-8846-C0FF643CA268}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -74,6 +79,10 @@ Global
|
||||
{668F689E-57B4-422E-8846-C0FF643CA999}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{668F689E-57B4-422E-8846-C0FF643CA999}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{668F689E-57B4-422E-8846-C0FF643CA999}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{668F689E-57B4-422E-8846-C0FF643CA268}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{668F689E-57B4-422E-8846-C0FF643CA268}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{668F689E-57B4-422E-8846-C0FF643CA268}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{668F689E-57B4-422E-8846-C0FF643CA268}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -87,5 +96,9 @@ Global
|
||||
{B6269AAC-170A-43D5-8B9A-579DED3D9A95} = {EF242EDF-7133-4277-9A0C-18744DE08707}
|
||||
{10E16614-61CA-48D8-8BDD-664C13913DED} = {F0C22C47-DF71-463C-9B04-B4E0F3B8708A}
|
||||
{668F689E-57B4-422E-8846-C0FF643CA999} = {F0C22C47-DF71-463C-9B04-B4E0F3B8708A}
|
||||
{668F689E-57B4-422E-8846-C0FF643CA268} = {F0C22C47-DF71-463C-9B04-B4E0F3B8708A}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {BF428BCC-C837-433B-87D2-15C7014B73E9}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
@@ -39,6 +39,6 @@ test_script:
|
||||
- nuget.exe install coveralls.net -ExcludeVersion
|
||||
- pip install codecov
|
||||
|
||||
- cmd: '"OpenCover\tools\OpenCover.Console.exe" -register:user -target:dotnet.exe -targetargs:"test test\WireMock.Net.Tests\WireMock.Net.Tests.csproj --no-build" -returntargetcode -filter:"+[WireMock.Net]* -[WireMock.Net.Tests*]*" -output:coverage.xml -oldstyle -searchdirs:".\test\WireMock.Net.Tests\bin\%CONFIGURATION%\net452"'
|
||||
- cmd: '"OpenCover\tools\OpenCover.Console.exe" -target:dotnet.exe -targetargs:"test test\WireMock.Net.Tests\WireMock.Net.Tests.csproj --no-build" -output:coverage.xml -returntargetcode -register:user -filter:"+[WireMock.Net]* -[WireMock.Net.Tests*]*" -nodefaultfilters -returntargetcode -oldstyle'
|
||||
- codecov -f "coverage.xml"
|
||||
- coveralls.net\tools\csmacnz.Coveralls.exe --opencover -i .\coverage.xml
|
||||
@@ -18,9 +18,6 @@
|
||||
<Content Include="__admin\mappings\11111110-a633-40e8-a244-5cb80bc0ab66.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="__admin\mappings\826aff7c-6208-4a3c-923d-575248907db4.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -28,4 +25,13 @@
|
||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="__admin\mappings\791a3f31-6946-4ce7-8e6f-0237c7443275.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="__admin\mappings\791a3f31-6946-4ce7-8e6f-0237c7443275.json">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -14,8 +14,9 @@
|
||||
},
|
||||
"Response": {
|
||||
"BodyAsJson": { "body": "static mapping" },
|
||||
"Headers": {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
"Headers": {
|
||||
"Content-Type": "application/json",
|
||||
"Test-X": [ "test 1", "test 2" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"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
@@ -10,13 +10,15 @@ namespace WireMock.Net.Console.Record.NETCoreApp
|
||||
{
|
||||
var server = FluentMockServer.Start(new FluentMockServerSettings
|
||||
{
|
||||
Urls = new[] { "http://localhost:9095/", "https://localhost:9096/" },
|
||||
Urls = new[] { "http://localhost:9091/", "https://localhost:9443/" },
|
||||
StartAdminInterface = true,
|
||||
ReadStaticMappings = false,
|
||||
ProxyAndRecordSettings = new ProxyAndRecordSettings
|
||||
{
|
||||
Url = "https://www.msn.com",
|
||||
Url = "https://www.google.com",
|
||||
//X509Certificate2ThumbprintOrSubjectName = "www.yourclientcertname.com OR yourcertificatethumbprint (only if the service you're proxying to requires it)",
|
||||
SaveMapping = true
|
||||
SaveMapping = true,
|
||||
SaveMappingToFile = false
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -15,4 +15,8 @@
|
||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="__admin\mappings\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
File diff suppressed because one or more lines are too long
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.RequestBuilders;
|
||||
@@ -21,7 +20,9 @@ namespace WireMock.Net.ConsoleApplication
|
||||
{
|
||||
Urls = new[] { url1, url2, url3 },
|
||||
StartAdminInterface = true,
|
||||
ReadStaticMappings = true
|
||||
ReadStaticMappings = true,
|
||||
PreWireMockMiddlewareInit = app => { System.Console.WriteLine($"PreWireMockMiddlewareInit : {app.GetType()}"); },
|
||||
PostWireMockMiddlewareInit = app => { System.Console.WriteLine($"PostWireMockMiddlewareInit : {app.GetType()}"); }
|
||||
});
|
||||
System.Console.WriteLine("FluentMockServer listening at {0}", string.Join(" and ", server.Urls));
|
||||
|
||||
@@ -29,6 +30,46 @@ namespace WireMock.Net.ConsoleApplication
|
||||
|
||||
// server.AllowPartialMapping();
|
||||
|
||||
server
|
||||
.Given(Request.Create().WithPath("/headers", "/headers_test").UsingPost().WithHeader("Content-Type", "application/json*"))
|
||||
.RespondWith(Response.Create()
|
||||
.WithStatusCode(201)
|
||||
.WithHeader("MyHeader", "application/json", "application/json2")
|
||||
.WithBody(@"{ ""result"": ""data posted with 201""}"));
|
||||
|
||||
server
|
||||
.Given(Request.Create().WithPath("/file").UsingGet())
|
||||
.RespondWith(Response.Create()
|
||||
.WithBodyFromFile(@"c:\temp\x.json", false)
|
||||
);
|
||||
|
||||
server
|
||||
.Given(Request.Create().WithPath("/filecache").UsingGet())
|
||||
.RespondWith(Response.Create()
|
||||
.WithBodyFromFile(@"c:\temp\x.json")
|
||||
);
|
||||
|
||||
server
|
||||
.Given(Request.Create().WithPath("/file_rel").UsingGet())
|
||||
.RespondWith(Response.Create()
|
||||
.WithBodyFromFile("Program.cs", false)
|
||||
);
|
||||
|
||||
server
|
||||
.Given(Request.Create().WithHeader("ProxyThis", "true")
|
||||
.UsingGet())
|
||||
.RespondWith(Response.Create()
|
||||
.WithProxy("http://www.google.com")
|
||||
);
|
||||
|
||||
server
|
||||
.Given(Request.Create().WithPath("/bodyasbytes.png")
|
||||
.UsingGet())
|
||||
.RespondWith(Response.Create()
|
||||
.WithHeader("Content-Type", "image/png")
|
||||
.WithBody(Convert.FromBase64String("iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAIAAAACUFjqAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMTczbp9jAAAAJ0lEQVQoU2NgUPuPD6Hz0RCEAtJoiAxpCCBXGgmRIo0TofORkdp/AMiMdRVnV6O0AAAAAElFTkSuQmCC"))
|
||||
);
|
||||
|
||||
server
|
||||
.Given(Request.Create().WithPath("/oauth2/access").UsingPost().WithBody("grant_type=password;username=u;password=p"))
|
||||
.RespondWith(Response.Create()
|
||||
@@ -58,13 +99,6 @@ namespace WireMock.Net.ConsoleApplication
|
||||
.WithHeader("Content-Type", "application/json")
|
||||
.WithBody(@"{ ""result"": ""data posted with FUNC 201""}"));
|
||||
|
||||
server
|
||||
.Given(Request.Create().WithPath("/data", "/ax").UsingPost().WithHeader("Content-Type", "application/json*"))
|
||||
.RespondWith(Response.Create()
|
||||
.WithStatusCode(201)
|
||||
.WithHeader("Content-Type", "application/json")
|
||||
.WithBody(@"{ ""result"": ""data posted with 201""}"));
|
||||
|
||||
server
|
||||
.Given(Request.Create().WithPath("/json").UsingPost().WithBody(new JsonPathMatcher("$.things[?(@.name == 'RequiredThing')]")))
|
||||
.RespondWith(Response.Create()
|
||||
|
||||
@@ -47,9 +47,6 @@
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="WireMock.Net">
|
||||
<HintPath>..\..\src\WireMock.Net\bin\$(Configuration)\net45\WireMock.Net.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="MainApp.cs" />
|
||||
@@ -67,6 +64,16 @@
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net.StandAlone\WireMock.Net.StandAlone.csproj">
|
||||
<Project>{b6269aac-170a-43d5-8b9a-579ded3d9a95}</Project>
|
||||
<Name>WireMock.Net.StandAlone</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj">
|
||||
<Project>{d3804228-91f4-4502-9595-39584e5a01ad}</Project>
|
||||
<Name>WireMock.Net</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
||||
@@ -66,6 +66,7 @@ namespace WireMock.Net.StandAlone
|
||||
{
|
||||
Url = proxyURL,
|
||||
SaveMapping = parser.GetBoolValue("SaveMapping"),
|
||||
SaveMappingToFile = parser.GetBoolValue("SaveMappingToFile"),
|
||||
X509Certificate2ThumbprintOrSubjectName = parser.GetStringValue("X509Certificate2ThumbprintOrSubjectName")
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,10 +3,9 @@
|
||||
<PropertyGroup>
|
||||
<Description>Lightweight StandAlone Http Mocking Server for .Net.</Description>
|
||||
<AssemblyTitle>WireMock.Net.StandAlone</AssemblyTitle>
|
||||
<Version>1.0.2.4</Version>
|
||||
<Version>1.0.2.7</Version>
|
||||
<Authors>Stef Heyenrath</Authors>
|
||||
<TargetFrameworks>net452;net46;netstandard1.3;netstandard2.0</TargetFrameworks>
|
||||
<!-- <TargetFrameworks>netstandard1.3;netstandard2.0</TargetFrameworks> -->
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<AssemblyName>WireMock.Net.StandAlone</AssemblyName>
|
||||
<PackageId>WireMock.Net.StandAlone</PackageId>
|
||||
|
||||
@@ -10,79 +10,71 @@ namespace WireMock.Admin.Mappings
|
||||
/// <summary>
|
||||
/// Gets or sets the HTTP status.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The HTTP status.
|
||||
/// </value>
|
||||
public int? StatusCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the body destination (SameAsSource, String or Bytes).
|
||||
/// </summary>
|
||||
public string BodyDestination { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the body.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The body.
|
||||
/// </value>
|
||||
public string Body { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the body.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The body.
|
||||
/// </value>
|
||||
public string BodyAsBase64 { get; set; }
|
||||
public string BodyFromBase64 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the body (as JSON object).
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The body.
|
||||
/// </value>
|
||||
public object BodyAsJson { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the body (as bytearray).
|
||||
/// </summary>
|
||||
public byte[] BodyAsBytes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the body as a file.
|
||||
/// </summary>
|
||||
public string BodyAsFile { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Is the body as file cached?
|
||||
/// </summary>
|
||||
public bool? BodyAsFileIsCached { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the body encoding.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The body encoding.
|
||||
/// </value>
|
||||
public EncodingModel BodyEncoding { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether [use transformer].
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if [use transformer]; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool UseTransformer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the headers.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The headers.
|
||||
/// </value>
|
||||
public IDictionary<string, string> Headers { get; set; }
|
||||
public IDictionary<string, object> Headers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Headers (Raw).
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The Headers (Raw).
|
||||
/// </value>
|
||||
public string HeadersRaw { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the delay in milliseconds.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The delay in milliseconds.
|
||||
/// </value>
|
||||
public int? Delay { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Proxy URL.
|
||||
/// </summary>
|
||||
/// <value>ProxyUrl</value>
|
||||
public string ProxyUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -23,17 +23,11 @@ namespace WireMock.Admin.Requests
|
||||
/// <summary>
|
||||
/// Gets or sets the Path.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The Path.
|
||||
/// </value>
|
||||
public string Path { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the absolete URL.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The absolute URL.
|
||||
/// </value>
|
||||
public string AbsoluteUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@@ -44,41 +38,26 @@ namespace WireMock.Admin.Requests
|
||||
/// <summary>
|
||||
/// Gets or sets the method.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The method.
|
||||
/// </value>
|
||||
public string Method { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Headers.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The Headers.
|
||||
/// </value>
|
||||
public IDictionary<string, string> Headers { get; set; }
|
||||
public IDictionary<string, WireMockList<string>> Headers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Cookies.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The Cookies.
|
||||
/// </value>
|
||||
public IDictionary<string, string> Cookies { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the body.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The body.
|
||||
/// </value>
|
||||
public string Body { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the body encoding.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The body encoding.
|
||||
/// </value>
|
||||
public EncodingModel BodyEncoding { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using WireMock.Admin.Mappings;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Admin.Requests
|
||||
{
|
||||
@@ -16,13 +17,33 @@ namespace WireMock.Admin.Requests
|
||||
/// <summary>
|
||||
/// Gets the headers.
|
||||
/// </summary>
|
||||
public IDictionary<string, string> Headers { get; set; }
|
||||
public IDictionary<string, WireMockList<string>> Headers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the body destination (SameAsSource, String or Bytes).
|
||||
/// </summary>
|
||||
public string BodyDestination { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the body.
|
||||
/// </summary>
|
||||
public string Body { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the body as bytes.
|
||||
/// </summary>
|
||||
public byte[] BodyAsBytes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the body as file.
|
||||
/// </summary>
|
||||
public string BodyAsFile { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Is the body as file cached?
|
||||
/// </summary>
|
||||
public bool? BodyAsFileIsCached { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the original body.
|
||||
/// </summary>
|
||||
|
||||
@@ -138,5 +138,23 @@ namespace WireMock.Client
|
||||
/// <param name="model">The RequestModel</param>
|
||||
[Post("__admin/requests/find")]
|
||||
Task<IList<LogRequestModel>> FindRequestsAsync([Body] RequestModel model);
|
||||
|
||||
/// <summary>
|
||||
/// Get all scenarios
|
||||
/// </summary>
|
||||
[Get("__admin/scenarios")]
|
||||
Task<string> GetScenariosAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Delete (reset) all scenarios
|
||||
/// </summary>
|
||||
[Delete("__admin/scenarios")]
|
||||
Task<string> DeleteScenariosAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Delete (reset) all scenarios
|
||||
/// </summary>
|
||||
[Post("__admin/scenarios")]
|
||||
Task<string> ResetScenariosAsync();
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,25 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Security.Authentication;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
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,
|
||||
@@ -25,63 +28,91 @@ namespace WireMock.Http
|
||||
|
||||
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,
|
||||
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
|
||||
AutomaticDecompression = System.Net.DecompressionMethods.GZip | System.Net.DecompressionMethods.Deflate
|
||||
};
|
||||
|
||||
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<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);
|
||||
|
||||
// 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.Add(headerName, new[] { requestMessage.Headers[headerName] });
|
||||
}
|
||||
}
|
||||
|
||||
// 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 = 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
|
||||
var httpResponseMessage = await client.SendAsync(httpRequestMessage, HttpCompletionOption.ResponseContentRead);
|
||||
|
||||
|
||||
// Transform response
|
||||
var responseMessage = new ResponseMessage
|
||||
{
|
||||
StatusCode = (int)httpResponseMessage.StatusCode,
|
||||
|
||||
BodyAsBytes = await httpResponseMessage.Content.ReadAsByteArrayAsync(),
|
||||
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;
|
||||
|
||||
96
src/WireMock.Net/Http/HttpKnownHeaderNames.cs
Normal file
96
src/WireMock.Net/Http/HttpKnownHeaderNames.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace WireMock.Http
|
||||
{
|
||||
/// <summary>
|
||||
/// Copied from https://raw.githubusercontent.com/dotnet/corefx/master/src/Common/src/System/Net/HttpKnownHeaderNames.cs
|
||||
/// </summary>
|
||||
internal static class HttpKnownHeaderNames
|
||||
{
|
||||
public const string Accept = "Accept";
|
||||
public const string AcceptCharset = "Accept-Charset";
|
||||
public const string AcceptEncoding = "Accept-Encoding";
|
||||
public const string AcceptLanguage = "Accept-Language";
|
||||
public const string AcceptPatch = "Accept-Patch";
|
||||
public const string AcceptRanges = "Accept-Ranges";
|
||||
public const string AccessControlAllowCredentials = "Access-Control-Allow-Credentials";
|
||||
public const string AccessControlAllowHeaders = "Access-Control-Allow-Headers";
|
||||
public const string AccessControlAllowMethods = "Access-Control-Allow-Methods";
|
||||
public const string AccessControlAllowOrigin = "Access-Control-Allow-Origin";
|
||||
public const string AccessControlExposeHeaders = "Access-Control-Expose-Headers";
|
||||
public const string AccessControlMaxAge = "Access-Control-Max-Age";
|
||||
public const string Age = "Age";
|
||||
public const string Allow = "Allow";
|
||||
public const string AltSvc = "Alt-Svc";
|
||||
public const string Authorization = "Authorization";
|
||||
public const string CacheControl = "Cache-Control";
|
||||
public const string Connection = "Connection";
|
||||
public const string ContentDisposition = "Content-Disposition";
|
||||
public const string ContentEncoding = "Content-Encoding";
|
||||
public const string ContentLanguage = "Content-Language";
|
||||
public const string ContentLength = "Content-Length";
|
||||
public const string ContentLocation = "Content-Location";
|
||||
public const string ContentMD5 = "Content-MD5";
|
||||
public const string ContentRange = "Content-Range";
|
||||
public const string ContentSecurityPolicy = "Content-Security-Policy";
|
||||
public const string ContentType = "Content-Type";
|
||||
public const string Cookie = "Cookie";
|
||||
public const string Cookie2 = "Cookie2";
|
||||
public const string Date = "Date";
|
||||
public const string ETag = "ETag";
|
||||
public const string Expect = "Expect";
|
||||
public const string Expires = "Expires";
|
||||
public const string From = "From";
|
||||
public const string Host = "Host";
|
||||
public const string IfMatch = "If-Match";
|
||||
public const string IfModifiedSince = "If-Modified-Since";
|
||||
public const string IfNoneMatch = "If-None-Match";
|
||||
public const string IfRange = "If-Range";
|
||||
public const string IfUnmodifiedSince = "If-Unmodified-Since";
|
||||
public const string KeepAlive = "Keep-Alive";
|
||||
public const string LastModified = "Last-Modified";
|
||||
public const string Link = "Link";
|
||||
public const string Location = "Location";
|
||||
public const string MaxForwards = "Max-Forwards";
|
||||
public const string Origin = "Origin";
|
||||
public const string P3P = "P3P";
|
||||
public const string Pragma = "Pragma";
|
||||
public const string ProxyAuthenticate = "Proxy-Authenticate";
|
||||
public const string ProxyAuthorization = "Proxy-Authorization";
|
||||
public const string ProxyConnection = "Proxy-Connection";
|
||||
public const string PublicKeyPins = "Public-Key-Pins";
|
||||
public const string Range = "Range";
|
||||
public const string Referer = "Referer"; // NB: The spelling-mistake "Referer" for "Referrer" must be matched.
|
||||
public const string RetryAfter = "Retry-After";
|
||||
public const string SecWebSocketAccept = "Sec-WebSocket-Accept";
|
||||
public const string SecWebSocketExtensions = "Sec-WebSocket-Extensions";
|
||||
public const string SecWebSocketKey = "Sec-WebSocket-Key";
|
||||
public const string SecWebSocketProtocol = "Sec-WebSocket-Protocol";
|
||||
public const string SecWebSocketVersion = "Sec-WebSocket-Version";
|
||||
public const string Server = "Server";
|
||||
public const string SetCookie = "Set-Cookie";
|
||||
public const string SetCookie2 = "Set-Cookie2";
|
||||
public const string StrictTransportSecurity = "Strict-Transport-Security";
|
||||
public const string TE = "TE";
|
||||
public const string TSV = "TSV";
|
||||
public const string Trailer = "Trailer";
|
||||
public const string TransferEncoding = "Transfer-Encoding";
|
||||
public const string Upgrade = "Upgrade";
|
||||
public const string UpgradeInsecureRequests = "Upgrade-Insecure-Requests";
|
||||
public const string UserAgent = "User-Agent";
|
||||
public const string Vary = "Vary";
|
||||
public const string Via = "Via";
|
||||
public const string WWWAuthenticate = "WWW-Authenticate";
|
||||
public const string Warning = "Warning";
|
||||
public const string XAspNetVersion = "X-AspNet-Version";
|
||||
public const string XContentDuration = "X-Content-Duration";
|
||||
public const string XContentTypeOptions = "X-Content-Type-Options";
|
||||
public const string XFrameOptions = "X-Frame-Options";
|
||||
public const string XMSEdgeRef = "X-MSEdge-Ref";
|
||||
public const string XPoweredBy = "X-Powered-By";
|
||||
public const string XRequestID = "X-Request-ID";
|
||||
public const string XUACompatible = "X-UA-Compatible";
|
||||
}
|
||||
}
|
||||
@@ -13,25 +13,16 @@ namespace WireMock
|
||||
/// <summary>
|
||||
/// Gets the unique identifier.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The unique identifier.
|
||||
/// </value>
|
||||
public Guid Guid { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the unique title.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The unique title.
|
||||
/// </value>
|
||||
public string Title { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the priority.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The priority.
|
||||
/// </value>
|
||||
public int Priority { get; }
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace WireMock.Matchers.Request
|
||||
/// Initializes a new instance of the <see cref="RequestMessageClientIPMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="clientIPs">The clientIPs.</param>
|
||||
public RequestMessageClientIPMatcher([NotNull] params string[] clientIPs) : this(clientIPs.Select(ip => new WildcardMatcher(ip)).ToArray())
|
||||
public RequestMessageClientIPMatcher([NotNull] params string[] clientIPs) : this(clientIPs.Select(ip => new WildcardMatcher(ip)).Cast<IMatcher>().ToArray())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -49,14 +49,7 @@ namespace WireMock.Matchers.Request
|
||||
Funcs = funcs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified RequestMessage is match.
|
||||
/// </summary>
|
||||
/// <param name="requestMessage">The RequestMessage.</param>
|
||||
/// <param name="requestMatchResult">The RequestMatchResult.</param>
|
||||
/// <returns>
|
||||
/// A value between 0.0 - 1.0 of the similarity.
|
||||
/// </returns>
|
||||
/// <inheritdoc cref="IRequestMatcher.GetMatchingScore"/>
|
||||
public double GetMatchingScore(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
|
||||
{
|
||||
double score = IsMatch(requestMessage);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Util;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock.Matchers.Request
|
||||
@@ -9,12 +10,13 @@ namespace WireMock.Matchers.Request
|
||||
/// <summary>
|
||||
/// The request header matcher.
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="IRequestMatcher"/>
|
||||
public class RequestMessageHeaderMatcher : IRequestMatcher
|
||||
{
|
||||
/// <summary>
|
||||
/// The functions
|
||||
/// </summary>
|
||||
public Func<IDictionary<string, string>, bool>[] Funcs { get; }
|
||||
public Func<IDictionary<string, string[]>, bool>[] Funcs { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The name
|
||||
@@ -31,7 +33,7 @@ namespace WireMock.Matchers.Request
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="pattern">The pattern.</param>
|
||||
/// <param name="ignoreCase">The ignoreCase.</param>
|
||||
/// <param name="ignoreCase">if set to <c>true</c> [ignore case].</param>
|
||||
public RequestMessageHeaderMatcher([NotNull] string name, [NotNull] string pattern, bool ignoreCase = true)
|
||||
{
|
||||
Check.NotNull(name, nameof(name));
|
||||
@@ -41,6 +43,21 @@ namespace WireMock.Matchers.Request
|
||||
Matchers = new IMatcher[] { new WildcardMatcher(pattern, ignoreCase) };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestMessageHeaderMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="patterns">The patterns.</param>
|
||||
/// <param name="ignoreCase">if set to <c>true</c> [ignore case].</param>
|
||||
public RequestMessageHeaderMatcher([NotNull] string name, [NotNull] string[] patterns, bool ignoreCase = true)
|
||||
{
|
||||
Check.NotNull(name, nameof(name));
|
||||
Check.NotNull(patterns, nameof(patterns));
|
||||
|
||||
Name = name;
|
||||
Matchers = patterns.Select(pattern => new WildcardMatcher(pattern, ignoreCase)).Cast<IMatcher>().ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestMessageHeaderMatcher"/> class.
|
||||
/// </summary>
|
||||
@@ -59,21 +76,14 @@ namespace WireMock.Matchers.Request
|
||||
/// Initializes a new instance of the <see cref="RequestMessageHeaderMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="funcs">The funcs.</param>
|
||||
public RequestMessageHeaderMatcher([NotNull] params Func<IDictionary<string, string>, bool>[] funcs)
|
||||
public RequestMessageHeaderMatcher([NotNull] params Func<IDictionary<string, string[]>, bool>[] funcs)
|
||||
{
|
||||
Check.NotNull(funcs, nameof(funcs));
|
||||
|
||||
Funcs = funcs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified RequestMessage is match.
|
||||
/// </summary>
|
||||
/// <param name="requestMessage">The RequestMessage.</param>
|
||||
/// <param name="requestMatchResult">The RequestMatchResult.</param>
|
||||
/// <returns>
|
||||
/// A value between 0.0 - 1.0 of the similarity.
|
||||
/// </returns>
|
||||
/// <inheritdoc cref="IRequestMatcher.GetMatchingScore"/>
|
||||
public double GetMatchingScore(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
|
||||
{
|
||||
double score = IsMatch(requestMessage);
|
||||
@@ -86,7 +96,7 @@ namespace WireMock.Matchers.Request
|
||||
return MatchScores.Mismatch;
|
||||
|
||||
if (Funcs != null)
|
||||
return MatchScores.ToScore(Funcs.Any(f => f(requestMessage.Headers)));
|
||||
return MatchScores.ToScore(Funcs.Any(f => f(requestMessage.Headers.ToDictionary(entry => entry.Key, entry => entry.Value.ToArray()))));
|
||||
|
||||
if (Matchers == null)
|
||||
return MatchScores.Mismatch;
|
||||
@@ -94,8 +104,8 @@ namespace WireMock.Matchers.Request
|
||||
if (!requestMessage.Headers.ContainsKey(Name))
|
||||
return MatchScores.Mismatch;
|
||||
|
||||
string value = requestMessage.Headers[Name];
|
||||
return Matchers.Max(m => m.IsMatch(value));
|
||||
WireMockList<string> list = requestMessage.Headers[Name];
|
||||
return Matchers.Max(m => list.Max(value => m.IsMatch(value))); // TODO : is this correct ?
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ namespace WireMock.Matchers.Request
|
||||
/// Initializes a new instance of the <see cref="RequestMessagePathMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="paths">The paths.</param>
|
||||
public RequestMessagePathMatcher([NotNull] params string[] paths) : this(paths.Select(path => new WildcardMatcher(path)).ToArray())
|
||||
public RequestMessagePathMatcher([NotNull] params string[] paths) : this(paths.Select(path => new WildcardMatcher(path)).Cast<IMatcher>().ToArray())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -49,14 +49,7 @@ namespace WireMock.Matchers.Request
|
||||
Funcs = funcs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified RequestMessage is match.
|
||||
/// </summary>
|
||||
/// <param name="requestMessage">The RequestMessage.</param>
|
||||
/// <param name="requestMatchResult">The RequestMatchResult.</param>
|
||||
/// <returns>
|
||||
/// A value between 0.0 - 1.0 of the similarity.
|
||||
/// </returns>
|
||||
/// <inheritdoc cref="IRequestMatcher.GetMatchingScore"/>
|
||||
public double GetMatchingScore(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
|
||||
{
|
||||
double score = IsMatch(requestMessage);
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace WireMock.Matchers.Request
|
||||
/// Initializes a new instance of the <see cref="RequestMessageUrlMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="urls">The urls.</param>
|
||||
public RequestMessageUrlMatcher([NotNull] params string[] urls) : this(urls.Select(url => new WildcardMatcher(url)).ToArray())
|
||||
public RequestMessageUrlMatcher([NotNull] params string[] urls) : this(urls.Select(url => new WildcardMatcher(url)).Cast<IMatcher>().ToArray())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -49,14 +49,7 @@ namespace WireMock.Matchers.Request
|
||||
Funcs = funcs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified RequestMessage is match.
|
||||
/// </summary>
|
||||
/// <param name="requestMessage">The RequestMessage.</param>
|
||||
/// <param name="requestMatchResult">The RequestMatchResult.</param>
|
||||
/// <returns>
|
||||
/// A value between 0.0 - 1.0 of the similarity.
|
||||
/// </returns>
|
||||
/// <inheritdoc cref="IRequestMatcher.GetMatchingScore"/>
|
||||
public double GetMatchingScore(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
|
||||
{
|
||||
double score = IsMatch(requestMessage);
|
||||
|
||||
@@ -46,7 +46,10 @@ namespace WireMock.Owin
|
||||
_host = new WebHostBuilder()
|
||||
.Configure(appBuilder =>
|
||||
{
|
||||
appBuilder.UseMiddleware<GlobalExceptionMiddleware>();
|
||||
_options.PreWireMockMiddlewareInit?.Invoke(appBuilder);
|
||||
appBuilder.UseMiddleware<WireMockMiddleware>(_options);
|
||||
_options.PostWireMockMiddlewareInit?.Invoke(appBuilder);
|
||||
})
|
||||
.UseKestrel()
|
||||
.UseUrls(_uriPrefixes)
|
||||
|
||||
49
src/WireMock.Net/Owin/GlobalExceptionMiddleware.cs
Normal file
49
src/WireMock.Net/Owin/GlobalExceptionMiddleware.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
#if !NETSTANDARD
|
||||
using Microsoft.Owin;
|
||||
#else
|
||||
using Microsoft.AspNetCore.Http;
|
||||
#endif
|
||||
|
||||
namespace WireMock.Owin
|
||||
{
|
||||
#if !NETSTANDARD
|
||||
internal class GlobalExceptionMiddleware : OwinMiddleware
|
||||
#else
|
||||
internal class GlobalExceptionMiddleware
|
||||
#endif
|
||||
{
|
||||
#if !NETSTANDARD
|
||||
public GlobalExceptionMiddleware(OwinMiddleware next) : base(next) { }
|
||||
#else
|
||||
public GlobalExceptionMiddleware(RequestDelegate next)
|
||||
{
|
||||
Next = next;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NETSTANDARD
|
||||
public RequestDelegate Next { get; private set; }
|
||||
#endif
|
||||
|
||||
private readonly OwinResponseMapper _responseMapper = new OwinResponseMapper();
|
||||
|
||||
#if !NETSTANDARD
|
||||
public override async Task Invoke(IOwinContext ctx)
|
||||
#else
|
||||
public async Task Invoke(HttpContext ctx)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
await Next?.Invoke(ctx);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await _responseMapper.MapAsync(new ResponseMessage { StatusCode = 500, Body = JsonConvert.SerializeObject(ex) }, ctx.Response);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ namespace WireMock.Owin
|
||||
string bodyAsString = null;
|
||||
byte[] body = null;
|
||||
Encoding bodyEncoding = null;
|
||||
if (request.Body != null)
|
||||
if (ParseBody(method) && request.Body != null)
|
||||
{
|
||||
using (var streamReader = new StreamReader(request.Body))
|
||||
{
|
||||
@@ -57,18 +57,42 @@ namespace WireMock.Owin
|
||||
body = bodyEncoding.GetBytes(bodyAsString);
|
||||
}
|
||||
|
||||
var listenerHeaders = request.Headers;
|
||||
Dictionary<string, string[]> headers = null;
|
||||
if (request.Headers.Any())
|
||||
{
|
||||
headers = new Dictionary<string, string[]>();
|
||||
foreach (var header in request.Headers)
|
||||
{
|
||||
headers.Add(header.Key, header.Value);
|
||||
}
|
||||
}
|
||||
|
||||
var headers = new Dictionary<string, string>();
|
||||
foreach (var header in listenerHeaders)
|
||||
headers.Add(header.Key, header.Value.FirstOrDefault());
|
||||
|
||||
var cookies = new Dictionary<string, string>();
|
||||
|
||||
foreach (var cookie in request.Cookies)
|
||||
cookies.Add(cookie.Key, cookie.Value);
|
||||
IDictionary<string, string> cookies = null;
|
||||
if (request.Cookies.Any())
|
||||
{
|
||||
cookies = new Dictionary<string, string>();
|
||||
foreach (var cookie in request.Cookies)
|
||||
{
|
||||
cookies.Add(cookie.Key, cookie.Value);
|
||||
}
|
||||
}
|
||||
|
||||
return new RequestMessage(url, method, clientIP, body, bodyAsString, bodyEncoding, headers, cookies) { DateTime = DateTime.Now };
|
||||
}
|
||||
|
||||
private bool ParseBody(string method)
|
||||
{
|
||||
/*
|
||||
HEAD - No defined body semantics.
|
||||
GET - No defined body semantics.
|
||||
PUT - Body supported.
|
||||
POST - Body supported.
|
||||
DELETE - No defined body semantics.
|
||||
TRACE - Body not supported.
|
||||
OPTIONS - Body supported but no semantics on usage (maybe in the future).
|
||||
CONNECT - No defined body semantics
|
||||
*/
|
||||
return new[] { "PUT", "POST", "OPTIONS" }.Contains(method.ToUpper());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Http;
|
||||
#if !NETSTANDARD
|
||||
using Microsoft.Owin;
|
||||
#else
|
||||
@@ -32,15 +33,43 @@ namespace WireMock.Owin
|
||||
{
|
||||
response.StatusCode = responseMessage.StatusCode;
|
||||
|
||||
responseMessage.Headers.ToList().ForEach(pair => response.Headers.Append(pair.Key, pair.Value));
|
||||
if (responseMessage.Headers.ContainsKey(HttpKnownHeaderNames.ContentType))
|
||||
{
|
||||
response.ContentType = responseMessage.Headers[HttpKnownHeaderNames.ContentType].FirstOrDefault();
|
||||
}
|
||||
|
||||
if (responseMessage.Body == null)
|
||||
var headers = responseMessage.Headers.Where(h => h.Key != HttpKnownHeaderNames.ContentType).ToList();
|
||||
|
||||
#if !NETSTANDARD
|
||||
headers.ForEach(pair => response.Headers.AppendValues(pair.Key, pair.Value.ToArray()));
|
||||
#else
|
||||
headers.ForEach(pair => response.Headers.Append(pair.Key, pair.Value.ToArray()));
|
||||
#endif
|
||||
|
||||
if (responseMessage.Body == null && responseMessage.BodyAsBytes == null && responseMessage.BodyAsFile == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (responseMessage.BodyAsBytes != null)
|
||||
{
|
||||
await response.Body.WriteAsync(responseMessage.BodyAsBytes, 0, responseMessage.BodyAsBytes.Length);
|
||||
return;
|
||||
}
|
||||
|
||||
if (responseMessage.BodyAsFile != null)
|
||||
{
|
||||
byte[] bytes = File.ReadAllBytes(responseMessage.BodyAsFile);
|
||||
|
||||
await response.Body.WriteAsync(bytes, 0, bytes.Length);
|
||||
return;
|
||||
}
|
||||
|
||||
Encoding encoding = responseMessage.BodyEncoding ?? _utf8NoBom;
|
||||
using (var writer = new StreamWriter(response.Body, encoding))
|
||||
{
|
||||
await writer.WriteAsync(responseMessage.Body);
|
||||
// TODO : response.ContentLength = responseMessage.Body.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,11 +57,14 @@ namespace WireMock.Owin
|
||||
|
||||
private void StartServers()
|
||||
{
|
||||
System.Console.WriteLine("WireMock.Net server using .net 4.5.x or .net 4.6.x");
|
||||
Console.WriteLine("WireMock.Net server using .net 4.5.x or .net 4.6.x");
|
||||
|
||||
Action<IAppBuilder> startup = app =>
|
||||
{
|
||||
app.Use<GlobalExceptionMiddleware>();
|
||||
_options.PreWireMockMiddlewareInit?.Invoke(app);
|
||||
app.Use<WireMockMiddleware>(_options);
|
||||
_options.PostWireMockMiddlewareInit?.Invoke(app);
|
||||
};
|
||||
|
||||
var servers = new List<IDisposable>();
|
||||
|
||||
@@ -4,6 +4,8 @@ using WireMock.Logging;
|
||||
using WireMock.Matchers.Request;
|
||||
using System.Linq;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Util;
|
||||
using Newtonsoft.Json;
|
||||
#if !NETSTANDARD
|
||||
using Microsoft.Owin;
|
||||
#else
|
||||
@@ -50,7 +52,7 @@ namespace WireMock.Owin
|
||||
RequestMatchResult requestMatchResult = null;
|
||||
try
|
||||
{
|
||||
foreach (var mapping in _options.Mappings.Where(m => m.Scenario != null))
|
||||
foreach (var mapping in _options.Mappings.Where(m => m?.Scenario != null))
|
||||
{
|
||||
// Set start
|
||||
if (!_options.Scenarios.ContainsKey(mapping.Scenario) && mapping.IsStartState)
|
||||
@@ -101,8 +103,8 @@ namespace WireMock.Owin
|
||||
|
||||
if (targetMapping.IsAdminInterface && _options.AuthorizationMatcher != null)
|
||||
{
|
||||
bool present = request.Headers.TryGetValue("Authorization", out string authorization);
|
||||
if (!present || _options.AuthorizationMatcher.IsMatch(authorization) < MatchScores.Perfect)
|
||||
bool present = request.Headers.TryGetValue("Authorization", out WireMockList<string> authorization);
|
||||
if (!present || _options.AuthorizationMatcher.IsMatch(authorization.ToString()) < MatchScores.Perfect)
|
||||
{
|
||||
response = new ResponseMessage { StatusCode = 401 };
|
||||
return;
|
||||
@@ -123,7 +125,7 @@ namespace WireMock.Owin
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
response = new ResponseMessage { StatusCode = 500, Body = ex.ToString() };
|
||||
response = new ResponseMessage { StatusCode = 500, Body = JsonConvert.SerializeObject(ex) };
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
@@ -4,6 +4,12 @@ using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Util;
|
||||
#if !NETSTANDARD
|
||||
using Owin;
|
||||
#else
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
#endif
|
||||
|
||||
namespace WireMock.Owin
|
||||
{
|
||||
@@ -17,12 +23,22 @@ namespace WireMock.Owin
|
||||
|
||||
public IList<Mapping> Mappings { get; set; } = new List<Mapping>();
|
||||
|
||||
public ObservableCollection<LogEntry> LogEntries { get; } = new ObservableCollection<LogEntry>();
|
||||
public ObservableCollection<LogEntry> LogEntries { get; } = new ConcurentObservableCollection<LogEntry>();
|
||||
|
||||
public int? RequestLogExpirationDuration { get; set; }
|
||||
|
||||
public int? MaxRequestLogCount { get; set; }
|
||||
|
||||
public IDictionary<string, object> Scenarios { get; } = new ConcurrentDictionary<string, object>();
|
||||
|
||||
#if !NETSTANDARD
|
||||
public Action<IAppBuilder> PreWireMockMiddlewareInit { get; set; }
|
||||
|
||||
public Action<IAppBuilder> PostWireMockMiddlewareInit { get; set; }
|
||||
#else
|
||||
public Action<IApplicationBuilder> PreWireMockMiddlewareInit { get; set; }
|
||||
|
||||
public Action<IApplicationBuilder> PostWireMockMiddlewareInit { get; set; }
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ namespace WireMock.RequestBuilders
|
||||
public interface IHeadersAndCookiesRequestBuilder : IBodyRequestBuilder, IRequestMatcher, IParamsRequestBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// The with header.
|
||||
/// Add Header matching based on name, pattern and ignoreCase.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="pattern">The pattern.</param>
|
||||
@@ -20,6 +20,15 @@ namespace WireMock.RequestBuilders
|
||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||
IRequestBuilder WithHeader([NotNull] string name, string pattern, bool ignoreCase = true);
|
||||
|
||||
/// <summary>
|
||||
/// Add Header matching based on name, patterns and ignoreCase.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="patterns">The patterns.</param>
|
||||
/// <param name="ignoreCase">ignore Case</param>
|
||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||
IRequestBuilder WithHeader([NotNull] string name, string[] patterns, bool ignoreCase = true);
|
||||
|
||||
/// <summary>
|
||||
/// The with header.
|
||||
/// </summary>
|
||||
@@ -33,7 +42,7 @@ namespace WireMock.RequestBuilders
|
||||
/// </summary>
|
||||
/// <param name="funcs">The headers funcs.</param>
|
||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||
IRequestBuilder WithHeader([NotNull] params Func<IDictionary<string, string>, bool>[] funcs);
|
||||
IRequestBuilder WithHeader([NotNull] params Func<IDictionary<string, string[]>, bool>[] funcs);
|
||||
|
||||
/// <summary>
|
||||
/// The with cookie.
|
||||
|
||||
@@ -359,13 +359,7 @@ namespace WireMock.RequestBuilders
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// With header.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="pattern">The pattern.</param>
|
||||
/// <param name="ignoreCase">if set to <c>true</c> [ignore case].</param>
|
||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||
/// <inheritdoc cref="IHeadersAndCookiesRequestBuilder.WithHeader(string,string,bool)"/>
|
||||
public IRequestBuilder WithHeader(string name, string pattern, bool ignoreCase = true)
|
||||
{
|
||||
Check.NotNull(name, nameof(name));
|
||||
@@ -375,6 +369,16 @@ namespace WireMock.RequestBuilders
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IHeadersAndCookiesRequestBuilder.WithHeader(string,string[],bool)"/>
|
||||
public IRequestBuilder WithHeader(string name, string[] patterns, bool ignoreCase = true)
|
||||
{
|
||||
Check.NotNull(name, nameof(name));
|
||||
Check.NotNull(patterns, nameof(patterns));
|
||||
|
||||
_requestMatchers.Add(new RequestMessageHeaderMatcher(name, patterns, ignoreCase));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// With header.
|
||||
/// </summary>
|
||||
@@ -395,7 +399,7 @@ namespace WireMock.RequestBuilders
|
||||
/// </summary>
|
||||
/// <param name="funcs">The funcs.</param>
|
||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||
public IRequestBuilder WithHeader(params Func<IDictionary<string, string>, bool>[] funcs)
|
||||
public IRequestBuilder WithHeader(params Func<IDictionary<string, string[]>, bool>[] funcs)
|
||||
{
|
||||
Check.NotEmpty(funcs, nameof(funcs));
|
||||
|
||||
|
||||
@@ -1,137 +1,170 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Util;
|
||||
using WireMock.Validation;
|
||||
using System.Text;
|
||||
|
||||
namespace WireMock
|
||||
{
|
||||
/// <summary>
|
||||
/// The request.
|
||||
/// </summary>
|
||||
public class RequestMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the Client IP Address.
|
||||
/// </summary>
|
||||
public string ClientIP { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the url.
|
||||
/// </summary>
|
||||
public string Url { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the DateTime.
|
||||
/// </summary>
|
||||
public DateTime DateTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path.
|
||||
/// </summary>
|
||||
public string Path { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the method.
|
||||
/// </summary>
|
||||
public string Method { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the headers.
|
||||
/// </summary>
|
||||
public IDictionary<string, string> Headers { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the cookies.
|
||||
/// </summary>
|
||||
public IDictionary<string, string> Cookies { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the query.
|
||||
/// </summary>
|
||||
public IDictionary<string, WireMockList<string>> Query { get; } = new Dictionary<string, WireMockList<string>>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bodyAsBytes.
|
||||
/// </summary>
|
||||
public byte[] BodyAsBytes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the body.
|
||||
/// </summary>
|
||||
public string Body { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the body encoding.
|
||||
/// </summary>
|
||||
public Encoding BodyEncoding { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="url">The original url.</param>
|
||||
/// <param name="method">The HTTP method.</param>
|
||||
/// <param name="clientIP">The client IP Address.</param>
|
||||
/// <param name="bodyAsBytes">The bodyAsBytes byte[].</param>
|
||||
/// <param name="body">The body string.</param>
|
||||
/// <param name="bodyEncoding">The body encoding</param>
|
||||
/// <param name="headers">The headers.</param>
|
||||
/// <param name="cookies">The cookies.</param>
|
||||
public RequestMessage([NotNull] Uri url, [NotNull] string method, [NotNull] string clientIP, [CanBeNull] byte[] bodyAsBytes = null, [CanBeNull] string body = null, [CanBeNull] Encoding bodyEncoding = null, [CanBeNull] IDictionary<string, string> headers = null, [CanBeNull] IDictionary<string, string> cookies = null)
|
||||
{
|
||||
Check.NotNull(url, nameof(url));
|
||||
Check.NotNull(method, nameof(method));
|
||||
Check.NotNull(clientIP, nameof(clientIP));
|
||||
|
||||
Url = url.ToString();
|
||||
Path = url.AbsolutePath;
|
||||
Method = method.ToLower();
|
||||
ClientIP = clientIP;
|
||||
BodyAsBytes = bodyAsBytes;
|
||||
Body = body;
|
||||
BodyEncoding = bodyEncoding;
|
||||
Headers = headers;
|
||||
Cookies = cookies;
|
||||
|
||||
string query = url.Query;
|
||||
if (!string.IsNullOrEmpty(query))
|
||||
{
|
||||
if (query.StartsWith("?"))
|
||||
{
|
||||
query = query.Substring(1);
|
||||
}
|
||||
|
||||
Query = query.Split('&').Aggregate(
|
||||
new Dictionary<string, WireMockList<string>>(),
|
||||
(dict, term) =>
|
||||
{
|
||||
var parts = term.Split('=');
|
||||
string key = parts[0];
|
||||
if (!dict.ContainsKey(key))
|
||||
{
|
||||
dict.Add(key, new WireMockList<string>());
|
||||
}
|
||||
|
||||
if (parts.Length == 2)
|
||||
{
|
||||
dict[key].Add(parts[1]);
|
||||
}
|
||||
|
||||
return dict;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The get a query parameter.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <returns>The query parameter.</returns>
|
||||
public List<string> GetParameter(string key)
|
||||
{
|
||||
return Query.ContainsKey(key) ? Query[key] : null;
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Util;
|
||||
using WireMock.Validation;
|
||||
using System.Text;
|
||||
|
||||
namespace WireMock
|
||||
{
|
||||
/// <summary>
|
||||
/// The request.
|
||||
/// </summary>
|
||||
public class RequestMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the Client IP Address.
|
||||
/// </summary>
|
||||
public string ClientIP { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the url.
|
||||
/// </summary>
|
||||
public string Url { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the DateTime.
|
||||
/// </summary>
|
||||
public DateTime DateTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path.
|
||||
/// </summary>
|
||||
public string Path { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the method.
|
||||
/// </summary>
|
||||
public string Method { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the headers.
|
||||
/// </summary>
|
||||
public IDictionary<string, WireMockList<string>> Headers { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the cookies.
|
||||
/// </summary>
|
||||
public IDictionary<string, string> Cookies { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the query.
|
||||
/// </summary>
|
||||
public IDictionary<string, WireMockList<string>> Query { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bodyAsBytes.
|
||||
/// </summary>
|
||||
public byte[] BodyAsBytes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the body.
|
||||
/// </summary>
|
||||
public string Body { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Host
|
||||
/// </summary>
|
||||
public string Host { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the protocol
|
||||
/// </summary>
|
||||
public string Protocol { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the port
|
||||
/// </summary>
|
||||
public int Port { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the origin
|
||||
/// </summary>
|
||||
public string Origin { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the body encoding.
|
||||
/// </summary>
|
||||
public Encoding BodyEncoding { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="url">The original url.</param>
|
||||
/// <param name="method">The HTTP method.</param>
|
||||
/// <param name="clientIP">The client IP Address.</param>
|
||||
/// <param name="bodyAsBytes">The bodyAsBytes byte[].</param>
|
||||
/// <param name="body">The body string.</param>
|
||||
/// <param name="bodyEncoding">The body encoding</param>
|
||||
/// <param name="headers">The headers.</param>
|
||||
/// <param name="cookies">The cookies.</param>
|
||||
public RequestMessage([NotNull] Uri url, [NotNull] string method, [NotNull] string clientIP, [CanBeNull] byte[] bodyAsBytes = null, [CanBeNull] string body = null, [CanBeNull] Encoding bodyEncoding = null, [CanBeNull] IDictionary<string, string[]> headers = null, [CanBeNull] IDictionary<string, string> cookies = null)
|
||||
{
|
||||
Check.NotNull(url, nameof(url));
|
||||
Check.NotNull(method, nameof(method));
|
||||
Check.NotNull(clientIP, nameof(clientIP));
|
||||
|
||||
Url = url.ToString();
|
||||
Protocol = url.Scheme;
|
||||
Host = url.Host;
|
||||
Port = url.Port;
|
||||
Origin = $"{url.Scheme}://{url.Host}:{url.Port}";
|
||||
Path = url.AbsolutePath;
|
||||
Method = method.ToLower();
|
||||
ClientIP = clientIP;
|
||||
BodyAsBytes = bodyAsBytes;
|
||||
Body = body;
|
||||
BodyEncoding = bodyEncoding;
|
||||
Headers = headers?.ToDictionary(header => header.Key, header => new WireMockList<string>(header.Value));
|
||||
Cookies = cookies;
|
||||
Query = ParseQuery(url.Query);
|
||||
}
|
||||
|
||||
private IDictionary<string, WireMockList<string>> ParseQuery(string queryString)
|
||||
{
|
||||
if (string.IsNullOrEmpty(queryString))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (queryString.StartsWith("?"))
|
||||
{
|
||||
queryString = queryString.Substring(1);
|
||||
}
|
||||
|
||||
return queryString.Split('&').Aggregate(new Dictionary<string, WireMockList<string>>(),
|
||||
(dict, term) =>
|
||||
{
|
||||
var parts = term.Split('=');
|
||||
string key = parts[0];
|
||||
if (!dict.ContainsKey(key))
|
||||
{
|
||||
dict.Add(key, new WireMockList<string>());
|
||||
}
|
||||
|
||||
if (parts.Length == 2)
|
||||
{
|
||||
dict[key].Add(parts[1]);
|
||||
}
|
||||
|
||||
return dict;
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The get a query parameter.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <returns>The query parameter.</returns>
|
||||
public List<string> GetParameter(string key)
|
||||
{
|
||||
if (Query == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return Query.ContainsKey(key) ? Query[key] : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
23
src/WireMock.Net/ResponseBuilders/BodyDestinationFormat.cs
Normal file
23
src/WireMock.Net/ResponseBuilders/BodyDestinationFormat.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
namespace WireMock.ResponseBuilders
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the BodyDestinationFormat
|
||||
/// </summary>
|
||||
public static class BodyDestinationFormat
|
||||
{
|
||||
/// <summary>
|
||||
/// Same as source (no conversion)
|
||||
/// </summary>
|
||||
public const string SameAsSource = "SameAsSource";
|
||||
|
||||
/// <summary>
|
||||
/// Convert to string
|
||||
/// </summary>
|
||||
public const string String = "String";
|
||||
|
||||
/// <summary>
|
||||
/// Convert to bytes
|
||||
/// </summary>
|
||||
public const string Bytes = "Bytes";
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Text;
|
||||
using System;
|
||||
using System.Text;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace WireMock.ResponseBuilders
|
||||
@@ -9,15 +10,25 @@ namespace WireMock.ResponseBuilders
|
||||
public interface IBodyResponseBuilder : ITransformResponseBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// The with body.
|
||||
/// WithBody : Create a ... response based on a string.
|
||||
/// </summary>
|
||||
/// <param name="body">The body.</param>
|
||||
/// <param name="destination">The Body Destination format (SameAsSource, String or Bytes).</param>
|
||||
/// <param name="encoding">The body encoding.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithBody([NotNull] string body, [CanBeNull] Encoding encoding = null);
|
||||
IResponseBuilder WithBody([NotNull] string body, [CanBeNull] string destination = BodyDestinationFormat.SameAsSource, [CanBeNull] Encoding encoding = null);
|
||||
|
||||
/// <summary>
|
||||
/// The with body as Json.
|
||||
/// WithBody : Create a ... response based on a bytearray.
|
||||
/// </summary>
|
||||
/// <param name="body">The body.</param>
|
||||
/// <param name="destination">The Body Destination format (SameAsSource, String or Bytes).</param>
|
||||
/// <param name="encoding">The body encoding.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithBody([NotNull] byte[] body, [CanBeNull] string destination = BodyDestinationFormat.SameAsSource, [CanBeNull] Encoding encoding = null);
|
||||
|
||||
/// <summary>
|
||||
/// WithBody : Create a string response based on a object (which will be converted to a JSON string).
|
||||
/// </summary>
|
||||
/// <param name="body">The body.</param>
|
||||
/// <param name="encoding">The body encoding.</param>
|
||||
@@ -25,11 +36,20 @@ namespace WireMock.ResponseBuilders
|
||||
IResponseBuilder WithBodyAsJson([NotNull] object body, [CanBeNull] Encoding encoding = null);
|
||||
|
||||
/// <summary>
|
||||
/// The with body as base64.
|
||||
/// WithBody : Create a string response based on a Base64 string (which will be decoded to a normal string).
|
||||
/// </summary>
|
||||
/// <param name="bodyAsbase64">The body asbase64.</param>
|
||||
/// <param name="bodyAsbase64">The body.</param>
|
||||
/// <param name="encoding">The Encoding.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithBodyAsBase64([NotNull] string bodyAsbase64, [CanBeNull] Encoding encoding = null);
|
||||
[Obsolete]
|
||||
IResponseBuilder WithBodyFromBase64([NotNull] string bodyAsbase64, [CanBeNull] Encoding encoding = null);
|
||||
|
||||
/// <summary>
|
||||
/// WithBodyFromFile : Create a ... response based on a File.
|
||||
/// </summary>
|
||||
/// <param name="filename">The filename.</param>
|
||||
/// <param name="cache">Defines if this file is cached in memory or retrieved from disk everytime the response is created.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithBodyFromFile([NotNull] string filename, bool cache = true);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.ResponseBuilders
|
||||
{
|
||||
@@ -12,15 +13,29 @@ namespace WireMock.ResponseBuilders
|
||||
/// The with header.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="values">The values.</param>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithHeader([NotNull] string name, string value);
|
||||
IResponseBuilder WithHeader([NotNull] string name, params string[] values);
|
||||
|
||||
/// <summary>
|
||||
/// The with headers.
|
||||
/// </summary>
|
||||
/// <param name="headers">The headers.</param>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithHeaders([NotNull] IDictionary<string,string> headers);
|
||||
IResponseBuilder WithHeaders([NotNull] IDictionary<string, string> headers);
|
||||
|
||||
/// <summary>
|
||||
/// The with headers.
|
||||
/// </summary>
|
||||
/// <param name="headers">The headers.</param>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithHeaders([NotNull] IDictionary<string, string[]> headers);
|
||||
|
||||
/// <summary>
|
||||
/// The with headers.
|
||||
/// </summary>
|
||||
/// <param name="headers">The headers.</param>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithHeaders([NotNull] IDictionary<string, WireMockList<string>> headers);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json;
|
||||
using WireMock.Validation;
|
||||
using WireMock.Http;
|
||||
using WireMock.Transformers;
|
||||
using WireMock.Util;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock.ResponseBuilders
|
||||
{
|
||||
@@ -16,6 +20,8 @@ namespace WireMock.ResponseBuilders
|
||||
/// </summary>
|
||||
public class Response : IResponseBuilder
|
||||
{
|
||||
private HttpClient httpClientForProxy;
|
||||
|
||||
/// <summary>
|
||||
/// The delay
|
||||
/// </summary>
|
||||
@@ -125,53 +131,117 @@ namespace WireMock.ResponseBuilders
|
||||
return WithStatusCode((int)HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The with header.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
public IResponseBuilder WithHeader(string name, string value)
|
||||
/// <inheritdoc cref="IHeadersResponseBuilder.WithHeader(string, string[])"/>
|
||||
public IResponseBuilder WithHeader(string name, params string[] values)
|
||||
{
|
||||
Check.NotNull(name, nameof(name));
|
||||
|
||||
ResponseMessage.AddHeader(name, value);
|
||||
ResponseMessage.AddHeader(name, values);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The with headers.
|
||||
/// </summary>
|
||||
/// <param name="headers">The headers.</param>
|
||||
/// <returns></returns>
|
||||
/// <inheritdoc cref="IHeadersResponseBuilder.WithHeaders(IDictionary{string, string})"/>
|
||||
public IResponseBuilder WithHeaders(IDictionary<string, string> headers)
|
||||
{
|
||||
Check.NotNull(headers, nameof(headers));
|
||||
|
||||
ResponseMessage.Headers = headers.ToDictionary(header => header.Key, header => new WireMockList<string>(header.Value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IHeadersResponseBuilder.WithHeaders(IDictionary{string, string[]})"/>
|
||||
public IResponseBuilder WithHeaders(IDictionary<string, string[]> headers)
|
||||
{
|
||||
Check.NotNull(headers, nameof(headers));
|
||||
|
||||
ResponseMessage.Headers = headers.ToDictionary(header => header.Key, header => new WireMockList<string>(header.Value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IHeadersResponseBuilder.WithHeaders(IDictionary{string, WireMockList{string}})"/>
|
||||
public IResponseBuilder WithHeaders(IDictionary<string, WireMockList<string>> headers)
|
||||
{
|
||||
ResponseMessage.Headers = headers;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The with body.
|
||||
/// </summary>
|
||||
/// <param name="body">The body.</param>
|
||||
/// <param name="encoding">The body encoding.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
public IResponseBuilder WithBody(string body, Encoding encoding = null)
|
||||
/// <inheritdoc cref="IBodyResponseBuilder.WithBody(byte[], string, Encoding)"/>
|
||||
public IResponseBuilder WithBody(byte[] body, string destination, Encoding encoding = null)
|
||||
{
|
||||
Check.NotNull(body, nameof(body));
|
||||
|
||||
ResponseMessage.Body = body;
|
||||
ResponseMessage.BodyEncoding = encoding ?? Encoding.UTF8;
|
||||
ResponseMessage.BodyDestination = destination;
|
||||
|
||||
switch (destination)
|
||||
{
|
||||
case BodyDestinationFormat.String:
|
||||
var enc = encoding ?? Encoding.UTF8;
|
||||
ResponseMessage.BodyAsBytes = null;
|
||||
ResponseMessage.Body = enc.GetString(body);
|
||||
ResponseMessage.BodyEncoding = enc;
|
||||
break;
|
||||
|
||||
default:
|
||||
ResponseMessage.BodyAsBytes = body;
|
||||
ResponseMessage.BodyEncoding = null;
|
||||
break;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The with body (AsJson object).
|
||||
/// </summary>
|
||||
/// <param name="body">The body.</param>
|
||||
/// <param name="encoding">The body encoding.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
/// <inheritdoc cref="IBodyResponseBuilder.WithBodyFromFile"/>
|
||||
public IResponseBuilder WithBodyFromFile(string filename, bool cache = true)
|
||||
{
|
||||
Check.NotNull(filename, nameof(filename));
|
||||
|
||||
ResponseMessage.BodyEncoding = null;
|
||||
ResponseMessage.BodyAsFileIsCached = cache;
|
||||
|
||||
if (cache)
|
||||
{
|
||||
ResponseMessage.Body = null;
|
||||
ResponseMessage.BodyAsBytes = File.ReadAllBytes(filename);
|
||||
ResponseMessage.BodyAsFile = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
ResponseMessage.Body = null;
|
||||
ResponseMessage.BodyAsBytes = null;
|
||||
ResponseMessage.BodyAsFile = filename;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IBodyResponseBuilder.WithBody(string, string, Encoding)"/>
|
||||
public IResponseBuilder WithBody(string body, string destination = BodyDestinationFormat.SameAsSource, Encoding encoding = null)
|
||||
{
|
||||
Check.NotNull(body, nameof(body));
|
||||
|
||||
encoding = encoding ?? Encoding.UTF8;
|
||||
|
||||
ResponseMessage.BodyDestination = destination;
|
||||
|
||||
switch (destination)
|
||||
{
|
||||
case BodyDestinationFormat.Bytes:
|
||||
ResponseMessage.Body = null;
|
||||
ResponseMessage.BodyAsBytes = encoding.GetBytes(body);
|
||||
ResponseMessage.BodyEncoding = encoding;
|
||||
break;
|
||||
|
||||
default:
|
||||
ResponseMessage.Body = body;
|
||||
ResponseMessage.BodyAsBytes = null;
|
||||
ResponseMessage.BodyEncoding = encoding;
|
||||
break;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IBodyResponseBuilder.WithBodyAsJson"/>
|
||||
public IResponseBuilder WithBodyAsJson(object body, Encoding encoding = null)
|
||||
{
|
||||
Check.NotNull(body, nameof(body));
|
||||
@@ -184,23 +254,20 @@ namespace WireMock.ResponseBuilders
|
||||
ResponseMessage.BodyEncoding = encoding;
|
||||
}
|
||||
|
||||
ResponseMessage.BodyDestination = null;
|
||||
ResponseMessage.Body = jsonBody;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The with body as base64.
|
||||
/// </summary>
|
||||
/// <param name="bodyAsbase64">The body asbase64.</param>
|
||||
/// <param name="encoding">The Encoding.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
public IResponseBuilder WithBodyAsBase64(string bodyAsbase64, Encoding encoding = null)
|
||||
/// <inheritdoc cref="IBodyResponseBuilder.WithBodyFromBase64"/>
|
||||
public IResponseBuilder WithBodyFromBase64(string bodyAsbase64, Encoding encoding = null)
|
||||
{
|
||||
Check.NotNull(bodyAsbase64, nameof(bodyAsbase64));
|
||||
|
||||
encoding = encoding ?? Encoding.UTF8;
|
||||
|
||||
ResponseMessage.BodyDestination = null;
|
||||
ResponseMessage.Body = encoding.GetString(Convert.FromBase64String(bodyAsbase64));
|
||||
ResponseMessage.BodyEncoding = encoding;
|
||||
|
||||
@@ -253,6 +320,7 @@ namespace WireMock.ResponseBuilders
|
||||
|
||||
ProxyUrl = proxyUrl;
|
||||
X509Certificate2ThumbprintOrSubjectName = clientX509Certificate2ThumbprintOrSubjectName;
|
||||
httpClientForProxy = HttpClientHelper.CreateHttpClient(clientX509Certificate2ThumbprintOrSubjectName);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -268,12 +336,12 @@ namespace WireMock.ResponseBuilders
|
||||
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)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using WireMock.Util;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock
|
||||
{
|
||||
@@ -12,7 +15,7 @@ namespace WireMock
|
||||
/// <summary>
|
||||
/// Gets the headers.
|
||||
/// </summary>
|
||||
public IDictionary<string, string> Headers { get; set; } = new ConcurrentDictionary<string, string>();
|
||||
public IDictionary<string, WireMockList<string>> Headers { get; set; } = new ConcurrentDictionary<string, WireMockList<string>>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the status code.
|
||||
@@ -25,27 +28,59 @@ namespace WireMock
|
||||
public string BodyOriginal { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the body.
|
||||
/// Gets or sets the body destination (SameAsSource, String or Bytes).
|
||||
/// </summary>
|
||||
public string BodyDestination { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the body as a string.
|
||||
/// </summary>
|
||||
public string Body { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the body as bytes.
|
||||
/// </summary>
|
||||
public byte[] BodyAsBytes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the body as a file.
|
||||
/// </summary>
|
||||
public string BodyAsFile { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Is the body as file cached?
|
||||
/// </summary>
|
||||
public bool? BodyAsFileIsCached { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the body encoding.
|
||||
/// </summary>
|
||||
public Encoding BodyEncoding { get; set; } = new UTF8Encoding(false);
|
||||
|
||||
/// <summary>
|
||||
/// The add header.
|
||||
/// Adds the header.
|
||||
/// </summary>
|
||||
/// <param name="name">
|
||||
/// The name.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// The value.
|
||||
/// </param>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
public void AddHeader(string name, string value)
|
||||
{
|
||||
Headers.Add(name, value);
|
||||
Headers.Add(name, new WireMockList<string>(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the header.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="values">The values.</param>
|
||||
public void AddHeader(string name, params string[] values)
|
||||
{
|
||||
Check.NotEmpty(values, nameof(values));
|
||||
|
||||
var newHeaderValues = Headers.TryGetValue(name, out WireMockList<string> existingValues)
|
||||
? values.Union(existingValues).ToArray()
|
||||
: values;
|
||||
|
||||
Headers[name] = new WireMockList<string>(newHeaderValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ using WireMock.Matchers;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Serialization
|
||||
{
|
||||
@@ -78,7 +79,7 @@ namespace WireMock.Serialization
|
||||
Funcs = Map(pm.Funcs)
|
||||
}).ToList() : null,
|
||||
|
||||
Body = methodMatcher?.Methods != null && methodMatcher.Methods.Count(m => m == "get") == 1 ? null : new BodyModel
|
||||
Body = methodMatcher?.Methods != null && methodMatcher.Methods.Any(m => m == "get") ? null : new BodyModel
|
||||
{
|
||||
Matcher = bodyMatcher != null ? Map(bodyMatcher.Matcher) : null,
|
||||
Func = bodyMatcher != null ? Map(bodyMatcher.Func) : null,
|
||||
@@ -95,31 +96,58 @@ namespace WireMock.Serialization
|
||||
{
|
||||
mappingModel.Response.StatusCode = null;
|
||||
mappingModel.Response.Headers = null;
|
||||
mappingModel.Response.BodyDestination = null;
|
||||
mappingModel.Response.Body = null;
|
||||
mappingModel.Response.BodyAsBytes = null;
|
||||
mappingModel.Response.BodyAsFile = null;
|
||||
mappingModel.Response.BodyAsFileIsCached = null;
|
||||
mappingModel.Response.UseTransformer = false;
|
||||
mappingModel.Response.BodyEncoding = null;
|
||||
mappingModel.Response.ProxyUrl = response.ProxyUrl;
|
||||
}
|
||||
else
|
||||
{
|
||||
mappingModel.Response.BodyDestination = response.ResponseMessage.BodyDestination;
|
||||
mappingModel.Response.StatusCode = response.ResponseMessage.StatusCode;
|
||||
mappingModel.Response.Headers = response.ResponseMessage.Headers;
|
||||
mappingModel.Response.Headers = Map(response.ResponseMessage.Headers);
|
||||
mappingModel.Response.Body = response.ResponseMessage.Body;
|
||||
mappingModel.Response.BodyAsBytes = response.ResponseMessage.BodyAsBytes;
|
||||
mappingModel.Response.BodyAsFile = response.ResponseMessage.BodyAsFile;
|
||||
mappingModel.Response.BodyAsFileIsCached = response.ResponseMessage.BodyAsFileIsCached;
|
||||
mappingModel.Response.UseTransformer = response.UseTransformer;
|
||||
mappingModel.Response.BodyEncoding = response.ResponseMessage.BodyEncoding != null
|
||||
? new EncodingModel
|
||||
|
||||
if (response.ResponseMessage.BodyEncoding != null)
|
||||
{
|
||||
mappingModel.Response.BodyEncoding = new EncodingModel
|
||||
{
|
||||
EncodingName = response.ResponseMessage.BodyEncoding.EncodingName,
|
||||
CodePage = response.ResponseMessage.BodyEncoding.CodePage,
|
||||
WebName = response.ResponseMessage.BodyEncoding.WebName
|
||||
}
|
||||
: null;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return mappingModel;
|
||||
}
|
||||
|
||||
public static MatcherModel[] Map([CanBeNull] IEnumerable<IMatcher> matchers)
|
||||
private static IDictionary<string, object> Map(IDictionary<string, WireMockList<string>> dictionary)
|
||||
{
|
||||
if (dictionary == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var newDictionary = new Dictionary<string, object>();
|
||||
foreach (var entry in dictionary)
|
||||
{
|
||||
object value = entry.Value.Count == 1 ? (object)entry.Value.ToString() : entry.Value;
|
||||
newDictionary.Add(entry.Key, value);
|
||||
}
|
||||
|
||||
return newDictionary;
|
||||
}
|
||||
|
||||
private static MatcherModel[] Map([CanBeNull] IEnumerable<IMatcher> matchers)
|
||||
{
|
||||
if (matchers == null || !matchers.Any())
|
||||
return null;
|
||||
@@ -127,7 +155,7 @@ namespace WireMock.Serialization
|
||||
return matchers.Select(Map).Where(x => x != null).ToArray();
|
||||
}
|
||||
|
||||
public static MatcherModel Map([CanBeNull] IMatcher matcher)
|
||||
private static MatcherModel Map([CanBeNull] IMatcher matcher)
|
||||
{
|
||||
if (matcher == null)
|
||||
return null;
|
||||
@@ -142,7 +170,7 @@ namespace WireMock.Serialization
|
||||
};
|
||||
}
|
||||
|
||||
public static string[] Map<T>([CanBeNull] IEnumerable<Func<T, bool>> funcs)
|
||||
private static string[] Map<T>([CanBeNull] IEnumerable<Func<T, bool>> funcs)
|
||||
{
|
||||
if (funcs == null || !funcs.Any())
|
||||
return null;
|
||||
@@ -150,7 +178,7 @@ namespace WireMock.Serialization
|
||||
return funcs.Select(Map).Where(x => x != null).ToArray();
|
||||
}
|
||||
|
||||
public static string Map<T>([CanBeNull] Func<T, bool> func)
|
||||
private static string Map<T>([CanBeNull] Func<T, bool> func)
|
||||
{
|
||||
return func?.ToString();
|
||||
}
|
||||
|
||||
@@ -2,23 +2,24 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json;
|
||||
using WireMock.Admin.Mappings;
|
||||
using WireMock.Admin.Requests;
|
||||
using WireMock.Admin.Settings;
|
||||
using WireMock.Http;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Serialization;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Util;
|
||||
using WireMock.Validation;
|
||||
using WireMock.Http;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Serialization;
|
||||
|
||||
namespace WireMock.Server
|
||||
{
|
||||
@@ -129,8 +130,11 @@ namespace WireMock.Server
|
||||
}
|
||||
|
||||
#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,12 +144,17 @@ namespace WireMock.Server
|
||||
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)
|
||||
{
|
||||
var mapping = ToMapping(requestMessage, responseMessage);
|
||||
SaveMappingToFile(mapping);
|
||||
_options.Mappings.Add(mapping);
|
||||
|
||||
if (settings.SaveMappingToFile)
|
||||
{
|
||||
SaveMappingToFile(mapping);
|
||||
}
|
||||
}
|
||||
|
||||
return responseMessage;
|
||||
@@ -153,11 +162,20 @@ namespace WireMock.Server
|
||||
|
||||
private Mapping ToMapping(RequestMessage requestMessage, ResponseMessage responseMessage)
|
||||
{
|
||||
var request = (Request)Request.Create();
|
||||
var request = Request.Create();
|
||||
request.WithPath(requestMessage.Path);
|
||||
request.UsingVerb(requestMessage.Method);
|
||||
|
||||
var response = (Response)Response.Create(responseMessage);
|
||||
requestMessage.Query.Loop((key, value) => request.WithParam(key, value.ToArray()));
|
||||
requestMessage.Headers.Loop((key, value) => request.WithHeader(key, value.ToArray()));
|
||||
requestMessage.Cookies.Loop((key, value) => request.WithCookie(key, value));
|
||||
|
||||
if (requestMessage.Body != null)
|
||||
{
|
||||
request.WithBody(new ExactMatcher(requestMessage.Body));
|
||||
}
|
||||
|
||||
var response = Response.Create(responseMessage);
|
||||
|
||||
return new Mapping(Guid.NewGuid(), string.Empty, request, response, 0, null, null, null);
|
||||
}
|
||||
@@ -412,8 +430,12 @@ namespace WireMock.Server
|
||||
Response = new LogResponseModel
|
||||
{
|
||||
StatusCode = logEntry.ResponseMessage.StatusCode,
|
||||
BodyDestination = logEntry.ResponseMessage.BodyDestination,
|
||||
Body = logEntry.ResponseMessage.Body,
|
||||
BodyAsBytes = logEntry.ResponseMessage.BodyAsBytes,
|
||||
BodyOriginal = logEntry.ResponseMessage.BodyOriginal,
|
||||
BodyAsFile = logEntry.ResponseMessage.BodyAsFile,
|
||||
BodyAsFileIsCached = logEntry.ResponseMessage.BodyAsFileIsCached,
|
||||
Headers = logEntry.ResponseMessage.Headers,
|
||||
BodyEncoding = logEntry.ResponseMessage.BodyEncoding != null ? new EncodingModel
|
||||
{
|
||||
@@ -515,12 +537,16 @@ namespace WireMock.Server
|
||||
{
|
||||
string path = requestModel.Path as string;
|
||||
if (path != null)
|
||||
{
|
||||
requestBuilder = requestBuilder.WithPath(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
var pathModel = JsonUtils.ParseJTokenToObject<PathModel>(requestModel.Path);
|
||||
if (pathModel?.Matchers != null)
|
||||
{
|
||||
requestBuilder = requestBuilder.WithPath(pathModel.Matchers.Select(MappingConverter.Map).ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -528,17 +554,23 @@ namespace WireMock.Server
|
||||
{
|
||||
string url = requestModel.Url as string;
|
||||
if (url != null)
|
||||
{
|
||||
requestBuilder = requestBuilder.WithUrl(url);
|
||||
}
|
||||
else
|
||||
{
|
||||
var urlModel = JsonUtils.ParseJTokenToObject<UrlModel>(requestModel.Url);
|
||||
if (urlModel?.Matchers != null)
|
||||
{
|
||||
requestBuilder = requestBuilder.WithUrl(urlModel.Matchers.Select(MappingConverter.Map).ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (requestModel.Methods != null)
|
||||
{
|
||||
requestBuilder = requestBuilder.UsingVerb(requestModel.Methods);
|
||||
}
|
||||
|
||||
if (requestModel.Headers != null)
|
||||
{
|
||||
@@ -599,7 +631,12 @@ namespace WireMock.Server
|
||||
|
||||
if (responseModel.Headers != null)
|
||||
{
|
||||
responseBuilder = responseBuilder.WithHeaders(responseModel.Headers);
|
||||
foreach (var entry in responseModel.Headers)
|
||||
{
|
||||
responseBuilder = entry.Value is string value ?
|
||||
responseBuilder.WithHeader(entry.Key, value) :
|
||||
responseBuilder.WithHeader(entry.Key, JsonUtils.ParseJTokenToObject<string[]>(entry.Value));
|
||||
}
|
||||
}
|
||||
else if (responseModel.HeadersRaw != null)
|
||||
{
|
||||
@@ -612,17 +649,21 @@ namespace WireMock.Server
|
||||
}
|
||||
}
|
||||
|
||||
if (responseModel.Body != null)
|
||||
if (responseModel.BodyAsBytes != null)
|
||||
{
|
||||
responseBuilder = responseBuilder.WithBody(responseModel.Body, ToEncoding(responseModel.BodyEncoding));
|
||||
responseBuilder = responseBuilder.WithBody(responseModel.BodyAsBytes, responseModel.BodyDestination, ToEncoding(responseModel.BodyEncoding));
|
||||
}
|
||||
else if (responseModel.Body != null)
|
||||
{
|
||||
responseBuilder = responseBuilder.WithBody(responseModel.Body, responseModel.BodyDestination, ToEncoding(responseModel.BodyEncoding));
|
||||
}
|
||||
else if (responseModel.BodyAsJson != null)
|
||||
{
|
||||
responseBuilder = responseBuilder.WithBodyAsJson(responseModel.BodyAsJson, ToEncoding(responseModel.BodyEncoding));
|
||||
}
|
||||
else if (responseModel.BodyAsBase64 != null)
|
||||
else if (responseModel.BodyFromBase64 != null)
|
||||
{
|
||||
responseBuilder = responseBuilder.WithBodyAsBase64(responseModel.BodyAsBase64, ToEncoding(responseModel.BodyEncoding));
|
||||
responseBuilder = responseBuilder.WithBodyFromBase64(responseModel.BodyFromBase64, ToEncoding(responseModel.BodyEncoding));
|
||||
}
|
||||
|
||||
if (responseModel.UseTransformer)
|
||||
@@ -639,7 +680,7 @@ namespace WireMock.Server
|
||||
{
|
||||
Body = JsonConvert.SerializeObject(result, _settings),
|
||||
StatusCode = 200,
|
||||
Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } }
|
||||
Headers = new Dictionary<string, WireMockList<string>> { { "Content-Type", new WireMockList<string>("application/json") } }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -162,6 +162,9 @@ namespace WireMock.Server
|
||||
Urls = new[] { (settings.UseSSL == true ? "https" : "http") + "://localhost:" + port + "/" };
|
||||
}
|
||||
|
||||
_options.PreWireMockMiddlewareInit = settings.PreWireMockMiddlewareInit;
|
||||
_options.PostWireMockMiddlewareInit = settings.PostWireMockMiddlewareInit;
|
||||
|
||||
#if NETSTANDARD
|
||||
_httpServer = new AspNetCoreSelfHost(_options, Urls);
|
||||
#else
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
namespace WireMock.Settings
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace WireMock.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// FluentMockServerSettings
|
||||
@@ -8,76 +11,87 @@
|
||||
/// <summary>
|
||||
/// Gets or sets the port.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The port.
|
||||
/// </value>
|
||||
[PublicAPI]
|
||||
public int? Port { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the use SSL.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The use SSL.
|
||||
/// </value>
|
||||
// ReSharper disable once InconsistentNaming
|
||||
[PublicAPI]
|
||||
public bool? UseSSL { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the start admin interface.
|
||||
/// Gets or sets wether to start admin interface.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The start admin interface.
|
||||
/// </value>
|
||||
[PublicAPI]
|
||||
public bool? StartAdminInterface { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if the static mappings should be read at startup.
|
||||
/// </summary>
|
||||
/// <value>true/false</value>
|
||||
[PublicAPI]
|
||||
public bool? ReadStaticMappings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if the server should record and save requests and responses.
|
||||
/// </summary>
|
||||
/// <value>true/false</value>
|
||||
[PublicAPI]
|
||||
public ProxyAndRecordSettings ProxyAndRecordSettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the urls.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The urls.
|
||||
/// </value>
|
||||
[PublicAPI]
|
||||
public string[] Urls { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// StartTimeout
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public int StartTimeout { get; set; } = 10000;
|
||||
|
||||
/// <summary>
|
||||
/// Allow Partial Mapping (default set to false).
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public bool? AllowPartialMapping { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The username needed for __admin access.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public string AdminUsername { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The password needed for __admin access.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public string AdminPassword { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The RequestLog expiration in hours (optional).
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public int? RequestLogExpirationDuration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The MaxRequestLog count (optional).
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public int? MaxRequestLogCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Action which is called (with the IAppBuilder or IApplicationBuilder) before the internal WireMockMiddleware is initialized. [Optional]
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public Action<object> PreWireMockMiddlewareInit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Action which is called (with the IAppBuilder or IApplicationBuilder) after the internal WireMockMiddleware is initialized. [Optional]
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public Action<object> PostWireMockMiddlewareInit { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -11,10 +11,15 @@
|
||||
public string Url { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Save the mapping for each request/response.
|
||||
/// Save the mapping for each request/response to the internal Mappings.
|
||||
/// </summary>
|
||||
public bool SaveMapping { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Save the mapping for each request/response to also file. (Note that SaveMapping must also be set to true.)
|
||||
/// </summary>
|
||||
public bool SaveMappingToFile { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// The clientCertificate thumbprint or subject name fragment to use. Example thumbprint : "D2DBF135A8D06ACCD0E1FAD9BFB28678DF7A9818". Example subject name: "www.google.com""
|
||||
/// </summary>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using HandlebarsDotNet;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using HandlebarsDotNet;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Transformers
|
||||
{
|
||||
@@ -16,13 +18,16 @@ namespace WireMock.Transformers
|
||||
responseMessage.Body = templateBody(template);
|
||||
|
||||
// Headers
|
||||
var newHeaders = new Dictionary<string, string>();
|
||||
var newHeaders = new Dictionary<string, WireMockList<string>>();
|
||||
foreach (var header in original.Headers)
|
||||
{
|
||||
var templateHeaderKey = Handlebars.Compile(header.Key);
|
||||
var templateHeaderValue = Handlebars.Compile(header.Value);
|
||||
var templateHeaderValues = header.Value
|
||||
.Select(Handlebars.Compile)
|
||||
.Select(func => func(template))
|
||||
.ToArray();
|
||||
|
||||
newHeaders.Add(templateHeaderKey(template), templateHeaderValue(template));
|
||||
newHeaders.Add(templateHeaderKey(template), new WireMockList<string>(templateHeaderValues));
|
||||
}
|
||||
|
||||
responseMessage.Headers = newHeaders;
|
||||
|
||||
77
src/WireMock.Net/Util/ConcurentObservableCollection.cs
Normal file
77
src/WireMock.Net/Util/ConcurentObservableCollection.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace WireMock.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// A special Collection that overrides methods of <see cref="ObservableCollection{T}"/> to make them thread safe
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of elements in the collection.</typeparam>
|
||||
/// <inheritdoc cref="ObservableCollection{T}" />
|
||||
public class ConcurentObservableCollection<T> : ObservableCollection<T>
|
||||
{
|
||||
private readonly object _lockObject = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:WireMock.Util.ConcurentObservableCollection`1" /> class.
|
||||
/// </summary>
|
||||
public ConcurentObservableCollection() { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ConcurentObservableCollection{T}"/> class that contains elements copied from the specified list.
|
||||
/// </summary>
|
||||
/// <param name="list">The list from which the elements are copied.</param>
|
||||
public ConcurentObservableCollection(List<T> list) : base(list) { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ConcurentObservableCollection{T}"/> class that contains elements copied from the specified collection.
|
||||
/// </summary>
|
||||
/// <param name="collection">The collection from which the elements are copied.</param>
|
||||
public ConcurentObservableCollection(IEnumerable<T> collection) : base(collection) { }
|
||||
|
||||
/// <inheritdoc cref="ObservableCollection{T}.ClearItems"/>
|
||||
protected override void ClearItems()
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
base.ClearItems();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ObservableCollection{T}.RemoveItem"/>
|
||||
protected override void RemoveItem(int index)
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
base.RemoveItem(index);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ObservableCollection{T}.InsertItem"/>
|
||||
protected override void InsertItem(int index, T item)
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
base.InsertItem(index, item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ObservableCollection{T}.SetItem"/>
|
||||
protected override void SetItem(int index, T item)
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
base.SetItem(index, item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ObservableCollection{T}.MoveItem"/>
|
||||
protected override void MoveItem(int oldIndex, int newIndex)
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
base.MoveItem(oldIndex, newIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
33
src/WireMock.Net/Util/DictionaryExtensions.cs
Normal file
33
src/WireMock.Net/Util/DictionaryExtensions.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Some IDictionary Extensions
|
||||
/// </summary>
|
||||
public static class DictionaryExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Loops the dictionary and executes the specified action.
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">The type of the key.</typeparam>
|
||||
/// <typeparam name="TValue">The type of the value.</typeparam>
|
||||
/// <param name="dictionary">The dictionary to loop (can be null).</param>
|
||||
/// <param name="action">The action.</param>
|
||||
public static void Loop<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, [NotNull] Action<TKey, TValue> action)
|
||||
{
|
||||
Check.NotNull(action, nameof(action));
|
||||
|
||||
if (dictionary != null)
|
||||
{
|
||||
foreach (var entry in dictionary)
|
||||
{
|
||||
action(entry.Key, entry.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,13 +7,12 @@ namespace WireMock.Util
|
||||
public static T ParseJTokenToObject<T>(object value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
|
||||
JToken token = value as JToken;
|
||||
if (token == null)
|
||||
return default(T);
|
||||
|
||||
return token.ToObject<T>();
|
||||
var token = value as JToken;
|
||||
return token == null ? default(T) : token.ToObject<T>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,8 +74,7 @@ namespace WireMock.Util
|
||||
|
||||
public void RemoveLock(string name)
|
||||
{
|
||||
ReaderWriterLockSlim o;
|
||||
_lockDict.TryRemove(name, out o);
|
||||
_lockDict.TryRemove(name, out _);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,9 +36,6 @@ namespace WireMock.Util
|
||||
/// <summary>
|
||||
/// Returns a <see cref="string" /> that represents this instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="string" /> that represents this instance.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
if (this != null && this.Any())
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<Description>Lightweight Http Mocking Server for .Net, inspired by WireMock from the Java landscape.</Description>
|
||||
<AssemblyTitle>WireMock.Net</AssemblyTitle>
|
||||
<Version>1.0.2.4</Version>
|
||||
<Version>1.0.2.7</Version>
|
||||
<Authors>Alexandre Victoor;Stef Heyenrath</Authors>
|
||||
<TargetFrameworks>net452;net46;netstandard1.3;netstandard2.0</TargetFrameworks>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,417 +1,417 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using NFluent;
|
||||
using Xunit;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Server;
|
||||
|
||||
namespace WireMock.Net.Tests
|
||||
{
|
||||
//[TestFixture]
|
||||
//[Timeout(5000)]
|
||||
public class FluentMockServerTests : IDisposable
|
||||
{
|
||||
private FluentMockServer _server;
|
||||
|
||||
// For for AppVeyor + OpenCover
|
||||
private string GetCurrentFolder()
|
||||
{
|
||||
string current = Directory.GetCurrentDirectory();
|
||||
//if (!current.EndsWith("WireMock.Net.Tests"))
|
||||
// return Path.Combine(current, "test", "WireMock.Net.Tests");
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FluentMockServer_StartStop()
|
||||
{
|
||||
var server1 = FluentMockServer.Start("http://localhost:9091/");
|
||||
server1.Stop();
|
||||
|
||||
var server2 = FluentMockServer.Start("http://localhost:9091/");
|
||||
server2.Stop();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FluentMockServer_ReadStaticMapping_WithNonGuidFilename()
|
||||
{
|
||||
var guid = Guid.Parse("04ee4872-9efd-4770-90d3-88d445265d0d");
|
||||
string title = "documentdb_root_title";
|
||||
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
string folder = Path.Combine(GetCurrentFolder(), "__admin", "mappings", "documentdb_root.json");
|
||||
_server.ReadStaticMapping(folder);
|
||||
|
||||
var mappings = _server.Mappings.ToArray();
|
||||
Check.That(mappings).HasSize(1);
|
||||
|
||||
Check.That(mappings.First().RequestMatcher).IsNotNull();
|
||||
Check.That(mappings.First().Provider).IsNotNull();
|
||||
Check.That(mappings.First().Guid).Equals(guid);
|
||||
Check.That(mappings.First().Title).Equals(title);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FluentMockServer_ReadStaticMapping_WithGuidFilename()
|
||||
{
|
||||
string guid = "00000002-ee28-4f29-ae63-1ac9b0802d86";
|
||||
|
||||
_server = FluentMockServer.Start();
|
||||
string folder = Path.Combine(GetCurrentFolder(), "__admin", "mappings", guid + ".json");
|
||||
_server.ReadStaticMapping(folder);
|
||||
|
||||
var mappings = _server.Mappings.ToArray();
|
||||
Check.That(mappings).HasSize(1);
|
||||
|
||||
Check.That(mappings.First().RequestMatcher).IsNotNull();
|
||||
Check.That(mappings.First().Provider).IsNotNull();
|
||||
Check.That(mappings.First().Guid).Equals(Guid.Parse(guid));
|
||||
Check.That(mappings.First().Title).IsNullOrEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FluentMockServer_ReadStaticMappings()
|
||||
{
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
string folder = Path.Combine(GetCurrentFolder(), "__admin", "mappings");
|
||||
_server.ReadStaticMappings(folder);
|
||||
|
||||
var mappings = _server.Mappings.ToArray();
|
||||
Check.That(mappings).HasSize(2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FluentMockServer_Admin_Mappings_Get()
|
||||
{
|
||||
var guid = Guid.Parse("90356dba-b36c-469a-a17e-669cd84f1f05");
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
_server.Given(Request.Create().WithPath("/foo1").UsingGet())
|
||||
.WithGuid(guid)
|
||||
.RespondWith(Response.Create().WithStatusCode(201).WithBody("1"));
|
||||
|
||||
_server.Given(Request.Create().WithPath("/foo2").UsingGet())
|
||||
.RespondWith(Response.Create().WithStatusCode(202).WithBody("2"));
|
||||
|
||||
var mappings = _server.Mappings.ToArray();
|
||||
Check.That(mappings).HasSize(2);
|
||||
|
||||
Check.That(mappings.First().RequestMatcher).IsNotNull();
|
||||
Check.That(mappings.First().Provider).IsNotNull();
|
||||
Check.That(mappings.First().Guid).Equals(guid);
|
||||
|
||||
Check.That(mappings[1].Guid).Not.Equals(guid);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FluentMockServer_Admin_Mappings_Add_SameGuid()
|
||||
{
|
||||
var guid = Guid.Parse("90356dba-b36c-469a-a17e-669cd84f1f05");
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
_server.Given(Request.Create().WithPath("/1").UsingGet())
|
||||
.WithGuid(guid)
|
||||
.RespondWith(Response.Create().WithStatusCode(500));
|
||||
|
||||
var mappings = _server.Mappings.ToArray();
|
||||
Check.That(mappings).HasSize(1);
|
||||
Check.That(mappings.First().Guid).Equals(guid);
|
||||
|
||||
_server.Given(Request.Create().WithPath("/2").UsingGet())
|
||||
.WithGuid(guid)
|
||||
.RespondWith(Response.Create().WithStatusCode(500));
|
||||
|
||||
Check.That(mappings).HasSize(1);
|
||||
Check.That(mappings.First().Guid).Equals(guid);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FluentMockServer_Admin_Mappings_AtPriority()
|
||||
{
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
// given
|
||||
_server.Given(Request.Create().WithPath("/1").UsingGet())
|
||||
.AtPriority(2)
|
||||
.RespondWith(Response.Create().WithStatusCode(200));
|
||||
|
||||
_server.Given(Request.Create().WithPath("/1").UsingGet())
|
||||
.AtPriority(1)
|
||||
.RespondWith(Response.Create().WithStatusCode(400));
|
||||
|
||||
var mappings = _server.Mappings.ToArray();
|
||||
Check.That(mappings).HasSize(2);
|
||||
Check.That(mappings[0].Priority).Equals(2);
|
||||
Check.That(mappings[1].Priority).Equals(1);
|
||||
|
||||
// when
|
||||
var response = await new HttpClient().GetAsync("http://localhost:" + _server.Ports[0] + "/1");
|
||||
|
||||
// then
|
||||
Check.That((int)response.StatusCode).IsEqualTo(400);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FluentMockServer_Admin_Requests_Get()
|
||||
{
|
||||
// given
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
// when
|
||||
await new HttpClient().GetAsync("http://localhost:" + _server.Ports[0] + "/foo");
|
||||
|
||||
// then
|
||||
Check.That(_server.LogEntries).HasSize(1);
|
||||
var requestLogged = _server.LogEntries.First();
|
||||
Check.That(requestLogged.RequestMessage.Method).IsEqualTo("get");
|
||||
Check.That(requestLogged.RequestMessage.BodyAsBytes).IsEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Should_respond_to_request()
|
||||
{
|
||||
// given
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
_server
|
||||
.Given(Request.Create()
|
||||
.WithPath("/foo")
|
||||
.UsingGet())
|
||||
.RespondWith(Response.Create()
|
||||
.WithStatusCode(200)
|
||||
.WithBody(@"{ msg: ""Hello world!""}"));
|
||||
|
||||
// when
|
||||
var response = await new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + "/foo");
|
||||
|
||||
// then
|
||||
Check.That(response).IsEqualTo(@"{ msg: ""Hello world!""}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Should_respond_to_request_bodyAsBase64()
|
||||
{
|
||||
// given
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
_server.Given(Request.Create().WithPath("/foo").UsingGet()).RespondWith(Response.Create().WithBodyAsBase64("SGVsbG8gV29ybGQ/"));
|
||||
|
||||
// when
|
||||
var response = await new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + "/foo");
|
||||
|
||||
// then
|
||||
Check.That(response).IsEqualTo("Hello World?");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Should_respond_404_for_unexpected_request()
|
||||
{
|
||||
// given
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
// when
|
||||
var response = await new HttpClient().GetAsync("http://localhost:" + _server.Ports[0] + "/foo");
|
||||
|
||||
// then
|
||||
Check.That(response.StatusCode).IsEqualTo(HttpStatusCode.NotFound);
|
||||
Check.That((int)response.StatusCode).IsEqualTo(404);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Should_find_a_request_satisfying_a_request_spec()
|
||||
{
|
||||
// given
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
// when
|
||||
await new HttpClient().GetAsync("http://localhost:" + _server.Ports[0] + "/foo");
|
||||
await new HttpClient().GetAsync("http://localhost:" + _server.Ports[0] + "/bar");
|
||||
|
||||
// then
|
||||
var result = _server.FindLogEntries(Request.Create().WithPath(new RegexMatcher("^/b.*"))).ToList();
|
||||
Check.That(result).HasSize(1);
|
||||
|
||||
var requestLogged = result.First();
|
||||
Check.That(requestLogged.RequestMessage.Path).IsEqualTo("/bar");
|
||||
Check.That(requestLogged.RequestMessage.Url).IsEqualTo("http://localhost:" + _server.Ports[0] + "/bar");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Should_reset_requestlogs()
|
||||
{
|
||||
// given
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
// when
|
||||
await new HttpClient().GetAsync("http://localhost:" + _server.Ports[0] + "/foo");
|
||||
_server.ResetLogEntries();
|
||||
|
||||
// then
|
||||
Check.That(_server.LogEntries).IsEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_reset_mappings()
|
||||
{
|
||||
// given
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
_server
|
||||
.Given(Request.Create()
|
||||
.WithPath("/foo")
|
||||
.UsingGet())
|
||||
.RespondWith(Response.Create()
|
||||
.WithBody(@"{ msg: ""Hello world!""}"));
|
||||
|
||||
// when
|
||||
_server.ResetMappings();
|
||||
|
||||
// then
|
||||
Check.That(_server.Mappings).IsEmpty();
|
||||
Check.ThatAsyncCode(() => new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + "/foo"))
|
||||
.ThrowsAny();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Should_respond_a_redirect_without_body()
|
||||
{
|
||||
// given
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
_server
|
||||
.Given(Request.Create()
|
||||
.WithPath("/foo")
|
||||
.UsingGet())
|
||||
.RespondWith(Response.Create()
|
||||
.WithStatusCode(307)
|
||||
.WithHeader("Location", "/bar"));
|
||||
_server
|
||||
.Given(Request.Create()
|
||||
.WithPath("/bar")
|
||||
.UsingGet())
|
||||
.RespondWith(Response.Create()
|
||||
.WithStatusCode(200)
|
||||
.WithBody("REDIRECT SUCCESSFUL"));
|
||||
|
||||
// when
|
||||
var response = await new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + "/foo");
|
||||
|
||||
// then
|
||||
Check.That(response).IsEqualTo("REDIRECT SUCCESSFUL");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Should_delay_responses_for_a_given_route()
|
||||
{
|
||||
// given
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
_server
|
||||
.Given(Request.Create()
|
||||
.WithPath("/*"))
|
||||
.RespondWith(Response.Create()
|
||||
.WithBody(@"{ msg: ""Hello world!""}")
|
||||
.WithDelay(TimeSpan.FromMilliseconds(200)));
|
||||
|
||||
// when
|
||||
var watch = new Stopwatch();
|
||||
watch.Start();
|
||||
await new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + "/foo");
|
||||
watch.Stop();
|
||||
|
||||
// then
|
||||
Check.That(watch.ElapsedMilliseconds).IsStrictlyGreaterThan(200);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Should_delay_responses()
|
||||
{
|
||||
// given
|
||||
_server = FluentMockServer.Start();
|
||||
_server.AddGlobalProcessingDelay(TimeSpan.FromMilliseconds(200));
|
||||
_server
|
||||
.Given(Request.Create().WithPath("/*"))
|
||||
.RespondWith(Response.Create().WithBody(@"{ msg: ""Hello world!""}"));
|
||||
|
||||
// when
|
||||
var watch = new Stopwatch();
|
||||
watch.Start();
|
||||
await new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + "/foo");
|
||||
watch.Stop();
|
||||
|
||||
// then
|
||||
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()
|
||||
//{
|
||||
// // given
|
||||
// _server = FluentMockServer.Start();
|
||||
// _server
|
||||
// .Given(Request.Create().WithPath("/*"))
|
||||
// .RespondWith(Response.Create().WithProxy("https://server-that-expects-a-client-certificate", @"\\yourclientcertificatecontainingprivatekey.pfx", "yourclientcertificatepassword"));
|
||||
|
||||
// // when
|
||||
// var result = await new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + "/someurl?someQuery=someValue");
|
||||
|
||||
// // then
|
||||
// Check.That(result).Contains("google");
|
||||
//}
|
||||
|
||||
[Fact]
|
||||
public async Task FluentMockServer_Logging_SetMaxRequestLogCount()
|
||||
{
|
||||
// Assign
|
||||
var client = new HttpClient();
|
||||
// Act
|
||||
_server = FluentMockServer.Start();
|
||||
_server.SetMaxRequestLogCount(2);
|
||||
|
||||
await client.GetAsync("http://localhost:" + _server.Ports[0] + "/foo1");
|
||||
await client.GetAsync("http://localhost:" + _server.Ports[0] + "/foo2");
|
||||
await client.GetAsync("http://localhost:" + _server.Ports[0] + "/foo3");
|
||||
|
||||
// Assert
|
||||
Check.That(_server.LogEntries).HasSize(2);
|
||||
|
||||
var requestLoggedA = _server.LogEntries.First();
|
||||
Check.That(requestLoggedA.RequestMessage.Path).EndsWith("/foo2");
|
||||
|
||||
var requestLoggedB = _server.LogEntries.Last();
|
||||
Check.That(requestLoggedB.RequestMessage.Path).EndsWith("/foo3");
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using NFluent;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Server;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests
|
||||
{
|
||||
public partial class FluentMockServerTests : IDisposable
|
||||
{
|
||||
private FluentMockServer _server;
|
||||
|
||||
// For for AppVeyor + OpenCover
|
||||
private string GetCurrentFolder()
|
||||
{
|
||||
string current = Directory.GetCurrentDirectory();
|
||||
//if (!current.EndsWith("WireMock.Net.Tests"))
|
||||
// return Path.Combine(current, "test", "WireMock.Net.Tests");
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_server?.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FluentMockServer_StartStop()
|
||||
{
|
||||
var server1 = FluentMockServer.Start("http://localhost:9091/");
|
||||
server1.Stop();
|
||||
|
||||
var server2 = FluentMockServer.Start("http://localhost:9091/");
|
||||
server2.Stop();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FluentMockServer_ReadStaticMapping_WithNonGuidFilename()
|
||||
{
|
||||
var guid = Guid.Parse("04ee4872-9efd-4770-90d3-88d445265d0d");
|
||||
string title = "documentdb_root_title";
|
||||
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
string folder = Path.Combine(GetCurrentFolder(), "__admin", "mappings", "documentdb_root.json");
|
||||
_server.ReadStaticMapping(folder);
|
||||
|
||||
var mappings = _server.Mappings.ToArray();
|
||||
Check.That(mappings).HasSize(1);
|
||||
|
||||
Check.That(mappings.First().RequestMatcher).IsNotNull();
|
||||
Check.That(mappings.First().Provider).IsNotNull();
|
||||
Check.That(mappings.First().Guid).Equals(guid);
|
||||
Check.That(mappings.First().Title).Equals(title);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FluentMockServer_ReadStaticMapping_WithGuidFilename()
|
||||
{
|
||||
string guid = "00000002-ee28-4f29-ae63-1ac9b0802d86";
|
||||
|
||||
_server = FluentMockServer.Start();
|
||||
string folder = Path.Combine(GetCurrentFolder(), "__admin", "mappings", guid + ".json");
|
||||
_server.ReadStaticMapping(folder);
|
||||
|
||||
var mappings = _server.Mappings.ToArray();
|
||||
Check.That(mappings).HasSize(1);
|
||||
|
||||
Check.That(mappings.First().RequestMatcher).IsNotNull();
|
||||
Check.That(mappings.First().Provider).IsNotNull();
|
||||
Check.That(mappings.First().Guid).Equals(Guid.Parse(guid));
|
||||
Check.That(mappings.First().Title).IsNullOrEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FluentMockServer_ReadStaticMappings()
|
||||
{
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
string folder = Path.Combine(GetCurrentFolder(), "__admin", "mappings");
|
||||
_server.ReadStaticMappings(folder);
|
||||
|
||||
var mappings = _server.Mappings.ToArray();
|
||||
Check.That(mappings).HasSize(2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FluentMockServer_Admin_Mappings_Get()
|
||||
{
|
||||
var guid = Guid.Parse("90356dba-b36c-469a-a17e-669cd84f1f05");
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
_server.Given(Request.Create().WithPath("/foo1").UsingGet())
|
||||
.WithGuid(guid)
|
||||
.RespondWith(Response.Create().WithStatusCode(201).WithBody("1"));
|
||||
|
||||
_server.Given(Request.Create().WithPath("/foo2").UsingGet())
|
||||
.RespondWith(Response.Create().WithStatusCode(202).WithBody("2"));
|
||||
|
||||
var mappings = _server.Mappings.ToArray();
|
||||
Check.That(mappings).HasSize(2);
|
||||
|
||||
Check.That(mappings.First().RequestMatcher).IsNotNull();
|
||||
Check.That(mappings.First().Provider).IsNotNull();
|
||||
Check.That(mappings.First().Guid).Equals(guid);
|
||||
|
||||
Check.That(mappings[1].Guid).Not.Equals(guid);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FluentMockServer_Admin_Mappings_Add_SameGuid()
|
||||
{
|
||||
var guid = Guid.Parse("90356dba-b36c-469a-a17e-669cd84f1f05");
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
_server.Given(Request.Create().WithPath("/1").UsingGet())
|
||||
.WithGuid(guid)
|
||||
.RespondWith(Response.Create().WithStatusCode(500));
|
||||
|
||||
var mappings = _server.Mappings.ToArray();
|
||||
Check.That(mappings).HasSize(1);
|
||||
Check.That(mappings.First().Guid).Equals(guid);
|
||||
|
||||
_server.Given(Request.Create().WithPath("/2").UsingGet())
|
||||
.WithGuid(guid)
|
||||
.RespondWith(Response.Create().WithStatusCode(500));
|
||||
|
||||
Check.That(mappings).HasSize(1);
|
||||
Check.That(mappings.First().Guid).Equals(guid);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FluentMockServer_Admin_Mappings_AtPriority()
|
||||
{
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
// given
|
||||
_server.Given(Request.Create().WithPath("/1").UsingGet())
|
||||
.AtPriority(2)
|
||||
.RespondWith(Response.Create().WithStatusCode(200));
|
||||
|
||||
_server.Given(Request.Create().WithPath("/1").UsingGet())
|
||||
.AtPriority(1)
|
||||
.RespondWith(Response.Create().WithStatusCode(400));
|
||||
|
||||
var mappings = _server.Mappings.ToArray();
|
||||
Check.That(mappings).HasSize(2);
|
||||
Check.That(mappings[0].Priority).Equals(2);
|
||||
Check.That(mappings[1].Priority).Equals(1);
|
||||
|
||||
// when
|
||||
var response = await new HttpClient().GetAsync("http://localhost:" + _server.Ports[0] + "/1");
|
||||
|
||||
// then
|
||||
Check.That((int)response.StatusCode).IsEqualTo(400);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FluentMockServer_Admin_Requests_Get()
|
||||
{
|
||||
// given
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
// when
|
||||
await new HttpClient().GetAsync("http://localhost:" + _server.Ports[0] + "/foo");
|
||||
|
||||
// then
|
||||
Check.That(_server.LogEntries).HasSize(1);
|
||||
var requestLogged = _server.LogEntries.First();
|
||||
Check.That(requestLogged.RequestMessage.Method).IsEqualTo("get");
|
||||
Check.That(requestLogged.RequestMessage.BodyAsBytes).IsNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FluentMockServer_Should_respond_to_request_bodyAsString()
|
||||
{
|
||||
// given
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
_server
|
||||
.Given(Request.Create()
|
||||
.WithPath("/foo")
|
||||
.UsingGet())
|
||||
.RespondWith(Response.Create()
|
||||
.WithStatusCode(200)
|
||||
.WithBody("Hello world!"));
|
||||
|
||||
// when
|
||||
var response = await new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + "/foo");
|
||||
|
||||
// then
|
||||
Check.That(response).IsEqualTo("Hello world!");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FluentMockServer_Should_respond_to_request_bodyAsBase64()
|
||||
{
|
||||
// given
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
_server.Given(Request.Create().WithPath("/foo").UsingGet()).RespondWith(Response.Create().WithBodyFromBase64("SGVsbG8gV29ybGQ/"));
|
||||
|
||||
// when
|
||||
var response = await new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + "/foo");
|
||||
|
||||
// then
|
||||
Check.That(response).IsEqualTo("Hello World?");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FluentMockServer_Should_respond_to_request_bodyAsBytes()
|
||||
{
|
||||
// given
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
_server.Given(Request.Create().WithPath("/foo").UsingGet()).RespondWith(Response.Create().WithBody(new byte[] { 48, 49 }));
|
||||
|
||||
// when
|
||||
var responseAsString = await new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + "/foo");
|
||||
var responseAsBytes = await new HttpClient().GetByteArrayAsync("http://localhost:" + _server.Ports[0] + "/foo");
|
||||
|
||||
// then
|
||||
Check.That(responseAsString).IsEqualTo("01");
|
||||
Check.That(responseAsBytes).ContainsExactly(new byte[] { 48, 49 });
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FluentMockServer_Should_respond_404_for_unexpected_request()
|
||||
{
|
||||
// given
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
// when
|
||||
var response = await new HttpClient().GetAsync("http://localhost:" + _server.Ports[0] + "/foo");
|
||||
|
||||
// then
|
||||
Check.That(response.StatusCode).IsEqualTo(HttpStatusCode.NotFound);
|
||||
Check.That((int)response.StatusCode).IsEqualTo(404);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FluentMockServer_Should_find_a_request_satisfying_a_request_spec()
|
||||
{
|
||||
// given
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
// when
|
||||
await new HttpClient().GetAsync("http://localhost:" + _server.Ports[0] + "/foo");
|
||||
await new HttpClient().GetAsync("http://localhost:" + _server.Ports[0] + "/bar");
|
||||
|
||||
// then
|
||||
var result = _server.FindLogEntries(Request.Create().WithPath(new RegexMatcher("^/b.*"))).ToList();
|
||||
Check.That(result).HasSize(1);
|
||||
|
||||
var requestLogged = result.First();
|
||||
Check.That(requestLogged.RequestMessage.Path).IsEqualTo("/bar");
|
||||
Check.That(requestLogged.RequestMessage.Url).IsEqualTo("http://localhost:" + _server.Ports[0] + "/bar");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FluentMockServer_Should_reset_requestlogs()
|
||||
{
|
||||
// given
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
// when
|
||||
await new HttpClient().GetAsync("http://localhost:" + _server.Ports[0] + "/foo");
|
||||
_server.ResetLogEntries();
|
||||
|
||||
// then
|
||||
Check.That(_server.LogEntries).IsEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FluentMockServer_Should_reset_mappings()
|
||||
{
|
||||
// given
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
_server
|
||||
.Given(Request.Create()
|
||||
.WithPath("/foo")
|
||||
.UsingGet())
|
||||
.RespondWith(Response.Create()
|
||||
.WithBody(@"{ msg: ""Hello world!""}"));
|
||||
|
||||
// when
|
||||
_server.ResetMappings();
|
||||
|
||||
// then
|
||||
Check.That(_server.Mappings).IsEmpty();
|
||||
Check.ThatAsyncCode(() => new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + "/foo"))
|
||||
.ThrowsAny();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FluentMockServer_Should_respond_a_redirect_without_body()
|
||||
{
|
||||
// given
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
_server
|
||||
.Given(Request.Create()
|
||||
.WithPath("/foo")
|
||||
.UsingGet())
|
||||
.RespondWith(Response.Create()
|
||||
.WithStatusCode(307)
|
||||
.WithHeader("Location", "/bar"));
|
||||
_server
|
||||
.Given(Request.Create()
|
||||
.WithPath("/bar")
|
||||
.UsingGet())
|
||||
.RespondWith(Response.Create()
|
||||
.WithStatusCode(200)
|
||||
.WithBody("REDIRECT SUCCESSFUL"));
|
||||
|
||||
// when
|
||||
var response = await new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + "/foo");
|
||||
|
||||
// then
|
||||
Check.That(response).IsEqualTo("REDIRECT SUCCESSFUL");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FluentMockServer_Should_delay_responses_for_a_given_route()
|
||||
{
|
||||
// given
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
_server
|
||||
.Given(Request.Create()
|
||||
.WithPath("/*"))
|
||||
.RespondWith(Response.Create()
|
||||
.WithBody(@"{ msg: ""Hello world!""}")
|
||||
.WithDelay(TimeSpan.FromMilliseconds(200)));
|
||||
|
||||
// when
|
||||
var watch = new Stopwatch();
|
||||
watch.Start();
|
||||
await new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + "/foo");
|
||||
watch.Stop();
|
||||
|
||||
// then
|
||||
Check.That(watch.ElapsedMilliseconds).IsStrictlyGreaterThan(200);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FluentMockServer_Should_delay_responses()
|
||||
{
|
||||
// given
|
||||
_server = FluentMockServer.Start();
|
||||
_server.AddGlobalProcessingDelay(TimeSpan.FromMilliseconds(200));
|
||||
_server
|
||||
.Given(Request.Create().WithPath("/*"))
|
||||
.RespondWith(Response.Create().WithBody(@"{ msg: ""Hello world!""}"));
|
||||
|
||||
// when
|
||||
var watch = new Stopwatch();
|
||||
watch.Start();
|
||||
await new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + "/foo");
|
||||
watch.Stop();
|
||||
|
||||
// then
|
||||
Check.That(watch.ElapsedMilliseconds).IsStrictlyGreaterThan(200);
|
||||
}
|
||||
|
||||
//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()
|
||||
//{
|
||||
// // given
|
||||
// _server = FluentMockServer.Start();
|
||||
// _server
|
||||
// .Given(Request.Create().WithPath("/*"))
|
||||
// .RespondWith(Response.Create().WithProxy("https://server-that-expects-a-client-certificate", @"\\yourclientcertificatecontainingprivatekey.pfx", "yourclientcertificatepassword"));
|
||||
|
||||
// // when
|
||||
// var result = await new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + "/someurl?someQuery=someValue");
|
||||
|
||||
// // then
|
||||
// Check.That(result).Contains("google");
|
||||
//}
|
||||
|
||||
[Fact]
|
||||
public async Task FluentMockServer_Logging_SetMaxRequestLogCount()
|
||||
{
|
||||
// Assign
|
||||
var client = new HttpClient();
|
||||
// Act
|
||||
_server = FluentMockServer.Start();
|
||||
_server.SetMaxRequestLogCount(2);
|
||||
|
||||
await client.GetAsync("http://localhost:" + _server.Ports[0] + "/foo1");
|
||||
await client.GetAsync("http://localhost:" + _server.Ports[0] + "/foo2");
|
||||
await client.GetAsync("http://localhost:" + _server.Ports[0] + "/foo3");
|
||||
|
||||
// Assert
|
||||
Check.That(_server.LogEntries).HasSize(2);
|
||||
|
||||
var requestLoggedA = _server.LogEntries.First();
|
||||
Check.That(requestLoggedA.RequestMessage.Path).EndsWith("/foo2");
|
||||
|
||||
var requestLoggedB = _server.LogEntries.Last();
|
||||
Check.That(requestLoggedB.RequestMessage.Path).EndsWith("/foo3");
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_server?.Stop();
|
||||
_serverForProxyForwarding?.Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using NFluent;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
@@ -8,7 +13,7 @@ using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests
|
||||
{
|
||||
public class ObservableLogEntriesTest: IDisposable
|
||||
public class ObservableLogEntriesTest : IDisposable
|
||||
{
|
||||
private FluentMockServer _server;
|
||||
|
||||
@@ -35,6 +40,42 @@ namespace WireMock.Net.Tests
|
||||
Check.That(count).Equals(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ParallelTest()
|
||||
{
|
||||
var expectedCount = 100;
|
||||
|
||||
// Assign
|
||||
_server = FluentMockServer.Start();
|
||||
|
||||
_server
|
||||
.Given(Request.Create()
|
||||
.WithPath("/foo")
|
||||
.UsingGet())
|
||||
.RespondWith(Response.Create()
|
||||
.WithDelay(6)
|
||||
.WithSuccess());
|
||||
|
||||
int count = 0;
|
||||
_server.LogEntriesChanged += (sender, args) => count++;
|
||||
|
||||
var http = new HttpClient();
|
||||
|
||||
// Act
|
||||
var listOfTasks = new List<Task<HttpResponseMessage>>();
|
||||
for (var i = 0; i < expectedCount; i++)
|
||||
{
|
||||
Thread.Sleep(3);
|
||||
listOfTasks.Add(http.GetAsync(_server.Urls[0] + $"/foo"));
|
||||
}
|
||||
var responses = await Task.WhenAll(listOfTasks);
|
||||
var countResponsesWithStatusNotOk = responses.Where(r => r.StatusCode != HttpStatusCode.OK).Count();
|
||||
|
||||
// Assert
|
||||
Check.That(countResponsesWithStatusNotOk).Equals(0);
|
||||
Check.That(count).Equals(expectedCount);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_server?.Dispose();
|
||||
|
||||
@@ -8,13 +8,13 @@ namespace WireMock.Net.Tests
|
||||
//[TestFixture]
|
||||
public class RequestMessageTests
|
||||
{
|
||||
private const string clientIP = "::1";
|
||||
private const string ClientIp = "::1";
|
||||
|
||||
[Fact]
|
||||
public void Should_handle_empty_query()
|
||||
{
|
||||
// given
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", clientIP);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp);
|
||||
|
||||
// then
|
||||
Check.That(request.GetParameter("not_there")).IsNull();
|
||||
@@ -26,7 +26,7 @@ namespace WireMock.Net.Tests
|
||||
// given
|
||||
string bodyAsString = "whatever";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost?foo=bar&multi=1&multi=2"), "POST", clientIP, body, bodyAsString, Encoding.UTF8);
|
||||
var request = new RequestMessage(new Uri("http://localhost?foo=bar&multi=1&multi=2"), "POST", ClientIp, body, bodyAsString, Encoding.UTF8);
|
||||
|
||||
// then
|
||||
Check.That(request.GetParameter("foo")).Contains("bar");
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
using System;
|
||||
using NFluent;
|
||||
using WireMock.Matchers.Request;
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace WireMock.Net.Tests
|
||||
//[TestFixture]
|
||||
public partial class RequestTests
|
||||
{
|
||||
private const string clientIP = "::1";
|
||||
private const string ClientIp = "::1";
|
||||
|
||||
[Fact]
|
||||
public void Should_specify_requests_matching_given_path()
|
||||
@@ -21,7 +21,7 @@ namespace WireMock.Net.Tests
|
||||
var spec = Request.Create().WithPath("/foo");
|
||||
|
||||
// when
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "blabla", clientIP);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "blabla", ClientIp);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -33,8 +33,8 @@ namespace WireMock.Net.Tests
|
||||
{
|
||||
var requestBuilder = Request.Create().WithPath("/x1", "/x2");
|
||||
|
||||
var request1 = new RequestMessage(new Uri("http://localhost/x1"), "blabla", clientIP);
|
||||
var request2 = new RequestMessage(new Uri("http://localhost/x2"), "blabla", clientIP);
|
||||
var request1 = new RequestMessage(new Uri("http://localhost/x1"), "blabla", ClientIp);
|
||||
var request2 = new RequestMessage(new Uri("http://localhost/x2"), "blabla", ClientIp);
|
||||
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
Check.That(requestBuilder.GetMatchingScore(request1, requestMatchResult)).IsEqualTo(1.0);
|
||||
@@ -48,7 +48,7 @@ namespace WireMock.Net.Tests
|
||||
var spec = Request.Create().WithPath(url => url.EndsWith("/foo"));
|
||||
|
||||
// when
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "blabla", clientIP);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "blabla", ClientIp);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -62,7 +62,7 @@ namespace WireMock.Net.Tests
|
||||
var spec = Request.Create().WithPath(new RegexMatcher("^/foo"));
|
||||
|
||||
// when
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo/bar"), "blabla", clientIP);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo/bar"), "blabla", ClientIp);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -76,7 +76,7 @@ namespace WireMock.Net.Tests
|
||||
var spec = Request.Create().WithPath("/foo");
|
||||
|
||||
// when
|
||||
var request = new RequestMessage(new Uri("http://localhost/bar"), "blabla", clientIP);
|
||||
var request = new RequestMessage(new Uri("http://localhost/bar"), "blabla", ClientIp);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -90,7 +90,7 @@ namespace WireMock.Net.Tests
|
||||
var spec = Request.Create().WithUrl("*/foo");
|
||||
|
||||
// when
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "blabla", clientIP);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "blabla", ClientIp);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -104,7 +104,7 @@ namespace WireMock.Net.Tests
|
||||
var spec = Request.Create().WithPath("/foo").UsingPut();
|
||||
|
||||
// when
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", ClientIp);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -118,7 +118,7 @@ namespace WireMock.Net.Tests
|
||||
var spec = Request.Create().WithPath("/foo").UsingPost();
|
||||
|
||||
// when
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", clientIP);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -132,7 +132,7 @@ namespace WireMock.Net.Tests
|
||||
var spec = Request.Create().WithPath("/foo").UsingGet();
|
||||
|
||||
// when
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "GET", clientIP);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "GET", ClientIp);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -148,7 +148,7 @@ namespace WireMock.Net.Tests
|
||||
// when
|
||||
string bodyAsString = "whatever";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "Delete", clientIP, body, bodyAsString, Encoding.UTF8);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "Delete", ClientIp, body, bodyAsString, Encoding.UTF8);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -162,7 +162,7 @@ namespace WireMock.Net.Tests
|
||||
var spec = Request.Create().WithPath("/foo").UsingHead();
|
||||
|
||||
// when
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "HEAD", clientIP);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "HEAD", ClientIp);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -176,7 +176,7 @@ namespace WireMock.Net.Tests
|
||||
var spec = Request.Create().WithPath("/foo").UsingPut();
|
||||
|
||||
// when
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "HEAD", clientIP);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "HEAD", ClientIp);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -190,7 +190,7 @@ namespace WireMock.Net.Tests
|
||||
var spec = Request.Create().WithPath("/bar").UsingPut();
|
||||
|
||||
// when
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", ClientIp);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -206,7 +206,7 @@ namespace WireMock.Net.Tests
|
||||
// when
|
||||
string bodyAsString = "whatever";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP, body, bodyAsString, Encoding.UTF8, new Dictionary<string, string> { { "X-toto", "tata" } });
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", ClientIp, body, bodyAsString, Encoding.UTF8, new Dictionary<string, string[]> { { "X-toto", new [] { "tata" } } });
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -222,7 +222,7 @@ namespace WireMock.Net.Tests
|
||||
// when
|
||||
string bodyAsString = "whatever";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP, body, bodyAsString, Encoding.UTF8, new Dictionary<string, string> { { "X-toto", "tata" } });
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", ClientIp, body, bodyAsString, Encoding.UTF8, new Dictionary<string, string[]> { { "X-toto", new[] { "tata" } } });
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -238,7 +238,7 @@ namespace WireMock.Net.Tests
|
||||
// when
|
||||
string bodyAsString = "whatever";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP, body, bodyAsString, Encoding.UTF8, new Dictionary<string, string> { { "X-toto", "ABC" } });
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", ClientIp, body, bodyAsString, Encoding.UTF8, new Dictionary<string, string[]> { { "X-toto", new[] { "ABC" } } });
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -254,7 +254,7 @@ namespace WireMock.Net.Tests
|
||||
// when
|
||||
string bodyAsString = "whatever";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP, body, bodyAsString, Encoding.UTF8, new Dictionary<string, string> { { "X-toto", "TaTa" } });
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", ClientIp, body, bodyAsString, Encoding.UTF8, new Dictionary<string, string[]> { { "X-toto", new[] { "TaTa" } } });
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -268,7 +268,7 @@ namespace WireMock.Net.Tests
|
||||
var spec = Request.Create().UsingAnyVerb().WithCookie("session", "a*");
|
||||
|
||||
// when
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP, null, null, null, null, new Dictionary<string, string> { { "session", "abc" } });
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", ClientIp, null, null, null, null, new Dictionary<string, string> { { "session", "abc" } });
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -284,7 +284,7 @@ namespace WireMock.Net.Tests
|
||||
// when
|
||||
string bodyAsString = "Hello world!";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP, body, bodyAsString, Encoding.UTF8);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", ClientIp, body, bodyAsString, Encoding.UTF8);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -300,7 +300,7 @@ namespace WireMock.Net.Tests
|
||||
// when
|
||||
string bodyAsString = "cat";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", clientIP, body, bodyAsString, Encoding.UTF8);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, body, bodyAsString, Encoding.UTF8);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -316,7 +316,7 @@ namespace WireMock.Net.Tests
|
||||
// when
|
||||
string bodyAsString = "cat";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", clientIP, body, bodyAsString, Encoding.UTF8);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, body, bodyAsString, Encoding.UTF8);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -332,7 +332,7 @@ namespace WireMock.Net.Tests
|
||||
// when
|
||||
string bodyAsString = "caR";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", clientIP, body, bodyAsString, Encoding.UTF8);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, body, bodyAsString, Encoding.UTF8);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -348,7 +348,7 @@ namespace WireMock.Net.Tests
|
||||
// when
|
||||
string bodyAsString = "The car drives in the street.";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", clientIP, body, bodyAsString, Encoding.UTF8);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, body, bodyAsString, Encoding.UTF8);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -364,7 +364,7 @@ namespace WireMock.Net.Tests
|
||||
// when
|
||||
string bodyAsString = "Hello";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", clientIP, body, bodyAsString, Encoding.UTF8);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, body, bodyAsString, Encoding.UTF8);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -380,7 +380,7 @@ namespace WireMock.Net.Tests
|
||||
// when
|
||||
string bodyAsString = "Hello world!";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP, body, bodyAsString, Encoding.UTF8, new Dictionary<string, string> { { "X-toto", "tatata" } });
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", ClientIp, body, bodyAsString, Encoding.UTF8, new Dictionary<string, string[]> { { "X-toto", new[] { "tatata" } } });
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -396,7 +396,7 @@ namespace WireMock.Net.Tests
|
||||
// when
|
||||
string bodyAsString = "Hello world!";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP, body, bodyAsString, Encoding.UTF8);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", ClientIp, body, bodyAsString, Encoding.UTF8);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -417,7 +417,7 @@ namespace WireMock.Net.Tests
|
||||
<todo-item id='a3'>xyz</todo-item>
|
||||
</todo-list>";
|
||||
byte[] body = Encoding.UTF8.GetBytes(xmlBodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP, body, xmlBodyAsString, Encoding.UTF8);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", ClientIp, body, xmlBodyAsString, Encoding.UTF8);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -438,7 +438,7 @@ namespace WireMock.Net.Tests
|
||||
<todo-item id='a3'>xyz</todo-item>
|
||||
</todo-list>";
|
||||
byte[] body = Encoding.UTF8.GetBytes(xmlBodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP, body, xmlBodyAsString, Encoding.UTF8);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", ClientIp, body, xmlBodyAsString, Encoding.UTF8);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -454,7 +454,7 @@ namespace WireMock.Net.Tests
|
||||
// when
|
||||
string bodyAsString = "{ \"things\": [ { \"name\": \"RequiredThing\" }, { \"name\": \"Wiremock\" } ] }";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP, body, bodyAsString, Encoding.UTF8);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", ClientIp, body, bodyAsString, Encoding.UTF8);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -470,7 +470,7 @@ namespace WireMock.Net.Tests
|
||||
// when
|
||||
string bodyAsString = "{ \"things\": { \"name\": \"Wiremock\" } }";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP, body, bodyAsString, Encoding.UTF8);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", ClientIp, body, bodyAsString, Encoding.UTF8);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -486,7 +486,7 @@ namespace WireMock.Net.Tests
|
||||
// when
|
||||
string bodyAsString = "xxx";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP, body, bodyAsString, Encoding.UTF8, new Dictionary<string, string> { { "X-toto", "tatata" } });
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", ClientIp, body, bodyAsString, Encoding.UTF8, new Dictionary<string, string[]> { { "X-toto", new[] { "tata" } } });
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -500,7 +500,7 @@ namespace WireMock.Net.Tests
|
||||
var spec = Request.Create().WithParam("bar", "1", "2");
|
||||
|
||||
// when
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo?bar=1&bar=2"), "PUT", clientIP);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo?bar=1&bar=2"), "PUT", ClientIp);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -514,7 +514,7 @@ namespace WireMock.Net.Tests
|
||||
var spec = Request.Create().WithParam("bar");
|
||||
|
||||
// when
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo?bar"), "PUT", clientIP);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo?bar"), "PUT", ClientIp);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -528,7 +528,7 @@ namespace WireMock.Net.Tests
|
||||
var spec = Request.Create().UsingAnyVerb().WithParam(p => p.ContainsKey("bar"));
|
||||
|
||||
// when
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo?bar=1&bar=2"), "PUT", clientIP);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo?bar=1&bar=2"), "PUT", ClientIp);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
@@ -542,7 +542,7 @@ namespace WireMock.Net.Tests
|
||||
var spec = Request.Create().WithParam("bar", "1");
|
||||
|
||||
// when
|
||||
var request = new RequestMessage(new Uri("http://localhost/test=7"), "PUT", clientIP);
|
||||
var request = new RequestMessage(new Uri("http://localhost/test=7"), "PUT", ClientIp);
|
||||
|
||||
// then
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
|
||||
109
test/WireMock.Net.Tests/ResponseTests.Handlebars.cs
Normal file
109
test/WireMock.Net.Tests/ResponseTests.Handlebars.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NFluent;
|
||||
using WireMock.ResponseBuilders;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests
|
||||
{
|
||||
public partial class ResponseTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_Handlebars_UrlPathVerb()
|
||||
{
|
||||
// given
|
||||
string bodyAsString = "abc";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, body, bodyAsString, Encoding.UTF8);
|
||||
|
||||
var response = Response.Create()
|
||||
.WithBody("test {{request.url}} {{request.path}} {{request.method}}")
|
||||
.WithTransformer();
|
||||
|
||||
// act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
|
||||
// then
|
||||
Check.That(responseMessage.Body).Equals("test http://localhost/foo /foo post");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_Handlebars_Query()
|
||||
{
|
||||
// given
|
||||
string bodyAsString = "abc";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo?a=1&a=2&b=5"), "POST", ClientIp, body, bodyAsString, Encoding.UTF8);
|
||||
|
||||
var response = Response.Create()
|
||||
.WithBody("test keya={{request.query.a}} idx={{request.query.a.[0]}} idx={{request.query.a.[1]}} keyb={{request.query.b}}")
|
||||
.WithTransformer();
|
||||
|
||||
// act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
|
||||
// then
|
||||
Check.That(responseMessage.Body).Equals("test keya=1 idx=1 idx=2 keyb=5");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_Handlebars_Header()
|
||||
{
|
||||
// given
|
||||
string bodyAsString = "abc";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, body, bodyAsString, Encoding.UTF8, new Dictionary<string, string[]> { { "Content-Type", new[] { "text/plain" } } });
|
||||
|
||||
var response = Response.Create().WithHeader("x", "{{request.headers.Content-Type}}").WithBody("test").WithTransformer();
|
||||
|
||||
// act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
|
||||
// then
|
||||
Check.That(responseMessage.Body).Equals("test");
|
||||
Check.That(responseMessage.Headers).ContainsKey("x");
|
||||
Check.That(responseMessage.Headers["x"]).ContainsExactly("text/plain");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_Handlebars_Headers()
|
||||
{
|
||||
// given
|
||||
string bodyAsString = "abc";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, body, bodyAsString, Encoding.UTF8, new Dictionary<string, string[]> { { "Content-Type", new[] { "text/plain" } } });
|
||||
|
||||
var response = Response.Create().WithHeader("x", "{{request.headers.Content-Type}}", "{{request.url}}").WithBody("test").WithTransformer();
|
||||
|
||||
// act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
|
||||
// then
|
||||
Check.That(responseMessage.Body).Equals("test");
|
||||
Check.That(responseMessage.Headers).ContainsKey("x");
|
||||
Check.That(responseMessage.Headers["x"]).Contains("text/plain");
|
||||
Check.That(responseMessage.Headers["x"]).Contains("http://localhost/foo");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_Handlebars_Origin_Port_Protocol_Host()
|
||||
{
|
||||
// given
|
||||
string bodyAsString = "abc";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost:1234"), "POST", ClientIp, body, bodyAsString, Encoding.UTF8);
|
||||
|
||||
var response = Response.Create()
|
||||
.WithBody("test {{request.origin}} {{request.port}} {{request.protocol}} {{request.host}}")
|
||||
.WithTransformer();
|
||||
|
||||
// act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
|
||||
// then
|
||||
Check.That(responseMessage.Body).Equals("test http://localhost:1234 1234 http localhost");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,83 +1,63 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NFluent;
|
||||
using Xunit;
|
||||
using WireMock.ResponseBuilders;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests
|
||||
{
|
||||
//[TestFixture]
|
||||
public class ResponseTests
|
||||
public partial class ResponseTests
|
||||
{
|
||||
private const string clientIP = "::1";
|
||||
private const string ClientIp = "::1";
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_Handlebars_UrlPathVerb()
|
||||
public async Task Response_ProvideResponse_WithBody_Bytes_Encoding_Destination_String()
|
||||
{
|
||||
// given
|
||||
string bodyAsString = "abc";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", clientIP, body, bodyAsString, Encoding.UTF8);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, body, bodyAsString, Encoding.UTF8);
|
||||
|
||||
var response = Response.Create()
|
||||
.WithBody("test {{request.url}} {{request.path}} {{request.method}}")
|
||||
.WithTransformer();
|
||||
var response = Response.Create().WithBody(new byte[] { 48, 49 }, BodyDestinationFormat.String, Encoding.ASCII);
|
||||
|
||||
// act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
|
||||
// then
|
||||
Check.That(responseMessage.Body).Equals("test http://localhost/foo /foo post");
|
||||
Check.That(responseMessage.Body).Equals("01");
|
||||
Check.That(responseMessage.BodyAsBytes).IsNull();
|
||||
Check.That(responseMessage.BodyEncoding).Equals(Encoding.ASCII);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_Handlebars_Query()
|
||||
public async Task Response_ProvideResponse_WithBody_Bytes_Encoding_Destination_Bytes()
|
||||
{
|
||||
// given
|
||||
string bodyAsString = "abc";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo?a=1&a=2&b=5"), "POST", clientIP, body, bodyAsString, Encoding.UTF8);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, body, bodyAsString, Encoding.UTF8);
|
||||
|
||||
var response = Response.Create()
|
||||
.WithBody("test keya={{request.query.a}} idx={{request.query.a.[0]}} idx={{request.query.a.[1]}} keyb={{request.query.b}}")
|
||||
.WithTransformer();
|
||||
var response = Response.Create().WithBody(new byte[] { 48, 49 }, BodyDestinationFormat.SameAsSource, Encoding.ASCII);
|
||||
|
||||
// act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
|
||||
// then
|
||||
Check.That(responseMessage.Body).Equals("test keya=1 idx=1 idx=2 keyb=5");
|
||||
Check.That(responseMessage.BodyAsBytes).ContainsExactly(new byte[] { 48, 49 });
|
||||
Check.That(responseMessage.Body).IsNull();
|
||||
Check.That(responseMessage.BodyEncoding).IsNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_Handlebars_Headers()
|
||||
public async Task Response_ProvideResponse_WithBody_String_Encoding()
|
||||
{
|
||||
// given
|
||||
string bodyAsString = "abc";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", clientIP, body, bodyAsString, Encoding.UTF8, new Dictionary<string, string> { { "Content-Type", "text/plain" } });
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, body, bodyAsString, Encoding.UTF8);
|
||||
|
||||
var response = Response.Create().WithHeader("x", "{{request.headers.Content-Type}}").WithBody("test").WithTransformer();
|
||||
|
||||
// act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
|
||||
// then
|
||||
Check.That(responseMessage.Body).Equals("test");
|
||||
Check.That(responseMessage.Headers).Contains(new KeyValuePair<string, string>("x", "text/plain"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_Encoding_Body()
|
||||
{
|
||||
// given
|
||||
string bodyAsString = "abc";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", clientIP, body, bodyAsString, Encoding.UTF8);
|
||||
|
||||
var response = Response.Create().WithBody("test", Encoding.ASCII);
|
||||
var response = Response.Create().WithBody("test", null, Encoding.ASCII);
|
||||
|
||||
// act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
@@ -88,12 +68,12 @@ namespace WireMock.Net.Tests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_Encoding_JsonBody()
|
||||
public async Task Response_ProvideResponse_WithBody_Object_Encoding()
|
||||
{
|
||||
// given
|
||||
string bodyAsString = "abc";
|
||||
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", clientIP, body, bodyAsString, Encoding.UTF8);
|
||||
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, body, bodyAsString, Encoding.UTF8);
|
||||
|
||||
var response = Response.Create().WithBodyAsJson(new { value = "test" }, Encoding.ASCII);
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Server;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace WireMock.Net.Tests
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user