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.Http;
using WireMock.Settings;
using WireMock.Transformers;
using WireMock.Util;
using WireMock.Validation;
namespace WireMock.ResponseBuilders
{
///
/// The Response.
///
public class Response : IResponseBuilder
{
private HttpClient _httpClientForProxy;
///
/// The delay
///
public TimeSpan? Delay { get; private set; }
///
/// Gets a value indicating whether [use transformer].
///
public bool UseTransformer { get; private set; }
///
/// The Proxy URL to use.
///
public string ProxyUrl { get; private set; }
///
/// The client X509Certificate2 Thumbprint or SubjectName to use.
///
public string ClientX509Certificate2ThumbprintOrSubjectName { get; private set; }
///
/// Gets the response message.
///
public ResponseMessage ResponseMessage { get; }
///
/// A delegate to execute to generate the response.
///
public Func Callback { get; private set; }
///
/// Defines if the method WithCallback(...) is used.
///
public bool WithCallbackUsed { get; private set; }
///
/// Creates this instance.
///
/// ResponseMessage
/// A .
[PublicAPI]
public static IResponseBuilder Create([CanBeNull] ResponseMessage responseMessage = null)
{
var message = responseMessage ?? new ResponseMessage { StatusCode = (int)HttpStatusCode.OK };
return new Response(message);
}
///
/// Creates this instance with the specified function.
///
/// The callback function.
/// A .
[PublicAPI]
public static IResponseBuilder Create([NotNull] Func func)
{
Check.NotNull(func, nameof(func));
return new Response(func());
}
///
/// Initializes a new instance of the class.
///
///
/// The response.
///
private Response(ResponseMessage responseMessage)
{
ResponseMessage = responseMessage;
}
///
/// The with status code.
///
/// The code.
/// A .\
[PublicAPI]
public IResponseBuilder WithStatusCode(int code)
{
ResponseMessage.StatusCode = code;
return this;
}
///
/// The with status code.
///
/// The code.
/// A .
[PublicAPI]
public IResponseBuilder WithStatusCode(HttpStatusCode code)
{
return WithStatusCode((int)code);
}
///
/// The with Success status code (200).
///
/// A .
[PublicAPI]
public IResponseBuilder WithSuccess()
{
return WithStatusCode((int)HttpStatusCode.OK);
}
///
/// The with NotFound status code (404).
///
/// The .
[PublicAPI]
public IResponseBuilder WithNotFound()
{
return WithStatusCode((int)HttpStatusCode.NotFound);
}
///
public IResponseBuilder WithHeader(string name, params string[] values)
{
Check.NotNull(name, nameof(name));
ResponseMessage.AddHeader(name, values);
return this;
}
///
public IResponseBuilder WithHeaders(IDictionary headers)
{
Check.NotNull(headers, nameof(headers));
ResponseMessage.Headers = headers.ToDictionary(header => header.Key, header => new WireMockList(header.Value));
return this;
}
///
public IResponseBuilder WithHeaders(IDictionary headers)
{
Check.NotNull(headers, nameof(headers));
ResponseMessage.Headers = headers.ToDictionary(header => header.Key, header => new WireMockList(header.Value));
return this;
}
///
public IResponseBuilder WithHeaders(IDictionary> headers)
{
ResponseMessage.Headers = headers;
return this;
}
///
public IResponseBuilder WithBody(Func bodyFactory, string destination = BodyDestinationFormat.SameAsSource, Encoding encoding = null)
{
Check.NotNull(bodyFactory, nameof(bodyFactory));
return WithCallbackInternal(false, req => new ResponseMessage
{
BodyData = new BodyData
{
DetectedBodyType = BodyType.String,
BodyAsString = bodyFactory(req),
Encoding = encoding ?? Encoding.UTF8
}
});
}
///
public IResponseBuilder WithBody(byte[] body, string destination = BodyDestinationFormat.SameAsSource, Encoding encoding = null)
{
Check.NotNull(body, nameof(body));
ResponseMessage.BodyDestination = destination;
ResponseMessage.BodyData = new BodyData();
switch (destination)
{
case BodyDestinationFormat.String:
var enc = encoding ?? Encoding.UTF8;
ResponseMessage.BodyData.DetectedBodyType = BodyType.String;
ResponseMessage.BodyData.BodyAsString = enc.GetString(body);
ResponseMessage.BodyData.Encoding = enc;
break;
default:
ResponseMessage.BodyData.DetectedBodyType = BodyType.Bytes;
ResponseMessage.BodyData.BodyAsBytes = body;
break;
}
return this;
}
///
public IResponseBuilder WithBodyFromFile(string filename, bool cache = true)
{
Check.NotNull(filename, nameof(filename));
ResponseMessage.BodyData = new BodyData
{
BodyAsFileIsCached = cache
};
if (cache)
{
ResponseMessage.BodyData.DetectedBodyType = BodyType.Bytes;
ResponseMessage.BodyData.BodyAsBytes = File.ReadAllBytes(filename);
}
else
{
ResponseMessage.BodyData.DetectedBodyType = BodyType.File;
ResponseMessage.BodyData.BodyAsFile = filename;
}
return this;
}
///
public IResponseBuilder WithBody(string body, string destination = BodyDestinationFormat.SameAsSource, Encoding encoding = null)
{
Check.NotNull(body, nameof(body));
encoding = encoding ?? Encoding.UTF8;
ResponseMessage.BodyDestination = destination;
ResponseMessage.BodyData = new BodyData
{
Encoding = encoding
};
switch (destination)
{
case BodyDestinationFormat.Bytes:
ResponseMessage.BodyData.DetectedBodyType = BodyType.Bytes;
ResponseMessage.BodyData.BodyAsBytes= encoding.GetBytes(body);
break;
case BodyDestinationFormat.Json:
ResponseMessage.BodyData.DetectedBodyType = BodyType.Json;
ResponseMessage.BodyData.BodyAsJson = JsonConvert.DeserializeObject(body);
break;
default:
ResponseMessage.BodyData.DetectedBodyType = BodyType.String;
ResponseMessage.BodyData.BodyAsString = body;
break;
}
return this;
}
///
public IResponseBuilder WithBodyAsJson(object body, Encoding encoding = null, bool? indented = null)
{
Check.NotNull(body, nameof(body));
ResponseMessage.BodyDestination = null;
ResponseMessage.BodyData = new BodyData
{
Encoding = encoding,
DetectedBodyType = BodyType.Json,
BodyAsJson = body,
BodyAsJsonIndented = indented
};
return this;
}
///
public IResponseBuilder WithBodyAsJson(object body, bool indented)
{
return WithBodyAsJson(body, null, indented);
}
///
public IResponseBuilder WithBodyFromBase64(string bodyAsBase64, Encoding encoding = null)
{
Check.NotNull(bodyAsBase64, nameof(bodyAsBase64));
encoding = encoding ?? Encoding.UTF8;
ResponseMessage.BodyData = new BodyData
{
Encoding = encoding,
DetectedBodyType = BodyType.String,
BodyAsString = encoding.GetString(Convert.FromBase64String(bodyAsBase64))
};
return this;
}
///
public IResponseBuilder WithTransformer()
{
UseTransformer = true;
return this;
}
///
public IResponseBuilder WithDelay(TimeSpan delay)
{
Check.Condition(delay, d => d > TimeSpan.Zero, nameof(delay));
Delay = delay;
return this;
}
///
public IResponseBuilder WithDelay(int milliseconds)
{
return WithDelay(TimeSpan.FromMilliseconds(milliseconds));
}
///
public IResponseBuilder WithProxy(string proxyUrl, string clientX509Certificate2ThumbprintOrSubjectName = null)
{
Check.NotNullOrEmpty(proxyUrl, nameof(proxyUrl));
ProxyUrl = proxyUrl;
ClientX509Certificate2ThumbprintOrSubjectName = clientX509Certificate2ThumbprintOrSubjectName;
_httpClientForProxy = HttpClientHelper.CreateHttpClient(clientX509Certificate2ThumbprintOrSubjectName);
return this;
}
///
public IResponseBuilder WithProxy(IProxyAndRecordSettings settings)
{
Check.NotNull(settings, nameof(settings));
return WithProxy(settings.Url, settings.ClientX509Certificate2ThumbprintOrSubjectName);
}
///
public IResponseBuilder WithCallback(Func callbackHandler)
{
Check.NotNull(callbackHandler, nameof(callbackHandler));
return WithCallbackInternal(true, callbackHandler);
}
///
private IResponseBuilder WithCallbackInternal(bool withCallbackUsed, Func callbackHandler)
{
Check.NotNull(callbackHandler, nameof(callbackHandler));
WithCallbackUsed = withCallbackUsed;
Callback = callbackHandler;
return this;
}
///
/// The provide response.
///
/// The request.
/// The .
public async Task ProvideResponseAsync(RequestMessage requestMessage)
{
Check.NotNull(requestMessage, nameof(requestMessage));
if (Delay != null)
{
await Task.Delay(Delay.Value);
}
if (Callback != null)
{
var callbackResponseMessage = Callback(requestMessage);
if (!WithCallbackUsed)
{
// Copy StatusCode from ResponseMessage
callbackResponseMessage.StatusCode = ResponseMessage.StatusCode;
// Copy Headers from ResponseMessage (if defined)
if (ResponseMessage.Headers != null)
{
callbackResponseMessage.Headers = ResponseMessage.Headers;
}
}
return callbackResponseMessage;
}
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(_httpClientForProxy, requestMessage, proxyUriWithRequestPathAndQuery.AbsoluteUri);
}
if (UseTransformer)
{
return ResponseMessageTransformer.Transform(requestMessage, ResponseMessage);
}
// Just return normal defined ResponseMessage
return ResponseMessage;
}
}
}