diff --git a/examples/WireMock.Net.Console.NETCoreApp/Program.cs b/examples/WireMock.Net.Console.NETCoreApp/Program.cs
index 90297c8c..e5f99e98 100644
--- a/examples/WireMock.Net.Console.NETCoreApp/Program.cs
+++ b/examples/WireMock.Net.Console.NETCoreApp/Program.cs
@@ -1,11 +1,21 @@
-using WireMock.Net.ConsoleApplication;
+using System.IO;
+using System.Reflection;
+using log4net;
+using log4net.Config;
+using log4net.Repository;
+using WireMock.Net.ConsoleApplication;
namespace WireMock.Net.Console.NETCoreApp
{
static class Program
{
+ private static readonly ILoggerRepository LogRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());
+ private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
+
static void Main(params string[] args)
{
+ XmlConfigurator.Configure(LogRepository, new FileInfo("log4net.config"));
+
MainApp.Run();
}
}
diff --git a/examples/WireMock.Net.Console.NETCoreApp/WireMock.Net.Console.NETCoreApp.csproj b/examples/WireMock.Net.Console.NETCoreApp/WireMock.Net.Console.NETCoreApp.csproj
index 37a4ed8d..4b6c9735 100644
--- a/examples/WireMock.Net.Console.NETCoreApp/WireMock.Net.Console.NETCoreApp.csproj
+++ b/examples/WireMock.Net.Console.NETCoreApp/WireMock.Net.Console.NETCoreApp.csproj
@@ -22,10 +22,17 @@
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
PreserveNewest
diff --git a/examples/WireMock.Net.Console.NETCoreApp/log4net.config b/examples/WireMock.Net.Console.NETCoreApp/log4net.config
new file mode 100644
index 00000000..feae9952
--- /dev/null
+++ b/examples/WireMock.Net.Console.NETCoreApp/log4net.config
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/WireMock.Net.Console.NETCoreApp/nlog.config b/examples/WireMock.Net.Console.NETCoreApp/nlog.config
new file mode 100644
index 00000000..de6d9072
--- /dev/null
+++ b/examples/WireMock.Net.Console.NETCoreApp/nlog.config
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/WireMock.Net.ConsoleApplication/MainApp.cs b/examples/WireMock.Net.ConsoleApplication/MainApp.cs
index 6549b171..09e4e290 100644
--- a/examples/WireMock.Net.ConsoleApplication/MainApp.cs
+++ b/examples/WireMock.Net.ConsoleApplication/MainApp.cs
@@ -54,8 +54,9 @@ namespace WireMock.Net.ConsoleApplication
.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""}"));
+ //.WithHeader("MyHeader", "application/json", "application/json2")
+ .WithHeader("Content-Type", "application/json")
+ .WithBodyAsJson(new { result = "data:headers posted with 201" }));
server
.Given(Request.Create().WithPath("/file").UsingGet())
@@ -117,7 +118,7 @@ namespace WireMock.Net.ConsoleApplication
.RespondWith(Response.Create()
.WithStatusCode(201)
.WithHeader("Content-Type", "application/json")
- .WithBody(@"{ ""result"": ""data posted with FUNC 201""}"));
+ .WithBodyAsJson(new { result = "data posted with FUNC 201" }));
server
.Given(Request.Create().WithPath("/json").UsingPost().WithBody(new JsonPathMatcher("$.things[?(@.name == 'RequiredThing')]")))
diff --git a/examples/WireMock.Net.ConsoleApplication/Program.cs b/examples/WireMock.Net.ConsoleApplication/Program.cs
index 5765ad6c..c143a0f3 100644
--- a/examples/WireMock.Net.ConsoleApplication/Program.cs
+++ b/examples/WireMock.Net.ConsoleApplication/Program.cs
@@ -1,9 +1,14 @@
-namespace WireMock.Net.ConsoleApplication
+using System.IO;
+using log4net.Config;
+
+namespace WireMock.Net.ConsoleApplication
{
static class Program
{
static void Main(params string[] args)
{
+ XmlConfigurator.Configure(new FileInfo("log4net.config"));
+
MainApp.Run();
}
}
diff --git a/examples/WireMock.Net.ConsoleApplication/WireMock.Net.Console.NET452.csproj b/examples/WireMock.Net.ConsoleApplication/WireMock.Net.Console.NET452.csproj
index 9c5a42ca..5f0a26a8 100644
--- a/examples/WireMock.Net.ConsoleApplication/WireMock.Net.Console.NET452.csproj
+++ b/examples/WireMock.Net.ConsoleApplication/WireMock.Net.Console.NET452.csproj
@@ -36,17 +36,22 @@
..\..\WireMock.Net-Logo.ico
+
+ ..\..\packages\log4net.2.0.8\lib\net45-full\log4net.dll
+
+
..\..\packages\Microsoft.Owin.Host.HttpListener.3.1.0\lib\net45\Microsoft.Owin.Host.HttpListener.dll
..\..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll
-
- ..\..\packages\SimMetrics.Net.1.0.3\lib\net45\SimMetrics.Net.dll
+
+ ..\..\packages\SimMetrics.Net.1.0.4\lib\net45\SimMetrics.Net.dll
+
@@ -57,6 +62,9 @@
Designer
+
+ PreserveNewest
+
Designer
diff --git a/examples/WireMock.Net.ConsoleApplication/log4net.config b/examples/WireMock.Net.ConsoleApplication/log4net.config
new file mode 100644
index 00000000..feae9952
--- /dev/null
+++ b/examples/WireMock.Net.ConsoleApplication/log4net.config
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/WireMock.Net.ConsoleApplication/packages.config b/examples/WireMock.Net.ConsoleApplication/packages.config
index 26f32c8a..a1ad973f 100644
--- a/examples/WireMock.Net.ConsoleApplication/packages.config
+++ b/examples/WireMock.Net.ConsoleApplication/packages.config
@@ -1,6 +1,7 @@
+
-
+
\ No newline at end of file
diff --git a/examples/WireMock.Net.StandAlone.NETCoreApp/Program.cs b/examples/WireMock.Net.StandAlone.NETCoreApp/Program.cs
index b3af5d9d..b7d69600 100644
--- a/examples/WireMock.Net.StandAlone.NETCoreApp/Program.cs
+++ b/examples/WireMock.Net.StandAlone.NETCoreApp/Program.cs
@@ -1,16 +1,26 @@
using System;
+using System.IO;
+using System.Reflection;
using System.Threading;
+using log4net;
+using log4net.Config;
+using log4net.Repository;
using WireMock.Server;
namespace WireMock.Net.StandAlone.NETCoreApp
{
- class Program
+ static class Program
{
+ private static readonly ILoggerRepository LogRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());
+ // private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
+
private static int sleepTime = 30000;
private static FluentMockServer _server;
static void Main(string[] args)
{
+ XmlConfigurator.Configure(LogRepository, new FileInfo("log4net.config"));
+
_server = StandAloneApp.Start(args);
Console.WriteLine($"{DateTime.UtcNow} Press Ctrl+C to shut down");
diff --git a/examples/WireMock.Net.StandAlone.NETCoreApp/WireMock.Net.StandAlone.NETCoreApp.csproj b/examples/WireMock.Net.StandAlone.NETCoreApp/WireMock.Net.StandAlone.NETCoreApp.csproj
index 6b7ea76f..5b2ac302 100644
--- a/examples/WireMock.Net.StandAlone.NETCoreApp/WireMock.Net.StandAlone.NETCoreApp.csproj
+++ b/examples/WireMock.Net.StandAlone.NETCoreApp/WireMock.Net.StandAlone.NETCoreApp.csproj
@@ -6,8 +6,18 @@
../../WireMock.Net-Logo.ico
+
+
+
+
+
+
+ PreserveNewest
+
+
+
\ No newline at end of file
diff --git a/examples/WireMock.Net.StandAlone.NETCoreApp/log4net.config b/examples/WireMock.Net.StandAlone.NETCoreApp/log4net.config
new file mode 100644
index 00000000..feae9952
--- /dev/null
+++ b/examples/WireMock.Net.StandAlone.NETCoreApp/log4net.config
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/WireMock.Net.StandAlone.Net452/Program.cs b/examples/WireMock.Net.StandAlone.Net452/Program.cs
index 36bd441f..69d444e4 100644
--- a/examples/WireMock.Net.StandAlone.Net452/Program.cs
+++ b/examples/WireMock.Net.StandAlone.Net452/Program.cs
@@ -1,4 +1,6 @@
using System;
+using System.IO;
+using log4net.Config;
namespace WireMock.Net.StandAlone.Net452
{
@@ -6,6 +8,8 @@ namespace WireMock.Net.StandAlone.Net452
{
static void Main(params string[] args)
{
+ XmlConfigurator.Configure(new FileInfo("log4net.config"));
+
StandAloneApp.Start(args);
Console.WriteLine("Press any key to stop the server");
diff --git a/examples/WireMock.Net.StandAlone.Net452/WireMock.Net.StandAlone.Net452.csproj b/examples/WireMock.Net.StandAlone.Net452/WireMock.Net.StandAlone.Net452.csproj
index 81075ad1..1157e052 100644
--- a/examples/WireMock.Net.StandAlone.Net452/WireMock.Net.StandAlone.Net452.csproj
+++ b/examples/WireMock.Net.StandAlone.Net452/WireMock.Net.StandAlone.Net452.csproj
@@ -39,6 +39,9 @@
WireMock.Net.StandAlone.Net452.Program
+
+ ..\..\packages\log4net.2.0.8\lib\net45-full\log4net.dll
+
@@ -50,6 +53,9 @@
+
+ PreserveNewest
+
diff --git a/examples/WireMock.Net.StandAlone.Net452/log4net.config b/examples/WireMock.Net.StandAlone.Net452/log4net.config
new file mode 100644
index 00000000..feae9952
--- /dev/null
+++ b/examples/WireMock.Net.StandAlone.Net452/log4net.config
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/WireMock.Net.StandAlone.Net452/packages.config b/examples/WireMock.Net.StandAlone.Net452/packages.config
index 6b8deb9c..a3909492 100644
--- a/examples/WireMock.Net.StandAlone.Net452/packages.config
+++ b/examples/WireMock.Net.StandAlone.Net452/packages.config
@@ -1,3 +1,4 @@
+
\ No newline at end of file
diff --git a/src/WireMock.Net.StandAlone/StandAloneApp.cs b/src/WireMock.Net.StandAlone/StandAloneApp.cs
index aedea35d..426a4744 100644
--- a/src/WireMock.Net.StandAlone/StandAloneApp.cs
+++ b/src/WireMock.Net.StandAlone/StandAloneApp.cs
@@ -1,10 +1,9 @@
-using System;
-using System.Linq;
+using System.Linq;
using WireMock.Server;
using WireMock.Settings;
using WireMock.Validation;
using JetBrains.Annotations;
-using Newtonsoft.Json;
+using log4net;
namespace WireMock.Net.StandAlone
{
@@ -13,8 +12,10 @@ namespace WireMock.Net.StandAlone
///
public static class StandAloneApp
{
+ private static readonly ILog Log = LogManager.GetLogger(typeof(StandAloneApp));
+
///
- /// Start WireMock.Net standalone based on the FluentMockServerSettings.
+ /// Start WireMock.Net standalone Server based on the FluentMockServerSettings.
///
/// The FluentMockServerSettings
[PublicAPI]
@@ -26,7 +27,7 @@ namespace WireMock.Net.StandAlone
}
///
- /// Start WireMock.Net standalone based on the commandline arguments.
+ /// Start WireMock.Net standalone Server based on the commandline arguments.
///
/// The commandline arguments
[PublicAPI]
@@ -34,7 +35,7 @@ namespace WireMock.Net.StandAlone
{
Check.NotNull(args, nameof(args));
- Console.WriteLine("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
+ Log.DebugFormat("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
var parser = new SimpleCommandLineParser();
parser.Parse(args);
@@ -73,11 +74,9 @@ namespace WireMock.Net.StandAlone
};
}
- Console.WriteLine("WireMock.Net server settings {0}", JsonConvert.SerializeObject(settings, Formatting.Indented));
-
FluentMockServer server = Start(settings);
- Console.WriteLine("WireMock.Net server listening at {0}", string.Join(",", server.Urls));
+ Log.InfoFormat("WireMock.Net server listening at {0}", string.Join(",", server.Urls));
return server;
}
diff --git a/src/WireMock.Net.StandAlone/WireMock.Net.StandAlone.csproj b/src/WireMock.Net.StandAlone/WireMock.Net.StandAlone.csproj
index 2d48a7ad..a33887f9 100644
--- a/src/WireMock.Net.StandAlone/WireMock.Net.StandAlone.csproj
+++ b/src/WireMock.Net.StandAlone/WireMock.Net.StandAlone.csproj
@@ -3,7 +3,7 @@
Lightweight StandAlone Http Mocking Server for .Net.
WireMock.Net.StandAlone
- 1.0.3
+ 1.0.3.1
Stef Heyenrath
net452;net46;netstandard1.3;netstandard2.0
true
@@ -36,10 +36,7 @@
All
-
-
-
-
+
diff --git a/src/WireMock.Net/Admin/Requests/LogEntryModel.cs b/src/WireMock.Net/Admin/Requests/LogEntryModel.cs
index d9d5263c..8a97f0fd 100644
--- a/src/WireMock.Net/Admin/Requests/LogEntryModel.cs
+++ b/src/WireMock.Net/Admin/Requests/LogEntryModel.cs
@@ -8,51 +8,33 @@ namespace WireMock.Admin.Requests
public class LogEntryModel
{
///
- /// Gets or sets the unique identifier.
- ///
- ///
/// The unique identifier.
- ///
+ ///
public Guid Guid { get; set; }
///
- /// Gets or sets the request.
- ///
- ///
/// The request.
- ///
+ ///
public LogRequestModel Request { get; set; }
///
- /// Gets or sets the response.
- ///
- ///
/// The response.
- ///
+ ///
public LogResponseModel Response { get; set; }
///
- /// Gets or sets the mapping unique identifier.
- ///
- ///
/// The mapping unique identifier.
- ///
+ ///
public Guid? MappingGuid { get; set; }
///
- /// Gets or sets the mapping unique title.
- ///
- ///
/// The mapping unique title.
- ///
+ ///
public string MappingTitle { get; set; }
///
- /// Gets or sets the request match result.
- ///
- ///
/// The request match result.
- ///
+ ///
public LogRequestMatchModel RequestMatchResult { get; set; }
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Admin/Requests/LogRequestModel.cs b/src/WireMock.Net/Admin/Requests/LogRequestModel.cs
index c6e04fcc..20b4ea0a 100644
--- a/src/WireMock.Net/Admin/Requests/LogRequestModel.cs
+++ b/src/WireMock.Net/Admin/Requests/LogRequestModel.cs
@@ -11,52 +11,62 @@ namespace WireMock.Admin.Requests
public class LogRequestModel
{
///
- /// Gets the Client IP Address.
+ /// The Client IP Address.
///
public string ClientIP { get; set; }
///
- /// Gets the DateTime.
+ /// The DateTime.
///
public DateTime DateTime { get; set; }
///
- /// Gets or sets the Path.
+ /// The Path.
///
public string Path { get; set; }
///
- /// Gets or sets the absolete URL.
+ ///The absolete URL.
///
public string AbsoluteUrl { get; set; }
///
- /// Gets the query.
+ /// The query.
///
public IDictionary> Query { get; set; }
///
- /// Gets or sets the method.
+ /// The method.
///
public string Method { get; set; }
///
- /// Gets or sets the Headers.
+ /// The Headers.
///
public IDictionary> Headers { get; set; }
///
- /// Gets or sets the Cookies.
+ /// Tthe Cookies.
///
public IDictionary Cookies { get; set; }
///
- /// Gets or sets the body.
+ /// The body (as string).
///
public string Body { get; set; }
///
- /// Gets or sets the body encoding.
+ /// The body (as JSON object).
+ ///
+ public object BodyAsJson { get; set; }
+
+ ///
+ /// The body (as bytearray).
+ ///
+ public byte[] BodyAsBytes { get; set; }
+
+ ///
+ /// The body encoding.
///
public EncodingModel BodyEncoding { get; set; }
}
diff --git a/src/WireMock.Net/Admin/Requests/LogResponseModel.cs b/src/WireMock.Net/Admin/Requests/LogResponseModel.cs
index edb88a77..60190c63 100644
--- a/src/WireMock.Net/Admin/Requests/LogResponseModel.cs
+++ b/src/WireMock.Net/Admin/Requests/LogResponseModel.cs
@@ -25,12 +25,17 @@ namespace WireMock.Admin.Requests
public string BodyDestination { get; set; }
///
- /// Gets or sets the body.
+ /// The body (as string).
///
public string Body { get; set; }
///
- /// Gets or sets the body as bytes.
+ /// The body (as JSON object).
+ ///
+ public object BodyAsJson { get; set; }
+
+ ///
+ /// The body (as bytearray).
///
public byte[] BodyAsBytes { get; set; }
diff --git a/src/WireMock.Net/Http/HttpClientHelper.cs b/src/WireMock.Net/Http/HttpClientHelper.cs
index b7634efc..431ab487 100644
--- a/src/WireMock.Net/Http/HttpClientHelper.cs
+++ b/src/WireMock.Net/Http/HttpClientHelper.cs
@@ -4,8 +4,10 @@ using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
+using JetBrains.Annotations;
using Newtonsoft.Json;
using WireMock.HttpsCertificate;
+using WireMock.Util;
using WireMock.Validation;
namespace WireMock.Http
@@ -51,20 +53,36 @@ namespace WireMock.Http
return client;
}
- public static async Task SendAsync(HttpClient client, RequestMessage requestMessage, string url)
+ public static async Task SendAsync([NotNull] HttpClient client, [NotNull] RequestMessage requestMessage, string url)
{
Check.NotNull(client, nameof(client));
+ Check.NotNull(requestMessage, nameof(requestMessage));
var originalUri = new Uri(requestMessage.Url);
var requiredUri = new Uri(url);
var httpRequestMessage = new HttpRequestMessage(new HttpMethod(requestMessage.Method), url);
+ WireMockList contentTypeHeader = null;
+ bool contentTypeHeaderPresent = requestMessage.Headers.Any(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentType, StringComparison.OrdinalIgnoreCase));
+ if (contentTypeHeaderPresent)
+ {
+ contentTypeHeader = requestMessage.Headers[HttpKnownHeaderNames.ContentType];
+ }
+
// Set Body if present
if (requestMessage.BodyAsBytes != null)
{
httpRequestMessage.Content = new ByteArrayContent(requestMessage.BodyAsBytes);
}
+ else if (requestMessage.BodyAsJson != null)
+ {
+ httpRequestMessage.Content = new StringContent(JsonConvert.SerializeObject(requestMessage.BodyAsJson), requestMessage.BodyEncoding);
+ }
+ else if (requestMessage.Body != null)
+ {
+ httpRequestMessage.Content = new StringContent(requestMessage.Body, requestMessage.BodyEncoding);
+ }
// Overwrite the host header
httpRequestMessage.Headers.Host = requiredUri.Authority;
@@ -90,10 +108,13 @@ namespace WireMock.Http
// Set both content and response headers, replacing URLs in values
var headers = (httpResponseMessage.Content?.Headers.Union(httpResponseMessage.Headers) ?? Enumerable.Empty>>()).ToArray();
- var contentTypeHeader = headers.FirstOrDefault(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentType, StringComparison.OrdinalIgnoreCase));
if (httpResponseMessage.Content != null)
{
- SetBody(httpResponseMessage.Content, contentTypeHeader, responseMessage);
+ var stream = await httpResponseMessage.Content.ReadAsStreamAsync();
+ var body = await BodyParser.Parse(stream, contentTypeHeader?.FirstOrDefault());
+ responseMessage.Body = body.BodyAsString;
+ responseMessage.BodyAsJson = body.BodyAsJson;
+ responseMessage.BodyAsBytes = body.BodyAsBytes;
}
foreach (var header in headers)
@@ -115,41 +136,5 @@ namespace WireMock.Http
return responseMessage;
}
-
- private static async void SetBody(HttpContent content, KeyValuePair> contentTypeHeader, ResponseMessage responseMessage)
- {
- bool contentTypeIsDefault = contentTypeHeader.Equals(default(KeyValuePair>));
- string[] textContentTypes = { "text/", "application/xml", "application/javascript", "application/typescript", "application/xhtml+xml" };
-
- if (!contentTypeIsDefault && contentTypeHeader.Value.Any(value => textContentTypes.Any(t => value != null && value.StartsWith(t, StringComparison.OrdinalIgnoreCase))))
- {
- try
- {
- responseMessage.Body = await content.ReadAsStringAsync();
- }
- catch
- {
- // Reading as string failed, just get the ByteArray.
- responseMessage.BodyAsBytes = await content.ReadAsByteArrayAsync();
- }
- }
- else if (!contentTypeIsDefault && contentTypeHeader.Value.Any(value => value != null && value.StartsWith("application/json", StringComparison.OrdinalIgnoreCase)))
- {
- string stringContent = await content.ReadAsStringAsync();
- try
- {
- responseMessage.BodyAsJson = JsonConvert.DeserializeObject(stringContent, new JsonSerializerSettings { Formatting = Formatting.Indented });
- }
- catch
- {
- // JsonConvert failed, just set the Body as string.
- responseMessage.Body = stringContent;
- }
- }
- else
- {
- responseMessage.BodyAsBytes = await content.ReadAsByteArrayAsync();
- }
- }
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Owin/GlobalExceptionMiddleware.cs b/src/WireMock.Net/Owin/GlobalExceptionMiddleware.cs
index faf275ac..f2e790f4 100644
--- a/src/WireMock.Net/Owin/GlobalExceptionMiddleware.cs
+++ b/src/WireMock.Net/Owin/GlobalExceptionMiddleware.cs
@@ -1,5 +1,6 @@
using System;
using System.Threading.Tasks;
+using log4net;
using Newtonsoft.Json;
#if !NETSTANDARD
using Microsoft.Owin;
@@ -15,6 +16,7 @@ namespace WireMock.Owin
internal class GlobalExceptionMiddleware
#endif
{
+ private static readonly ILog Log = LogManager.GetLogger(typeof(GlobalExceptionMiddleware));
#if !NETSTANDARD
public GlobalExceptionMiddleware(OwinMiddleware next) : base(next) { }
#else
@@ -42,6 +44,7 @@ namespace WireMock.Owin
}
catch (Exception ex)
{
+ Log.Error("HttpStatusCode set to 500", ex);
await _responseMapper.MapAsync(new ResponseMessage { StatusCode = 500, Body = JsonConvert.SerializeObject(ex) }, ctx.Response);
}
}
diff --git a/src/WireMock.Net/Owin/OwinRequestMapper.cs b/src/WireMock.Net/Owin/OwinRequestMapper.cs
index 4ac662f3..ef086115 100644
--- a/src/WireMock.Net/Owin/OwinRequestMapper.cs
+++ b/src/WireMock.Net/Owin/OwinRequestMapper.cs
@@ -4,6 +4,7 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using WireMock.Util;
#if !NETSTANDARD
using Microsoft.Owin;
#else
@@ -16,7 +17,7 @@ namespace WireMock.Owin
///
/// OwinRequestMapper
///
- public class OwinRequestMapper
+ internal class OwinRequestMapper
{
///
/// MapAsync IOwinRequest to RequestMessage
@@ -43,20 +44,6 @@ namespace WireMock.Owin
#endif
string method = request.Method;
- string bodyAsString = null;
- byte[] body = null;
- Encoding bodyEncoding = null;
- if (ParseBody(method) && request.Body != null)
- {
- using (var streamReader = new StreamReader(request.Body))
- {
- bodyAsString = await streamReader.ReadToEndAsync();
- bodyEncoding = streamReader.CurrentEncoding;
- }
-
- body = bodyEncoding.GetBytes(bodyAsString);
- }
-
Dictionary headers = null;
if (request.Headers.Any())
{
@@ -77,10 +64,16 @@ namespace WireMock.Owin
}
}
- return new RequestMessage(url, method, clientIP, body, bodyAsString, bodyEncoding, headers, cookies) { DateTime = DateTime.Now };
+ BodyData body = null;
+ if (request.Body != null && ShouldParseBody(method))
+ {
+ body = await BodyParser.Parse(request.Body, request.ContentType);
+ }
+
+ return new RequestMessage(url, method, clientIP, body, headers, cookies) { DateTime = DateTime.Now };
}
- private bool ParseBody(string method)
+ private bool ShouldParseBody(string method)
{
/*
HEAD - No defined body semantics.
diff --git a/src/WireMock.Net/Owin/WireMockMiddleware.cs b/src/WireMock.Net/Owin/WireMockMiddleware.cs
index 881458d8..d4dd61c7 100644
--- a/src/WireMock.Net/Owin/WireMockMiddleware.cs
+++ b/src/WireMock.Net/Owin/WireMockMiddleware.cs
@@ -3,9 +3,11 @@ using System.Threading.Tasks;
using WireMock.Logging;
using WireMock.Matchers.Request;
using System.Linq;
+using log4net;
using WireMock.Matchers;
using WireMock.Util;
using Newtonsoft.Json;
+using WireMock.Http;
#if !NETSTANDARD
using Microsoft.Owin;
#else
@@ -20,6 +22,7 @@ namespace WireMock.Owin
internal class WireMockMiddleware
#endif
{
+ private static readonly ILog Log = LogManager.GetLogger(typeof(WireMockMiddleware));
private static readonly Task CompletedTask = Task.FromResult(false);
private readonly WireMockMiddlewareOptions _options;
@@ -95,6 +98,7 @@ namespace WireMock.Owin
if (targetMapping == null)
{
logRequest = true;
+ Log.Warn("HttpStatusCode set to 404 : No matching mapping found");
response = new ResponseMessage { StatusCode = 404, Body = "No matching mapping found" };
return;
}
@@ -103,9 +107,10 @@ namespace WireMock.Owin
if (targetMapping.IsAdminInterface && _options.AuthorizationMatcher != null)
{
- bool present = request.Headers.TryGetValue("Authorization", out WireMockList authorization);
+ bool present = request.Headers.TryGetValue(HttpKnownHeaderNames.Authorization, out WireMockList authorization);
if (!present || _options.AuthorizationMatcher.IsMatch(authorization.ToString()) < MatchScores.Perfect)
{
+ Log.Error("HttpStatusCode set to 401");
response = new ResponseMessage { StatusCode = 401 };
return;
}
@@ -125,6 +130,7 @@ namespace WireMock.Owin
}
catch (Exception ex)
{
+ Log.Error("HttpStatusCode set to 500", ex);
response = new ResponseMessage { StatusCode = 500, Body = JsonConvert.SerializeObject(ex) };
}
finally
diff --git a/src/WireMock.Net/RequestMessage.cs b/src/WireMock.Net/RequestMessage.cs
index 75177ca1..f2d3346b 100644
--- a/src/WireMock.Net/RequestMessage.cs
+++ b/src/WireMock.Net/RequestMessage.cs
@@ -60,15 +60,20 @@ namespace WireMock
public string RawQuery { get; }
///
- /// Gets the bodyAsBytes.
- ///
- public byte[] BodyAsBytes { get; }
-
- ///
- /// Gets the body.
+ /// The body as string.
///
public string Body { get; }
+ ///
+ /// The body (as JSON object).
+ ///
+ public object BodyAsJson { get; set; }
+
+ ///
+ /// The body (as bytearray).
+ ///
+ public byte[] BodyAsBytes { get; set; }
+
///
/// Gets the Host
///
@@ -90,10 +95,45 @@ namespace WireMock
public string Origin { get; }
///
- /// Gets the body encoding.
+ /// The body encoding.
///
public Encoding BodyEncoding { get; }
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The original url.
+ /// The HTTP method.
+ /// The client IP Address.
+ /// The body.
+ /// The headers.
+ /// The cookies.
+ public RequestMessage([NotNull] Uri url, [NotNull] string method, [NotNull] string clientIP, [CanBeNull] BodyData body, [CanBeNull] IDictionary headers = null, [CanBeNull] IDictionary 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 = WebUtility.UrlDecode(url.AbsolutePath);
+ Method = method.ToLower();
+ ClientIP = clientIP;
+
+ Body = body?.BodyAsString;
+ BodyEncoding = body?.Encoding;
+ BodyAsJson = body?.BodyAsJson;
+ BodyAsBytes = body?.BodyAsBytes;
+
+ Headers = headers?.ToDictionary(header => header.Key, header => new WireMockList(header.Value));
+ Cookies = cookies;
+ RawQuery = WebUtility.UrlDecode(url.Query);
+ Query = ParseQuery(RawQuery);
+ }
+
///
/// Initializes a new instance of the class.
///
diff --git a/src/WireMock.Net/ResponseBuilders/Response.cs b/src/WireMock.Net/ResponseBuilders/Response.cs
index 920869a9..f55181eb 100644
--- a/src/WireMock.Net/ResponseBuilders/Response.cs
+++ b/src/WireMock.Net/ResponseBuilders/Response.cs
@@ -247,16 +247,9 @@ namespace WireMock.ResponseBuilders
{
Check.NotNull(body, nameof(body));
- string jsonBody = JsonConvert.SerializeObject(body, new JsonSerializerSettings { Formatting = Formatting.None, NullValueHandling = NullValueHandling.Ignore });
-
- if (encoding != null && !encoding.Equals(Encoding.UTF8))
- {
- jsonBody = encoding.GetString(Encoding.UTF8.GetBytes(jsonBody));
- ResponseMessage.BodyEncoding = encoding;
- }
-
ResponseMessage.BodyDestination = null;
- ResponseMessage.Body = jsonBody;
+ ResponseMessage.BodyAsJson = body;
+ ResponseMessage.BodyEncoding = encoding;
return this;
}
diff --git a/src/WireMock.Net/Server/FluentMockServer.Admin.cs b/src/WireMock.Net/Server/FluentMockServer.Admin.cs
index 8202f58d..3f51c570 100644
--- a/src/WireMock.Net/Server/FluentMockServer.Admin.cs
+++ b/src/WireMock.Net/Server/FluentMockServer.Admin.cs
@@ -7,6 +7,7 @@ using System.Text;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
using WireMock.Admin.Mappings;
using WireMock.Admin.Requests;
using WireMock.Admin.Settings;
@@ -112,6 +113,7 @@ namespace WireMock.Server
foreach (string filename in Directory.EnumerateFiles(folder).OrderBy(f => f))
{
+ Log.InfoFormat("Reading Static MappingFile : '{0}'", filename);
ReadStaticMappingAndAddOrUpdate(filename);
}
}
@@ -133,17 +135,22 @@ namespace WireMock.Server
return;
}
- var watcher = new EnhancedFileSystemWatcher(folder, "*.json", 500);
+ Log.InfoFormat("Watching folder '{0}' for new, updated and deleted MappingFiles.", folder);
+
+ var watcher = new EnhancedFileSystemWatcher(folder, "*.json", 1000);
watcher.Created += (sender, args) =>
{
+ Log.InfoFormat("New MappingFile created : '{0}'", args.FullPath);
ReadStaticMappingAndAddOrUpdate(args.FullPath);
};
watcher.Changed += (sender, args) =>
{
+ Log.InfoFormat("New MappingFile updated : '{0}'", args.FullPath);
ReadStaticMappingAndAddOrUpdate(args.FullPath);
};
watcher.Deleted += (sender, args) =>
{
+ Log.InfoFormat("New MappingFile deleted : '{0}'", args.FullPath);
string filenameWithoutExtension = Path.GetFileNameWithoutExtension(args.FullPath);
if (Guid.TryParse(filenameWithoutExtension, out Guid guidFromFilename))
@@ -170,13 +177,14 @@ namespace WireMock.Server
string filenameWithoutExtension = Path.GetFileNameWithoutExtension(path);
+ MappingModel mappingModel = JsonConvert.DeserializeObject(FileHelper.ReadAllText(path));
if (Guid.TryParse(filenameWithoutExtension, out Guid guidFromFilename))
{
- DeserializeAndAddOrUpdateMapping(FileHelper.ReadAllText(path), guidFromFilename, path);
+ DeserializeAndAddOrUpdateMapping(mappingModel, guidFromFilename, path);
}
else
{
- DeserializeAndAddOrUpdateMapping(FileHelper.ReadAllText(path), null, path);
+ DeserializeAndAddOrUpdateMapping(mappingModel, null, path);
}
}
#endregion
@@ -256,7 +264,7 @@ namespace WireMock.Server
private ResponseMessage SettingsUpdate(RequestMessage requestMessage)
{
- var settings = JsonConvert.DeserializeObject(requestMessage.Body);
+ var settings = requestMessage.Body != null ? JsonConvert.DeserializeObject(requestMessage.Body) : ((JObject)requestMessage.BodyAsJson).ToObject();
if (settings.AllowPartialMapping != null)
_options.AllowPartialMapping = settings.AllowPartialMapping.Value;
@@ -280,6 +288,7 @@ namespace WireMock.Server
if (mapping == null)
{
+ Log.Warn("HttpStatusCode set to 404 : Mapping not found");
return new ResponseMessage { StatusCode = 404, Body = "Mapping not found" };
}
@@ -292,7 +301,8 @@ namespace WireMock.Server
{
Guid guid = Guid.Parse(requestMessage.Path.TrimStart(AdminMappings.ToCharArray()));
- DeserializeAndAddOrUpdateMapping(requestMessage.Body, guid);
+ MappingModel mappingModel = requestMessage.Body != null ? JsonConvert.DeserializeObject(requestMessage.Body) : ((JObject)requestMessage.BodyAsJson).ToObject();
+ DeserializeAndAddOrUpdateMapping(mappingModel, guid);
return new ResponseMessage { Body = "Mapping added or updated" };
}
@@ -330,10 +340,12 @@ namespace WireMock.Server
}
var model = MappingConverter.ToMappingModel(mapping);
- string json = JsonConvert.SerializeObject(model, _settings);
string filename = !string.IsNullOrEmpty(mapping.Title) ? SanitizeFileName(mapping.Title) : mapping.Guid.ToString();
- File.WriteAllText(Path.Combine(folder, filename + ".json"), json);
+ string filePath = Path.Combine(folder, filename + ".json");
+ Log.InfoFormat("Saving Mapping to file {0}", filePath);
+
+ File.WriteAllText(filePath, JsonConvert.SerializeObject(model, _settings));
}
private static string SanitizeFileName(string name, char replaceChar = '_')
@@ -357,24 +369,25 @@ namespace WireMock.Server
{
try
{
- DeserializeAndAddOrUpdateMapping(requestMessage.Body);
+ MappingModel mappingModel = requestMessage.Body != null ? JsonConvert.DeserializeObject(requestMessage.Body) : ((JObject)requestMessage.BodyAsJson).ToObject();
+ DeserializeAndAddOrUpdateMapping(mappingModel);
}
catch (ArgumentException a)
{
+ Log.Error("HttpStatusCode set to 400", a);
return new ResponseMessage { StatusCode = 400, Body = a.Message };
}
catch (Exception e)
{
+ Log.Error("HttpStatusCode set to 500", e);
return new ResponseMessage { StatusCode = 500, Body = e.ToString() };
}
return new ResponseMessage { StatusCode = 201, Body = "Mapping added" };
}
- private void DeserializeAndAddOrUpdateMapping(string json, Guid? guid = null, string path = null)
+ private void DeserializeAndAddOrUpdateMapping(MappingModel mappingModel, Guid? guid = null, string path = null)
{
- var mappingModel = JsonConvert.DeserializeObject(json);
-
Check.NotNull(mappingModel, nameof(mappingModel));
Check.NotNull(mappingModel.Request, nameof(mappingModel.Request));
Check.NotNull(mappingModel.Response, nameof(mappingModel.Response));
@@ -435,7 +448,10 @@ namespace WireMock.Server
var entry = LogEntries.FirstOrDefault(r => !r.RequestMessage.Path.StartsWith("/__admin/") && r.Guid == guid);
if (entry == null)
- return new ResponseMessage { StatusCode = 404, Body = "Request not found" };
+ {
+ Log.Warn("HttpStatusCode set to 404 : Request not found");
+ return new ResponseMessage {StatusCode = 404, Body = "Request not found"};
+ }
var model = ToLogEntryModel(entry);
@@ -477,6 +493,8 @@ namespace WireMock.Server
Query = logEntry.RequestMessage.Query,
Method = logEntry.RequestMessage.Method,
Body = logEntry.RequestMessage.Body,
+ BodyAsJson = logEntry.RequestMessage.BodyAsJson,
+ BodyAsBytes = logEntry.RequestMessage.BodyAsBytes,
Headers = logEntry.RequestMessage.Headers,
Cookies = logEntry.RequestMessage.Cookies,
BodyEncoding = logEntry.RequestMessage.BodyEncoding != null ? new EncodingModel
@@ -491,6 +509,7 @@ namespace WireMock.Server
StatusCode = logEntry.ResponseMessage.StatusCode,
BodyDestination = logEntry.ResponseMessage.BodyDestination,
Body = logEntry.ResponseMessage.Body,
+ BodyAsJson = logEntry.ResponseMessage.BodyAsJson,
BodyAsBytes = logEntry.ResponseMessage.BodyAsBytes,
BodyOriginal = logEntry.ResponseMessage.BodyOriginal,
BodyAsFile = logEntry.ResponseMessage.BodyAsFile,
@@ -531,7 +550,7 @@ namespace WireMock.Server
#region Requests/find
private ResponseMessage RequestsFind(RequestMessage requestMessage)
{
- var requestModel = JsonConvert.DeserializeObject(requestMessage.Body);
+ var requestModel = requestMessage.Body != null ? JsonConvert.DeserializeObject(requestMessage.Body) : ((JObject)requestMessage.BodyAsJson).ToObject();
var request = (Request)InitRequestBuilder(requestModel);
diff --git a/src/WireMock.Net/Server/FluentMockServer.cs b/src/WireMock.Net/Server/FluentMockServer.cs
index 0ed4e989..c1cc220d 100644
--- a/src/WireMock.Net/Server/FluentMockServer.cs
+++ b/src/WireMock.Net/Server/FluentMockServer.cs
@@ -6,6 +6,8 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using JetBrains.Annotations;
+using log4net;
+using Newtonsoft.Json;
using WireMock.Http;
using WireMock.Matchers;
using WireMock.Matchers.Request;
@@ -13,7 +15,6 @@ using WireMock.RequestBuilders;
using WireMock.Settings;
using WireMock.Validation;
using WireMock.Owin;
-using WireMock.Serialization;
namespace WireMock.Server
{
@@ -22,6 +23,7 @@ namespace WireMock.Server
///
public partial class FluentMockServer : IDisposable
{
+ private static readonly ILog Log = LogManager.GetLogger(typeof(FluentMockServer));
private const int ServerStartDelay = 100;
private readonly IOwinSelfHost _httpServer;
private readonly WireMockMiddlewareOptions _options = new WireMockMiddlewareOptions();
@@ -156,6 +158,8 @@ namespace WireMock.Server
private FluentMockServer(IFluentMockServerSettings settings)
{
+ Log.DebugFormat("WireMock.Net server settings {0}", JsonConvert.SerializeObject(settings, Formatting.Indented));
+
if (settings.Urls != null)
{
Urls = settings.Urls.Select(u => u.EndsWith("/") ? u : $"{u}/").ToArray();
@@ -315,9 +319,10 @@ namespace WireMock.Server
/// Allows the partial mapping.
///
[PublicAPI]
- public void AllowPartialMapping()
+ public void AllowPartialMapping(bool allow = true)
{
- _options.AllowPartialMapping = true;
+ Log.InfoFormat("AllowPartialMapping is set to {0}", allow);
+ _options.AllowPartialMapping = allow;
}
///
diff --git a/src/WireMock.Net/Settings/FluentMockServerSettings.cs b/src/WireMock.Net/Settings/FluentMockServerSettings.cs
index 2784e620..9ef91538 100644
--- a/src/WireMock.Net/Settings/FluentMockServerSettings.cs
+++ b/src/WireMock.Net/Settings/FluentMockServerSettings.cs
@@ -1,5 +1,6 @@
using System;
using JetBrains.Annotations;
+using Newtonsoft.Json;
namespace WireMock.Settings
{
@@ -63,10 +64,12 @@ namespace WireMock.Settings
///
[PublicAPI]
+ [JsonIgnore]
public Action