Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Body Encoding #24

Merged
merged 2 commits into from
Feb 25, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions src/WireMock.Net/Admin/Mappings/EncodingModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System.Text;

namespace WireMock.Admin.Mappings
{
/// <summary>
/// EncodingModel
/// </summary>
public class EncodingModel
{
/// <summary>
/// Encoding CodePage
/// </summary>
public int CodePage { get; set; }
/// <summary>
/// Encoding EncodingName
/// </summary>
public string EncodingName { get; set; }
/// <summary>
/// Encoding WebName
/// </summary>
public string WebName { get; set; }
}
}
9 changes: 9 additions & 0 deletions src/WireMock.Net/Admin/Mappings/ResponseModel.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Text;

namespace WireMock.Admin.Mappings
{
Expand Down Expand Up @@ -39,6 +40,14 @@ public class ResponseModel
/// </value>
public object BodyAsJson { 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>
Expand Down
10 changes: 10 additions & 0 deletions src/WireMock.Net/Admin/Requests/LogRequestModel.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text;
using WireMock.Admin.Mappings;
using WireMock.Util;

namespace WireMock.Admin.Requests
Expand Down Expand Up @@ -66,5 +68,13 @@ public class LogRequestModel
/// 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; }
}
}
7 changes: 7 additions & 0 deletions src/WireMock.Net/Admin/Requests/LogResponseModel.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Collections.Generic;
using System.Text;
using WireMock.Admin.Mappings;

namespace WireMock.Admin.Requests
{
Expand Down Expand Up @@ -26,5 +28,10 @@ public class LogResponseModel
/// Gets or sets the original body.
/// </summary>
public string BodyOriginal { get; set; }

/// <summary>
/// Gets or sets the body.
/// </summary>
public EncodingModel BodyEncoding { get; set; }
}
}
9 changes: 5 additions & 4 deletions src/WireMock.Net/HttpListenerRequestMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.IO;
using System.Linq;
using System.Net;
using System.Text;

namespace WireMock
{
Expand All @@ -21,16 +22,16 @@ public RequestMessage Map(HttpListenerRequest listenerRequest)
Uri url = listenerRequest.Url;
string verb = listenerRequest.HttpMethod;
byte[] body = GetRequestBody(listenerRequest);
string bodyAsString = body != null ? listenerRequest.ContentEncoding.GetString(body) : null;
Encoding bodyEncoding = body != null ? listenerRequest.ContentEncoding : null;
string bodyAsString = bodyEncoding?.GetString(body);
var listenerHeaders = listenerRequest.Headers;
var headers = listenerHeaders.AllKeys.ToDictionary(k => k, k => listenerHeaders[k]);
var cookies = new Dictionary<string, string>();

foreach (Cookie cookie in listenerRequest.Cookies)
cookies.Add(cookie.Name, cookie.Value);

var message = new RequestMessage(url, verb, body, bodyAsString, headers, cookies) { DateTime = DateTime.Now };

return message;
return new RequestMessage(url, verb, body, bodyAsString, bodyEncoding, headers, cookies) { DateTime = DateTime.Now };
}

/// <summary>
Expand Down
18 changes: 10 additions & 8 deletions src/WireMock.Net/HttpListenerResponseMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,16 @@ public void Map(ResponseMessage responseMessage, HttpListenerResponse listenerRe

responseMessage.Headers.ToList().ForEach(pair => listenerResponse.AddHeader(pair.Key, pair.Value));

if (responseMessage.Body != null)
{
byte[] buffer = _utf8NoBom.GetBytes(responseMessage.Body);
listenerResponse.ContentEncoding = _utf8NoBom;
listenerResponse.ContentLength64 = buffer.Length;
listenerResponse.OutputStream.Write(buffer, 0, buffer.Length);
listenerResponse.OutputStream.Flush();
}
if (responseMessage.Body == null)
return;

var encoding = responseMessage.BodyEncoding ?? _utf8NoBom;
byte[] buffer = encoding.GetBytes(responseMessage.Body);

listenerResponse.ContentEncoding = encoding;
listenerResponse.ContentLength64 = buffer.Length;
listenerResponse.OutputStream.Write(buffer, 0, buffer.Length);
listenerResponse.OutputStream.Flush();
}
}
}
10 changes: 9 additions & 1 deletion src/WireMock.Net/RequestMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using JetBrains.Annotations;
using WireMock.Util;
using WireMock.Validation;
using System.Text;

