mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-03-29 21:31:45 +02:00
Rename to WireMock.Net
This commit is contained in:
110
src/WireMock.Net/Server/FluentMockServer.Admin.cs
Normal file
110
src/WireMock.Net/Server/FluentMockServer.Admin.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json;
|
||||
using WireMock.Admin;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
|
||||
namespace WireMock.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// The fluent mock server.
|
||||
/// </summary>
|
||||
public partial class FluentMockServer
|
||||
{
|
||||
private void InitAdmin()
|
||||
{
|
||||
Given(Request.Create().WithUrl("/__admin/mappings").UsingGet()).RespondWith(new DynamicResponseProvider(MappingsGet));
|
||||
}
|
||||
|
||||
private ResponseMessage MappingsGet()
|
||||
{
|
||||
var result = new List<MappingModel>();
|
||||
foreach (var mapping in Mappings.Where(m => !(m.Provider is DynamicResponseProvider)))
|
||||
{
|
||||
var request = (Request) mapping.RequestMatcher;
|
||||
var urlMatchers = request.GetRequestMessageMatchers<RequestMessageUrlMatcher>();
|
||||
var headerMatchers = request.GetRequestMessageMatchers<RequestMessageHeaderMatcher>();
|
||||
var cookieMatchers = request.GetRequestMessageMatchers<RequestMessageCookieMatcher>();
|
||||
var paramsMatchers = request.GetRequestMessageMatchers<RequestMessageParamMatcher>();
|
||||
var bodyMatcher = request.GetRequestMessageMatcher<RequestMessageBodyMatcher>();
|
||||
var verbMatcher = request.GetRequestMessageMatcher<RequestMessageVerbMatcher>();
|
||||
|
||||
var response = (Response) mapping.Provider;
|
||||
|
||||
var model = new MappingModel
|
||||
{
|
||||
Guid = Guid.NewGuid(),
|
||||
Request = new RequestModel
|
||||
{
|
||||
Url = new UrlModel
|
||||
{
|
||||
Matchers = urlMatchers != null ? Map(urlMatchers.Where(m => m.Matchers != null).SelectMany(m => m.Matchers)) : null
|
||||
},
|
||||
Verbs = verbMatcher != null ? verbMatcher.Verbs : new [] { "any" },
|
||||
Headers = headerMatchers?.Select(hm => new HeaderModel
|
||||
{
|
||||
Name = hm.Name,
|
||||
Matchers = Map(hm.Matchers)
|
||||
}).ToList(),
|
||||
Cookies = cookieMatchers?.Select(hm => new CookieModel
|
||||
{
|
||||
Name = hm.Name,
|
||||
Matchers = Map(hm.Matchers)
|
||||
}).ToList(),
|
||||
Params = paramsMatchers?.Select(hm => new ParamModel
|
||||
{
|
||||
Name = hm.Key,
|
||||
Values = hm.Values?.ToList()
|
||||
}).ToList(),
|
||||
Body = new BodyModel
|
||||
{
|
||||
Matcher = bodyMatcher != null ? Map(bodyMatcher.Matcher) : null
|
||||
}
|
||||
},
|
||||
Response = new ResponseModel
|
||||
{
|
||||
StatusCode = response.ResponseMessage.StatusCode,
|
||||
Headers = response.ResponseMessage.Headers,
|
||||
Body = response.ResponseMessage.Body
|
||||
}
|
||||
};
|
||||
|
||||
result.Add(model);
|
||||
}
|
||||
|
||||
return ToJson(result);
|
||||
}
|
||||
|
||||
private IList<MatcherModel> Map([CanBeNull] IEnumerable<IMatcher> matchers)
|
||||
{
|
||||
return matchers?.Select(Map).Where(x => x != null).ToList();
|
||||
}
|
||||
|
||||
private MatcherModel Map([CanBeNull] IMatcher matcher)
|
||||
{
|
||||
if (matcher == null)
|
||||
return null;
|
||||
|
||||
return new MatcherModel
|
||||
{
|
||||
Name = matcher.GetType().Name,
|
||||
Pattern = matcher.GetPattern()
|
||||
};
|
||||
}
|
||||
|
||||
private ResponseMessage ToJson<T>(T result)
|
||||
{
|
||||
return new ResponseMessage
|
||||
{
|
||||
Body = JsonConvert.SerializeObject(result, Formatting.Indented),
|
||||
StatusCode = 200,
|
||||
Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } }
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
272
src/WireMock.Net/Server/FluentMockServer.cs
Normal file
272
src/WireMock.Net/Server/FluentMockServer.cs
Normal file
@@ -0,0 +1,272 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Http;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// The fluent mock server.
|
||||
/// </summary>
|
||||
public partial class FluentMockServer
|
||||
{
|
||||
/// <summary>
|
||||
/// The _http server.
|
||||
/// </summary>
|
||||
private readonly TinyHttpServer _httpServer;
|
||||
|
||||
/// <summary>
|
||||
/// The _mappings.
|
||||
/// </summary>
|
||||
private readonly IList<Mapping> _mappings = new List<Mapping>();
|
||||
|
||||
/// <summary>
|
||||
/// The _request logs.
|
||||
/// </summary>
|
||||
private readonly IList<RequestMessage> _requestLogs = new List<RequestMessage>();
|
||||
|
||||
/// <summary>
|
||||
/// The _request mapper.
|
||||
/// </summary>
|
||||
private readonly HttpListenerRequestMapper _requestMapper = new HttpListenerRequestMapper();
|
||||
|
||||
/// <summary>
|
||||
/// The _response mapper.
|
||||
/// </summary>
|
||||
private readonly HttpListenerResponseMapper _responseMapper = new HttpListenerResponseMapper();
|
||||
|
||||
/// <summary>
|
||||
/// The _sync root.
|
||||
/// </summary>
|
||||
private readonly object _syncRoot = new object();
|
||||
|
||||
/// <summary>
|
||||
/// The _request processing delay.
|
||||
/// </summary>
|
||||
private TimeSpan _requestProcessingDelay = TimeSpan.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the port.
|
||||
/// </summary>
|
||||
public int Port { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the request logs.
|
||||
/// </summary>
|
||||
public IEnumerable<RequestMessage> RequestLogs
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (((ICollection)_requestLogs).SyncRoot)
|
||||
{
|
||||
return new ReadOnlyCollection<RequestMessage>(_requestLogs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the routes.
|
||||
/// </summary>
|
||||
public IEnumerable<Mapping> Mappings
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (((ICollection)_mappings).SyncRoot)
|
||||
{
|
||||
return new ReadOnlyCollection<Mapping>(_mappings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start this FluentMockServer.
|
||||
/// </summary>
|
||||
/// <param name="port">The port.</param>
|
||||
/// <param name="ssl">The SSL support.</param>
|
||||
/// <returns>The <see cref="FluentMockServer"/>.</returns>
|
||||
[PublicAPI]
|
||||
public static FluentMockServer Start(int port = 0, bool ssl = false)
|
||||
{
|
||||
Check.Condition(port, p => p >= 0, nameof(port));
|
||||
|
||||
if (port == 0)
|
||||
port = Ports.FindFreeTcpPort();
|
||||
|
||||
return new FluentMockServer(false, port, ssl);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start this FluentMockServer with the admin interface.
|
||||
/// </summary>
|
||||
/// <param name="port">The port.</param>
|
||||
/// <param name="ssl">The SSL support.</param>
|
||||
/// <returns>The <see cref="FluentMockServer"/>.</returns>
|
||||
[PublicAPI]
|
||||
public static FluentMockServer StartWithAdminInterface(int port = 0, bool ssl = false)
|
||||
{
|
||||
Check.Condition(port, p => p >= 0, nameof(port));
|
||||
|
||||
if (port == 0)
|
||||
port = Ports.FindFreeTcpPort();
|
||||
|
||||
return new FluentMockServer(true, port, ssl);
|
||||
}
|
||||
|
||||
private FluentMockServer(bool startAdmin, int port, bool ssl)
|
||||
{
|
||||
string protocol = ssl ? "https" : "http";
|
||||
_httpServer = new TinyHttpServer(protocol + "://localhost:" + port + "/", HandleRequestAsync);
|
||||
Port = port;
|
||||
_httpServer.Start();
|
||||
|
||||
if (startAdmin)
|
||||
{
|
||||
InitAdmin();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop this server.
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
_httpServer.Stop();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The reset.
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
lock (((ICollection)_requestLogs).SyncRoot)
|
||||
{
|
||||
_requestLogs.Clear();
|
||||
}
|
||||
|
||||
lock (((ICollection)_mappings).SyncRoot)
|
||||
{
|
||||
_mappings.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The search logs for.
|
||||
/// </summary>
|
||||
/// <param name="spec">
|
||||
/// The matcher.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The <see cref="IEnumerable"/>.
|
||||
/// </returns>
|
||||
public IEnumerable<RequestMessage> SearchLogsFor(IRequestMatcher spec)
|
||||
{
|
||||
lock (((ICollection)_requestLogs).SyncRoot)
|
||||
{
|
||||
return _requestLogs.Where(spec.IsMatch);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The add request processing delay.
|
||||
/// </summary>
|
||||
/// <param name="delay">
|
||||
/// The delay.
|
||||
/// </param>
|
||||
public void AddRequestProcessingDelay(TimeSpan delay)
|
||||
{
|
||||
lock (_syncRoot)
|
||||
{
|
||||
_requestProcessingDelay = delay;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The given.
|
||||
/// </summary>
|
||||
/// <param name="requestMatcher">The request matcher.</param>
|
||||
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
|
||||
public IRespondWithAProvider Given(IRequestMatcher requestMatcher)
|
||||
{
|
||||
return new RespondWithAProvider(RegisterMapping, requestMatcher);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The register mapping.
|
||||
/// </summary>
|
||||
/// <param name="mapping">
|
||||
/// The mapping.
|
||||
/// </param>
|
||||
private void RegisterMapping(Mapping mapping)
|
||||
{
|
||||
lock (((ICollection)_mappings).SyncRoot)
|
||||
{
|
||||
_mappings.Add(mapping);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The log request.
|
||||
/// </summary>
|
||||
/// <param name="requestMessage">
|
||||
/// The request.
|
||||
/// </param>
|
||||
private void LogRequest(RequestMessage requestMessage)
|
||||
{
|
||||
lock (((ICollection)_requestLogs).SyncRoot)
|
||||
{
|
||||
_requestLogs.Add(requestMessage);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The handle request.
|
||||
/// </summary>
|
||||
/// <param name="ctx">The HttpListenerContext.</param>
|
||||
private async void HandleRequestAsync(HttpListenerContext ctx)
|
||||
{
|
||||
lock (_syncRoot)
|
||||
{
|
||||
Task.Delay(_requestProcessingDelay).Wait();
|
||||
}
|
||||
|
||||
var request = _requestMapper.Map(ctx.Request);
|
||||
LogRequest(request);
|
||||
|
||||
try
|
||||
{
|
||||
var targetRoute = _mappings.FirstOrDefault(route => route.IsRequestHandled(request));
|
||||
if (targetRoute == null)
|
||||
{
|
||||
ctx.Response.StatusCode = 404;
|
||||
|
||||
byte[] content = Encoding.UTF8.GetBytes("No mapping found");
|
||||
ctx.Response.OutputStream.Write(content, 0, content.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
var response = await targetRoute.ResponseTo(request);
|
||||
_responseMapper.Map(response, ctx.Response);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ctx.Response.StatusCode = 500;
|
||||
|
||||
byte[] content = Encoding.UTF8.GetBytes(ex.ToString());
|
||||
ctx.Response.OutputStream.Write(content, 0, content.Length);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ctx.Response.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
16
src/WireMock.Net/Server/IRespondWithAProvider.cs
Normal file
16
src/WireMock.Net/Server/IRespondWithAProvider.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace WireMock.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// IRespondWithAProvider
|
||||
/// </summary>
|
||||
public interface IRespondWithAProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// The respond with.
|
||||
/// </summary>
|
||||
/// <param name="provider">
|
||||
/// The provider.
|
||||
/// </param>
|
||||
void RespondWith(IResponseProvider provider);
|
||||
}
|
||||
}
|
||||
42
src/WireMock.Net/Server/RespondWithAProvider.cs
Normal file
42
src/WireMock.Net/Server/RespondWithAProvider.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using WireMock.Matchers.Request;
|
||||
|
||||
namespace WireMock.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// The respond with a provider.
|
||||
/// </summary>
|
||||
internal class RespondWithAProvider : IRespondWithAProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// The _registration callback.
|
||||
/// </summary>
|
||||
private readonly RegistrationCallback _registrationCallback;
|
||||
|
||||
/// <summary>
|
||||
/// The _request matcher.
|
||||
/// </summary>
|
||||
private readonly IRequestMatcher _requestMatcher;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RespondWithAProvider"/> class.
|
||||
/// </summary>
|
||||
/// <param name="registrationCallback">The registration callback.</param>
|
||||
/// <param name="requestMatcher">The request matcher.</param>
|
||||
public RespondWithAProvider(RegistrationCallback registrationCallback, IRequestMatcher requestMatcher)
|
||||
{
|
||||
_registrationCallback = registrationCallback;
|
||||
_requestMatcher = requestMatcher;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The respond with.
|
||||
/// </summary>
|
||||
/// <param name="provider">
|
||||
/// The provider.
|
||||
/// </param>
|
||||
public void RespondWith(IResponseProvider provider)
|
||||
{
|
||||
_registrationCallback(new Mapping(_requestMatcher, provider));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user