namespace WireMock
{
Expand Down Expand Up @@ -57,16 +58,22 @@ public class RequestMessage
/// </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="verb">The verb.</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 verb, [CanBeNull] byte[] bodyAsBytes = null, [CanBeNull] string body = null, [CanBeNull] IDictionary<string, string> headers = null, [CanBeNull] IDictionary<string, string> cookies = null)
public RequestMessage([NotNull] Uri url, [NotNull] string verb, [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(verb, nameof(verb));
Expand All @@ -76,6 +83,7 @@ public RequestMessage([NotNull] Uri url, [NotNull] string verb, [CanBeNull] byte
Method = verb.ToLower();
BodyAsBytes = bodyAsBytes;
Body = body;
BodyEncoding = bodyEncoding;
Headers = headers;
Cookies = cookies;

Expand Down
6 changes: 4 additions & 2 deletions src/WireMock.Net/ResponseBuilders/IBodyResponseBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,17 @@ public interface IBodyResponseBuilder : ITransformResponseBuilder
/// The with body.
/// </summary>
/// <param name="body">The body.</param>
/// <param name="encoding">The body encoding.</param>
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
IResponseBuilder WithBody([NotNull] string body);
IResponseBuilder WithBody([NotNull] string body, [CanBeNull] Encoding encoding = null);

/// <summary>
/// The with body.
/// </summary>
/// <param name="body">The body.</param>
/// <param name="encoding">The body encoding.</param>
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
IResponseBuilder WithBodyAsJson([NotNull] object body);
IResponseBuilder WithBodyAsJson([NotNull] object body, [CanBeNull] Encoding encoding = null);

/// <summary>
/// The with body as base64.
Expand Down
25 changes: 21 additions & 4 deletions src/WireMock.Net/ResponseBuilders/Response.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,25 +143,38 @@ public IResponseBuilder WithHeaders(IDictionary<string, string> headers)
/// 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)
public IResponseBuilder WithBody(string body, Encoding encoding = null)
{
Check.NotNull(body, nameof(body));

ResponseMessage.Body = body;
ResponseMessage.BodyEncoding = encoding ?? Encoding.UTF8;

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>
public IResponseBuilder WithBodyAsJson(object body)
public IResponseBuilder WithBodyAsJson(object body, Encoding encoding = null)
{
Check.NotNull(body, nameof(body));

ResponseMessage.Body = JsonConvert.SerializeObject(body, new JsonSerializerSettings { Formatting = Formatting.None, NullValueHandling = NullValueHandling.Ignore });
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.Body = jsonBody;

return this;
}

Expand All @@ -175,7 +188,11 @@ public IResponseBuilder WithBodyAsBase64(string bodyAsbase64, Encoding encoding
{
Check.NotNull(bodyAsbase64, nameof(bodyAsbase64));

ResponseMessage.Body = (encoding ?? Encoding.UTF8).GetString(Convert.FromBase64String(bodyAsbase64));
encoding = encoding ?? Encoding.UTF8;

ResponseMessage.Body = encoding.GetString(Convert.FromBase64String(bodyAsbase64));
ResponseMessage.BodyEncoding = encoding;

return this;
}

Expand Down
7 changes: 7 additions & 0 deletions src/WireMock.Net/ResponseMessage.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text;

namespace WireMock
{
/// <summary>
Expand Down Expand Up @@ -27,6 +29,11 @@ public class ResponseMessage
/// </summary>
public string Body { get; set; }

/// <summary>
/// Gets or sets the body encoding.
/// </summary>
public Encoding BodyEncoding { get; set; } = new UTF8Encoding(false);

/// <summary>
/// The add header.
/// </summary>
Expand Down
37 changes: 31 additions & 6 deletions src/WireMock.Net/Server/FluentMockServer.Admin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using JetBrains.Annotations;
using Newtonsoft.Json;
using SimMetrics.Net;
Expand Down Expand Up @@ -292,14 +293,26 @@ private LogEntryModel ToLogEntryModel(LogEntry logEntry)
Method = logEntry.RequestMessage.Method,
Body = logEntry.RequestMessage.Body,
Headers = logEntry.RequestMessage.Headers,
Cookies = logEntry.RequestMessage.Cookies
Cookies = logEntry.RequestMessage.Cookies,
BodyEncoding = logEntry.RequestMessage.BodyEncoding != null ? new EncodingModel
{
EncodingName = logEntry.RequestMessage.BodyEncoding.EncodingName,
CodePage = logEntry.RequestMessage.BodyEncoding.CodePage,
WebName = logEntry.RequestMessage.BodyEncoding.WebName
} : null
},
Response = new LogResponseModel
{
StatusCode = logEntry.ResponseMessage.StatusCode,
Body = logEntry.ResponseMessage.Body,
BodyOriginal = logEntry.ResponseMessage.BodyOriginal,
Headers = logEntry.ResponseMessage.Headers
Headers = logEntry.ResponseMessage.Headers,
BodyEncoding = logEntry.ResponseMessage.BodyEncoding != null ? new EncodingModel
{
EncodingName = logEntry.ResponseMessage.BodyEncoding.EncodingName,
CodePage = logEntry.ResponseMessage.BodyEncoding.CodePage,
WebName = logEntry.ResponseMessage.BodyEncoding.WebName
} : null
},
MappingGuid = logEntry.MappingGuid,
RequestMatchResult = logEntry.RequestMatchResult != null ? new LogRequestMatchModel
Expand Down Expand Up @@ -418,11 +431,11 @@ private IResponseBuilder InitResponseBuilder(ResponseModel responseModel)
responseBuilder = responseBuilder.WithHeaders(responseModel.Headers);

if (responseModel.Body != null)
responseBuilder = responseBuilder.WithBody(responseModel.Body);
responseBuilder = responseBuilder.WithBody(responseModel.Body, ToEncoding(responseModel.BodyEncoding));
else if (responseModel.BodyAsJson != null)
responseBuilder = responseBuilder.WithBodyAsJson(responseModel.BodyAsJson);
responseBuilder = responseBuilder.WithBodyAsJson(responseModel.BodyAsJson, ToEncoding(responseModel.BodyEncoding));
else if (responseModel.BodyAsBase64 != null)
responseBuilder = responseBuilder.WithBodyAsBase64(responseModel.BodyAsBase64);
responseBuilder = responseBuilder.WithBodyAsBase64(responseModel.BodyAsBase64, ToEncoding(responseModel.BodyEncoding));

if (responseModel.UseTransformer)
responseBuilder = responseBuilder.WithTransformer();
Expand Down Expand Up @@ -500,7 +513,14 @@ private MappingModel ToMappingModel(Mapping mapping)
Headers = response.ResponseMessage.Headers,
Body = response.ResponseMessage.Body,
UseTransformer = response.UseTransformer,
Delay = response.Delay?.Milliseconds
Delay = response.Delay?.Milliseconds,

BodyEncoding = response.ResponseMessage.BodyEncoding != null ? new EncodingModel
{
EncodingName = response.ResponseMessage.BodyEncoding.EncodingName,
CodePage = response.ResponseMessage.BodyEncoding.CodePage,
WebName = response.ResponseMessage.BodyEncoding.WebName
} : null
}
};
}
Expand Down Expand Up @@ -590,5 +610,10 @@ private ResponseMessage ToJson<T>(T result)
Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } }
};
}

private Encoding ToEncoding(EncodingModel encodingModel)
{
return encodingModel != null ? Encoding.GetEncoding(encodingModel.CodePage) : null;
}
}
}
26 changes: 26 additions & 0 deletions test/WireMock.Net.Tests/HttpListenerResponseMapperTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using NFluent;
Expand Down Expand Up @@ -67,6 +68,31 @@ public void Should_map_body_from_original_response()
Check.That(contentTask.Result).IsEqualTo("Hello !!!");
}

[Test]
public void Should_map_encoded_body_from_original_response()
{
// given
var response = new ResponseMessage
{
Body = "Hello !!!",
BodyEncoding = Encoding.ASCII
};

var httpListenerResponse = CreateHttpListenerResponse();

// when
new HttpListenerResponseMapper().Map(response, httpListenerResponse);

// then
Check.That(httpListenerResponse.ContentEncoding).Equals(Encoding.ASCII);

var responseMessage = ToResponseMessage(httpListenerResponse);
Check.That(responseMessage).IsNotNull();

var contentTask = responseMessage.Content.ReadAsStringAsync();
Check.That(contentTask.Result).IsEqualTo("Hello !!!");
}

[TearDown]
public void StopServer()
{
Expand Down
Loading