Summary

Class:WireMock.Server.FluentMockServer
Assembly:WireMock.Net
File(s):C:\Users\StefHeyenrath\Documents\GitHub\WireMock.Net\src\WireMock.Net\Server\FluentMockServer.Admin.cs
C:\Users\StefHeyenrath\Documents\GitHub\WireMock.Net\src\WireMock.Net\Server\FluentMockServer.cs
C:\Users\StefHeyenrath\Documents\GitHub\WireMock.Net\src\WireMock.Net\Server\FluentMockServer.LogEntries.cs
Covered lines:392
Uncovered lines:344
Coverable lines:736
Total lines:1317
Line coverage:53.2%
Branch coverage:53.2%

Metrics

MethodCyclomatic complexity NPath complexity Sequence coverage Branch coverage
InitAdmin()0010
SaveStaticMappings(...)0011
ReadStaticMappings(...)000.811
WatchStaticMappings(...)000.250.75
ReadStaticMappingAndAddOrUpdate(...)0011
InitProxyAndRecord(...)0011
ToMapping(...)0000
SettingsGet(...)0010.5
SettingsUpdate(...)000.5710.5
MappingGet(...)0000
MappingPut(...)0000
MappingDelete(...)0000
MappingsSave(...)0000
SaveMappingToFile(...)000.80.667
SanitizeFileName(...)0000
MappingsGet(...)0000
MappingsPost(...)000.4670
DeserializeAndAddOrUpdateMapping(...)000.8210.8
MappingsDelete(...)0000
RequestGet(...)0000
RequestDelete(...)0000
RequestsGet(...)0011
RequestsDelete(...)0000
RequestsFind(...)0011
ScenariosGet(...)0000
ScenariosReset(...)0000
InitRequestBuilder(...)000.4240.404
InitResponseBuilder(...)000.5740.633
ToJson(...)0010.5
ToEncoding(...)0011
DeserializeObject(...)0010.5
.ctor(...)0010
ProxyAndRecordAsync()0000
Dispose()0000
Dispose(...)0000
Start(...)0010
Start(...)0010
Start(...)0010
StartWithAdminInterface(...)0010
StartWithAdminInterface(...)0000
StartWithAdminInterfaceAndReadStaticMappings(...)0000
Stop()0010.75
AddCatchAllMapping()0000
Reset()0000
ResetMappings()0011
DeleteMapping(...)0000
DeleteMapping(...)0000
AddGlobalProcessingDelay(...)0010
AllowPartialMapping(...)0010
SetBasicAuthentication(...)0010
RemoveBasicAuthentication()0010
SetMaxRequestLogCount(...)0010
SetRequestLogExpirationDuration(...)0010
ResetScenarios()0000
Given(...)0010
RegisterMapping(...)0011
.ctor(...)000.7350.647
add_LogEntriesChanged(...)0010
remove_LogEntriesChanged(...)0000
FindLogEntries(...)0000
ResetLogEntries()0010
DeleteLogEntry(...)0000

File(s)

C:\Users\StefHeyenrath\Documents\GitHub\WireMock.Net\src\WireMock.Net\Server\FluentMockServer.Admin.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.IO;
 4using System.Linq;
 5using System.Net.Http;
 6using System.Text;
 7using System.Threading.Tasks;
 8using JetBrains.Annotations;
 9using Newtonsoft.Json;
 10using Newtonsoft.Json.Linq;
 11using WireMock.Admin.Mappings;
 12using WireMock.Admin.Scenarios;
 13using WireMock.Admin.Settings;
 14using WireMock.Http;
 15using WireMock.Logging;
 16using WireMock.Matchers;
 17using WireMock.Matchers.Request;
 18using WireMock.RequestBuilders;
 19using WireMock.ResponseBuilders;
 20using WireMock.ResponseProviders;
 21using WireMock.Serialization;
 22using WireMock.Settings;
 23using WireMock.Util;
 24using WireMock.Validation;
 25
 26namespace WireMock.Server
 27{
 28    /// <summary>
 29    /// The fluent mock server.
 30    /// </summary>
 31    public partial class FluentMockServer
 32    {
 33        private const int EnhancedFileSystemWatcherTimeoutMs = 1000;
 34        private const int AdminPriority = int.MinValue;
 35        private const int ProxyPriority = 1000;
 36        private const string ContentTypeJson = "application/json";
 37        private const string AdminMappings = "/__admin/mappings";
 38        private const string AdminRequests = "/__admin/requests";
 39        private const string AdminSettings = "/__admin/settings";
 40        private const string AdminScenarios = "/__admin/scenarios";
 41
 4742        private readonly RegexMatcher _adminMappingsGuidPathMatcher = new RegexMatcher(MatchBehaviour.AcceptOnMatch, @"^
 4743        private readonly RegexMatcher _adminRequestsGuidPathMatcher = new RegexMatcher(MatchBehaviour.AcceptOnMatch, @"^
 44
 4745        private readonly JsonSerializerSettings _settings = new JsonSerializerSettings
 4746        {
 4747            Formatting = Formatting.Indented,
 4748            NullValueHandling = NullValueHandling.Ignore
 4749        };
 50
 4751        private readonly JsonSerializerSettings _settingsIncludeNullValues = new JsonSerializerSettings
 4752        {
 4753            Formatting = Formatting.Indented,
 4754            NullValueHandling = NullValueHandling.Include
 4755        };
 56
 57        #region InitAdmin
 58        private void InitAdmin()
 1159        {
 60            // __admin/settings
 1161            Given(Request.Create().WithPath(AdminSettings).UsingGet()).AtPriority(AdminPriority).RespondWith(new Dynamic
 1162            Given(Request.Create().WithPath(AdminSettings).UsingMethod("PUT", "POST").WithHeader(HttpKnownHeaderNames.Co
 63
 64            // __admin/mappings
 1165            Given(Request.Create().WithPath(AdminMappings).UsingGet()).AtPriority(AdminPriority).RespondWith(new Dynamic
 1166            Given(Request.Create().WithPath(AdminMappings).UsingPost().WithHeader(HttpKnownHeaderNames.ContentType, Cont
 1167            Given(Request.Create().WithPath(AdminMappings).UsingDelete()).AtPriority(AdminPriority).RespondWith(new Dyna
 68
 69            // __admin/mappings/reset
 1170            Given(Request.Create().WithPath(AdminMappings + "/reset").UsingPost()).AtPriority(AdminPriority).RespondWith
 71
 72            // __admin/mappings/{guid}
 1173            Given(Request.Create().WithPath(_adminMappingsGuidPathMatcher).UsingGet()).AtPriority(AdminPriority).Respond
 1174            Given(Request.Create().WithPath(_adminMappingsGuidPathMatcher).UsingPut().WithHeader(HttpKnownHeaderNames.Co
 1175            Given(Request.Create().WithPath(_adminMappingsGuidPathMatcher).UsingDelete()).AtPriority(AdminPriority).Resp
 76
 77            // __admin/mappings/save
 1178            Given(Request.Create().WithPath(AdminMappings + "/save").UsingPost()).AtPriority(AdminPriority).RespondWith(
 79
 80            // __admin/requests
 1181            Given(Request.Create().WithPath(AdminRequests).UsingGet()).AtPriority(AdminPriority).RespondWith(new Dynamic
 1182            Given(Request.Create().WithPath(AdminRequests).UsingDelete()).AtPriority(AdminPriority).RespondWith(new Dyna
 83
 84            // __admin/requests/reset
 1185            Given(Request.Create().WithPath(AdminRequests + "/reset").UsingPost()).AtPriority(AdminPriority).RespondWith
 86
 87            // __admin/request/{guid}
 1188            Given(Request.Create().WithPath(_adminRequestsGuidPathMatcher).UsingGet()).AtPriority(AdminPriority).Respond
 1189            Given(Request.Create().WithPath(_adminRequestsGuidPathMatcher).UsingDelete()).AtPriority(AdminPriority).Resp
 90
 91            // __admin/requests/find
 1192            Given(Request.Create().WithPath(AdminRequests + "/find").UsingPost()).AtPriority(AdminPriority).RespondWith(
 93
 94            // __admin/scenarios
 1195            Given(Request.Create().WithPath(AdminScenarios).UsingGet()).AtPriority(AdminPriority).RespondWith(new Dynami
 1196            Given(Request.Create().WithPath(AdminScenarios).UsingDelete()).AtPriority(AdminPriority).RespondWith(new Dyn
 97
 98            // __admin/scenarios/reset
 1199            Given(Request.Create().WithPath(AdminScenarios + "/reset").UsingPost()).AtPriority(AdminPriority).RespondWit
 11100        }
 101        #endregion
 102
 103        #region StaticMappings
 104        /// <summary>
 105        /// Saves the static mappings.
 106        /// </summary>
 107        /// <param name="folder">The optional folder. If not defined, use {CurrentFolder}/__admin/mappings</param>
 108        [PublicAPI]
 109        public void SaveStaticMappings([CanBeNull] string folder = null)
 1110        {
 6111            foreach (var mapping in Mappings.Where(m => !m.IsAdminInterface))
 1112            {
 1113                SaveMappingToFile(mapping, folder);
 1114            }
 1115        }
 116
 117        /// <summary>
 118        /// Reads the static mappings from a folder.
 119        /// </summary>
 120        /// <param name="folder">The optional folder. If not defined, use {CurrentFolder}/__admin/mappings</param>
 121        [PublicAPI]
 122        public void ReadStaticMappings([CanBeNull] string folder = null)
 4123        {
 4124            if (folder == null)
 1125            {
 1126                folder = _fileSystemHandler.GetMappingFolder();
 1127            }
 128
 4129            if (!_fileSystemHandler.FolderExists(folder))
 1130            {
 1131                _logger.Info("The Static Mapping folder '{0}' does not exist, reading Static MappingFiles will be skippe
 1132                return;
 133            }
 134
 27135            foreach (string filename in _fileSystemHandler.EnumerateFiles(folder).OrderBy(f => f))
 6136            {
 6137                _logger.Info("Reading Static MappingFile : '{0}'", filename);
 138
 139                try
 6140                {
 6141                    ReadStaticMappingAndAddOrUpdate(filename);
 6142                }
 0143                catch
 0144                {
 0145                    _logger.Error("Static MappingFile : '{0}' could not be read. This file will be skipped.", filename);
 0146                }
 6147            }
 4148        }
 149
 150        /// <summary>
 151        /// Watches the static mappings for changes.
 152        /// </summary>
 153        /// <param name="folder">The optional folder. If not defined, use {CurrentFolder}/__admin/mappings</param>
 154        [PublicAPI]
 155        public void WatchStaticMappings([CanBeNull] string folder = null)
 1156        {
 1157            if (folder == null)
 1158            {
 1159                folder = _fileSystemHandler.GetMappingFolder();
 1160            }
 161
 1162            if (!_fileSystemHandler.FolderExists(folder))
 1163            {
 1164                return;
 165            }
 166
 0167            _logger.Info("Watching folder '{0}' for new, updated and deleted MappingFiles.", folder);
 168
 0169            var watcher = new EnhancedFileSystemWatcher(folder, "*.json", EnhancedFileSystemWatcherTimeoutMs);
 0170            watcher.Created += (sender, args) =>
 0171            {
 0172                _logger.Info("New MappingFile created : '{0}'", args.FullPath);
 0173                ReadStaticMappingAndAddOrUpdate(args.FullPath);
 0174            };
 0175            watcher.Changed += (sender, args) =>
 0176            {
 0177                _logger.Info("New MappingFile updated : '{0}'", args.FullPath);
 0178                ReadStaticMappingAndAddOrUpdate(args.FullPath);
 0179            };
 0180            watcher.Deleted += (sender, args) =>
 0181            {
 0182                _logger.Info("New MappingFile deleted : '{0}'", args.FullPath);
 0183                string filenameWithoutExtension = Path.GetFileNameWithoutExtension(args.FullPath);
 0184
 0185                if (Guid.TryParse(filenameWithoutExtension, out Guid guidFromFilename))
 0186                {
 0187                    DeleteMapping(guidFromFilename);
 0188                }
 0189                else
 0190                {
 0191                    DeleteMapping(args.FullPath);
 0192                }
 0193            };
 194
 0195            watcher.EnableRaisingEvents = true;
 1196        }
 197
 198        /// <summary>
 199        /// Reads a static mapping file and adds or updates the mapping.
 200        /// </summary>
 201        /// <param name="path">The path.</param>
 202        [PublicAPI]
 203        public void ReadStaticMappingAndAddOrUpdate([NotNull] string path)
 10204        {
 10205            Check.NotNull(path, nameof(path));
 206
 10207            string filenameWithoutExtension = Path.GetFileNameWithoutExtension(path);
 208
 10209            MappingModel mappingModel = JsonConvert.DeserializeObject<MappingModel>(_fileSystemHandler.ReadMappingFile(p
 10210            if (Guid.TryParse(filenameWithoutExtension, out Guid guidFromFilename))
 6211            {
 6212                DeserializeAndAddOrUpdateMapping(mappingModel, guidFromFilename, path);
 6213            }
 214            else
 4215            {
 4216                DeserializeAndAddOrUpdateMapping(mappingModel, null, path);
 4217            }
 10218        }
 219        #endregion
 220
 221        #region Proxy and Record
 222        private HttpClient _httpClientForProxy;
 223
 224        private void InitProxyAndRecord(IFluentMockServerSettings settings)
 2225        {
 2226            _httpClientForProxy = HttpClientHelper.CreateHttpClient(settings.ProxyAndRecordSettings.ClientX509Certificat
 227
 2228            var respondProvider = Given(Request.Create().WithPath("/*").UsingAnyMethod());
 2229            if (settings.StartAdminInterface == true)
 1230            {
 1231                respondProvider.AtPriority(ProxyPriority);
 1232            }
 233
 2234            respondProvider.RespondWith(new ProxyAsyncResponseProvider(ProxyAndRecordAsync, settings.ProxyAndRecordSetti
 2235        }
 236
 237        private async Task<ResponseMessage> ProxyAndRecordAsync(RequestMessage requestMessage, IProxyAndRecordSettings s
 0238        {
 0239            var requestUri = new Uri(requestMessage.Url);
 0240            var proxyUri = new Uri(settings.Url);
 0241            var proxyUriWithRequestPathAndQuery = new Uri(proxyUri, requestUri.PathAndQuery);
 242
 0243            var responseMessage = await HttpClientHelper.SendAsync(_httpClientForProxy, requestMessage, proxyUriWithRequ
 244
 0245            if (settings.SaveMapping)
 0246            {
 0247                var mapping = ToMapping(requestMessage, responseMessage, settings.BlackListedHeaders ?? new string[] { }
 0248                _options.Mappings.TryAdd(mapping.Guid, mapping);
 249
 0250                if (settings.SaveMappingToFile)
 0251                {
 0252                    SaveMappingToFile(mapping);
 0253                }
 0254            }
 255
 0256            return responseMessage;
 0257        }
 258
 259        private IMapping ToMapping(RequestMessage requestMessage, ResponseMessage responseMessage, string[] blacklistedH
 0260        {
 0261            var request = Request.Create();
 0262            request.WithPath(requestMessage.Path);
 0263            request.UsingMethod(requestMessage.Method);
 264
 0265            requestMessage.Query.Loop((key, value) => request.WithParam(key, value.ToArray()));
 0266            requestMessage.Cookies.Loop((key, value) => request.WithCookie(key, value));
 267
 0268            var allBlackListedHeaders = new List<string>(blacklistedHeaders) { "Cookie" };
 0269            requestMessage.Headers.Loop((key, value) =>
 0270            {
 0271                if (!allBlackListedHeaders.Any(b => string.Equals(key, b, StringComparison.OrdinalIgnoreCase)))
 0272                {
 0273                    request.WithHeader(key, value.ToArray());
 0274                }
 0275            });
 276
 0277            if (requestMessage.BodyAsJson != null)
 0278            {
 0279                request.WithBody(new JsonMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyAsJson));
 0280            }
 0281            else if (requestMessage.Body != null)
 0282            {
 0283                request.WithBody(new ExactMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.Body));
 0284            }
 285
 0286            var response = Response.Create(responseMessage);
 287
 0288            return new Mapping(Guid.NewGuid(), string.Empty, null, request, response, 0, null, null, null);
 0289        }
 290        #endregion
 291
 292        #region Settings
 293        private ResponseMessage SettingsGet(RequestMessage requestMessage)
 1294        {
 1295            var model = new SettingsModel
 1296            {
 1297                AllowPartialMapping = _options.AllowPartialMapping,
 1298                MaxRequestLogCount = _options.MaxRequestLogCount,
 1299                RequestLogExpirationDuration = _options.RequestLogExpirationDuration,
 1300                GlobalProcessingDelay = (int?)_options.RequestProcessingDelay?.TotalMilliseconds
 1301            };
 302
 1303            return ToJson(model);
 1304        }
 305
 306        private ResponseMessage SettingsUpdate(RequestMessage requestMessage)
 2307        {
 2308            var settings = DeserializeObject<SettingsModel>(requestMessage);
 2309            _options.MaxRequestLogCount = settings.MaxRequestLogCount;
 2310            _options.RequestLogExpirationDuration = settings.RequestLogExpirationDuration;
 311
 2312            if (settings.AllowPartialMapping != null)
 0313            {
 0314                _options.AllowPartialMapping = settings.AllowPartialMapping.Value;
 0315            }
 316
 2317            if (settings.GlobalProcessingDelay != null)
 0318            {
 0319                _options.RequestProcessingDelay = TimeSpan.FromMilliseconds(settings.GlobalProcessingDelay.Value);
 0320            }
 321
 2322            return ResponseMessageBuilder.Create("Settings updated");
 2323        }
 324        #endregion Settings
 325
 326        #region Mapping/{guid}
 327        private ResponseMessage MappingGet(RequestMessage requestMessage)
 0328        {
 0329            Guid guid = Guid.Parse(requestMessage.Path.Substring(AdminMappings.Length + 1));
 0330            var mapping = Mappings.FirstOrDefault(m => !m.IsAdminInterface && m.Guid == guid);
 331
 0332            if (mapping == null)
 0333            {
 0334                _logger.Warn("HttpStatusCode set to 404 : Mapping not found");
 0335                return ResponseMessageBuilder.Create("Mapping not found", 404);
 336            }
 337
 0338            var model = MappingConverter.ToMappingModel(mapping);
 339
 0340            return ToJson(model);
 0341        }
 342
 343        private ResponseMessage MappingPut(RequestMessage requestMessage)
 0344        {
 0345            Guid guid = Guid.Parse(requestMessage.Path.TrimStart(AdminMappings.ToCharArray()));
 346
 0347            var mappingModel = DeserializeObject<MappingModel>(requestMessage);
 0348            Guid? guidFromPut = DeserializeAndAddOrUpdateMapping(mappingModel, guid);
 349
 0350            return ResponseMessageBuilder.Create("Mapping added or updated", 200, guidFromPut);
 0351        }
 352
 353        private ResponseMessage MappingDelete(RequestMessage requestMessage)
 0354        {
 0355            Guid guid = Guid.Parse(requestMessage.Path.Substring(AdminMappings.Length + 1));
 356
 0357            if (DeleteMapping(guid))
 0358            {
 0359                return ResponseMessageBuilder.Create("Mapping removed", 200, guid);
 360            }
 361
 0362            return ResponseMessageBuilder.Create("Mapping not found", 404);
 0363        }
 364        #endregion Mapping/{guid}
 365
 366        #region Mappings
 367        private ResponseMessage MappingsSave(RequestMessage requestMessage)
 0368        {
 0369            SaveStaticMappings();
 370
 0371            return ResponseMessageBuilder.Create("Mappings saved to disk");
 0372        }
 373
 374        private void SaveMappingToFile(IMapping mapping, string folder = null)
 1375        {
 1376            if (folder == null)
 1377            {
 1378                folder = _fileSystemHandler.GetMappingFolder();
 1379            }
 380
 1381            if (!_fileSystemHandler.FolderExists(folder))
 0382            {
 0383                _fileSystemHandler.CreateFolder(folder);
 0384            }
 385
 1386            var model = MappingConverter.ToMappingModel(mapping);
 1387            string filename = (!string.IsNullOrEmpty(mapping.Title) ? SanitizeFileName(mapping.Title) : mapping.Guid.ToS
 388
 1389            string path = Path.Combine(folder, filename);
 390
 1391            _logger.Info("Saving Mapping file {0}", filename);
 392
 1393            _fileSystemHandler.WriteMappingFile(path, JsonConvert.SerializeObject(model, _settings));
 1394        }
 395
 396        private static string SanitizeFileName(string name, char replaceChar = '_')
 0397        {
 0398            return Path.GetInvalidFileNameChars().Aggregate(name, (current, c) => current.Replace(c, replaceChar));
 0399        }
 400
 401        private ResponseMessage MappingsGet(RequestMessage requestMessage)
 0402        {
 0403            var result = new List<MappingModel>();
 0404            foreach (var mapping in Mappings.Where(m => !m.IsAdminInterface))
 0405            {
 0406                var model = MappingConverter.ToMappingModel(mapping);
 0407                result.Add(model);
 0408            }
 409
 0410            return ToJson(result);
 0411        }
 412
 413        private ResponseMessage MappingsPost(RequestMessage requestMessage)
 1414        {
 415            Guid? guid;
 416            try
 1417            {
 1418                var mappingModel = DeserializeObject<MappingModel>(requestMessage);
 1419                guid = DeserializeAndAddOrUpdateMapping(mappingModel);
 1420            }
 0421            catch (ArgumentException a)
 0422            {
 0423                _logger.Error("HttpStatusCode set to 400 {0}", a);
 0424                return ResponseMessageBuilder.Create(a.Message, 400);
 425            }
 0426            catch (Exception e)
 0427            {
 0428                _logger.Error("HttpStatusCode set to 500 {0}", e);
 0429                return ResponseMessageBuilder.Create(e.ToString(), 500);
 430            }
 431
 1432            return ResponseMessageBuilder.Create("Mapping added", 201, guid);
 1433        }
 434
 435        private Guid? DeserializeAndAddOrUpdateMapping(MappingModel mappingModel, Guid? guid = null, string path = null)
 11436        {
 11437            Check.NotNull(mappingModel, nameof(mappingModel));
 11438            Check.NotNull(mappingModel.Request, nameof(mappingModel.Request));
 11439            Check.NotNull(mappingModel.Response, nameof(mappingModel.Response));
 440
 11441            var requestBuilder = InitRequestBuilder(mappingModel.Request, true);
 11442            if (requestBuilder == null)
 0443            {
 0444                return null;
 445            }
 446
 11447            var responseBuilder = InitResponseBuilder(mappingModel.Response);
 448
 11449            var respondProvider = Given(requestBuilder);
 450
 11451            if (guid != null)
 6452            {
 6453                respondProvider = respondProvider.WithGuid(guid.Value);
 6454            }
 5455            else if (mappingModel.Guid != null && mappingModel.Guid != Guid.Empty)
 3456            {
 3457                respondProvider = respondProvider.WithGuid(mappingModel.Guid.Value);
 3458            }
 459
 11460            if (path != null)
 10461            {
 10462                respondProvider = respondProvider.WithPath(path);
 10463            }
 464
 11465            if (!string.IsNullOrEmpty(mappingModel.Title))
 4466            {
 4467                respondProvider = respondProvider.WithTitle(mappingModel.Title);
 4468            }
 469
 11470            if (mappingModel.Priority != null)
 10471            {
 10472                respondProvider = respondProvider.AtPriority(mappingModel.Priority.Value);
 10473            }
 474
 11475            if (mappingModel.Scenario != null)
 0476            {
 0477                respondProvider = respondProvider.InScenario(mappingModel.Scenario);
 0478                respondProvider = respondProvider.WhenStateIs(mappingModel.WhenStateIs);
 0479                respondProvider = respondProvider.WillSetStateTo(mappingModel.SetStateTo);
 0480            }
 481
 11482            respondProvider.RespondWith(responseBuilder);
 483
 11484            return respondProvider.Guid;
 11485        }
 486
 487        private ResponseMessage MappingsDelete(RequestMessage requestMessage)
 0488        {
 0489            ResetMappings();
 490
 0491            ResetScenarios();
 492
 0493            return ResponseMessageBuilder.Create("Mappings deleted");
 0494        }
 495        #endregion Mappings
 496
 497        #region Request/{guid}
 498        private ResponseMessage RequestGet(RequestMessage requestMessage)
 0499        {
 0500            Guid guid = Guid.Parse(requestMessage.Path.Substring(AdminRequests.Length + 1));
 0501            var entry = LogEntries.FirstOrDefault(r => !r.RequestMessage.Path.StartsWith("/__admin/") && r.Guid == guid)
 502
 0503            if (entry == null)
 0504            {
 0505                _logger.Warn("HttpStatusCode set to 404 : Request not found");
 0506                return ResponseMessageBuilder.Create("Request not found", 404);
 507            }
 508
 0509            var model = LogEntryMapper.Map(entry);
 510
 0511            return ToJson(model);
 0512        }
 513
 514        private ResponseMessage RequestDelete(RequestMessage requestMessage)
 0515        {
 0516            Guid guid = Guid.Parse(requestMessage.Path.Substring(AdminRequests.Length + 1));
 517
 0518            if (DeleteLogEntry(guid))
 0519            {
 0520                return ResponseMessageBuilder.Create("Request removed");
 521            }
 522
 0523            return ResponseMessageBuilder.Create("Request not found", 404);
 0524        }
 525        #endregion Request/{guid}
 526
 527        #region Requests
 528        private ResponseMessage RequestsGet(RequestMessage requestMessage)
 3529        {
 3530            var result = LogEntries
 6531                .Where(r => !r.RequestMessage.Path.StartsWith("/__admin/"))
 3532                .Select(LogEntryMapper.Map);
 533
 3534            return ToJson(result);
 3535        }
 536
 537        private ResponseMessage RequestsDelete(RequestMessage requestMessage)
 0538        {
 0539            ResetLogEntries();
 540
 0541            return ResponseMessageBuilder.Create("Requests deleted");
 0542        }
 543        #endregion Requests
 544
 545        #region Requests/find
 546        private ResponseMessage RequestsFind(RequestMessage requestMessage)
 1547        {
 1548            var requestModel = DeserializeObject<RequestModel>(requestMessage);
 549
 1550            var request = (Request)InitRequestBuilder(requestModel, false);
 551
 1552            var dict = new Dictionary<LogEntry, RequestMatchResult>();
 6553            foreach (var logEntry in LogEntries.Where(le => !le.RequestMessage.Path.StartsWith("/__admin/")))
 1554            {
 1555                var requestMatchResult = new RequestMatchResult();
 1556                if (request.GetMatchingScore(logEntry.RequestMessage, requestMatchResult) > MatchScores.AlmostPerfect)
 1557                {
 1558                    dict.Add(logEntry, requestMatchResult);
 1559                }
 1560            }
 561
 3562            var result = dict.OrderBy(x => x.Value.AverageTotalScore).Select(x => x.Key).Select(LogEntryMapper.Map);
 563
 1564            return ToJson(result);
 1565        }
 566        #endregion Requests/find
 567
 568        #region Scenarios
 569        private ResponseMessage ScenariosGet(RequestMessage requestMessage)
 0570        {
 0571            var scenariosStates = Scenarios.Values.Select(s => new ScenarioStateModel
 0572            {
 0573                Name = s.Name,
 0574                NextState = s.NextState,
 0575                Started = s.Started,
 0576                Finished = s.Finished
 0577            });
 578
 0579            return ToJson(scenariosStates, true);
 0580        }
 581
 582        private ResponseMessage ScenariosReset(RequestMessage requestMessage)
 0583        {
 0584            ResetScenarios();
 585
 0586            return ResponseMessageBuilder.Create("Scenarios reset");
 0587        }
 588        #endregion
 589
 590        private IRequestBuilder InitRequestBuilder(RequestModel requestModel, bool pathOrUrlRequired)
 12591        {
 12592            IRequestBuilder requestBuilder = Request.Create();
 593
 12594            if (requestModel.ClientIP != null)
 0595            {
 0596                if (requestModel.ClientIP is string clientIP)
 0597                {
 0598                    requestBuilder = requestBuilder.WithClientIP(clientIP);
 0599                }
 600                else
 0601                {
 0602                    var clientIPModel = JsonUtils.ParseJTokenToObject<ClientIPModel>(requestModel.ClientIP);
 0603                    if (clientIPModel?.Matchers != null)
 0604                    {
 0605                        requestBuilder = requestBuilder.WithPath(clientIPModel.Matchers.Select(MatcherMapper.Map).Cast<I
 0606                    }
 0607                }
 0608            }
 609
 12610            bool pathOrUrlmatchersValid = false;
 12611            if (requestModel.Path != null)
 11612            {
 11613                if (requestModel.Path is string path)
 1614                {
 1615                    requestBuilder = requestBuilder.WithPath(path);
 1616                    pathOrUrlmatchersValid = true;
 1617                }
 618                else
 10619                {
 10620                    var pathModel = JsonUtils.ParseJTokenToObject<PathModel>(requestModel.Path);
 10621                    if (pathModel?.Matchers != null)
 10622                    {
 10623                        requestBuilder = requestBuilder.WithPath(pathModel.Matchers.Select(MatcherMapper.Map).Cast<IStri
 10624                        pathOrUrlmatchersValid = true;
 10625                    }
 10626                }
 11627            }
 1628            else if (requestModel.Url != null)
 0629            {
 0630                if (requestModel.Url is string url)
 0631                {
 0632                    requestBuilder = requestBuilder.WithUrl(url);
 0633                    pathOrUrlmatchersValid = true;
 0634                }
 635                else
 0636                {
 0637                    var urlModel = JsonUtils.ParseJTokenToObject<UrlModel>(requestModel.Url);
 0638                    if (urlModel?.Matchers != null)
 0639                    {
 0640                        requestBuilder = requestBuilder.WithUrl(urlModel.Matchers.Select(MatcherMapper.Map).Cast<IString
 0641                        pathOrUrlmatchersValid = true;
 0642                    }
 0643                }
 0644            }
 645
 12646            if (pathOrUrlRequired && !pathOrUrlmatchersValid)
 0647            {
 0648                _logger.Error("Path or Url matcher is missing for this mapping, this mapping will not be added.");
 0649                return null;
 650            }
 651
 12652            if (requestModel.Methods != null)
 11653            {
 11654                requestBuilder = requestBuilder.UsingMethod(requestModel.Methods);
 11655            }
 656
 12657            if (requestModel.Headers != null)
 0658            {
 0659                foreach (var headerModel in requestModel.Headers.Where(h => h.Matchers != null))
 0660                {
 0661                    requestBuilder = requestBuilder.WithHeader(headerModel.Name, headerModel.Matchers.Select(MatcherMapp
 0662                }
 0663            }
 664
 12665            if (requestModel.Cookies != null)
 0666            {
 0667                foreach (var cookieModel in requestModel.Cookies.Where(c => c.Matchers != null))
 0668                {
 0669                    requestBuilder = requestBuilder.WithCookie(cookieModel.Name, cookieModel.Matchers.Select(MatcherMapp
 0670                }
 0671            }
 672
 12673            if (requestModel.Params != null)
 0674            {
 0675                foreach (var paramModel in requestModel.Params.Where(c => c.Matchers != null))
 0676                {
 0677                    requestBuilder = requestBuilder.WithParam(paramModel.Name, paramModel.Matchers.Select(MatcherMapper.
 0678                }
 0679            }
 680
 12681            if (requestModel.Body?.Matcher != null)
 3682            {
 3683                var bodyMatcher = MatcherMapper.Map(requestModel.Body.Matcher);
 3684                requestBuilder = requestBuilder.WithBody(bodyMatcher);
 3685            }
 686
 12687            return requestBuilder;
 12688        }
 689
 690        private IResponseBuilder InitResponseBuilder(ResponseModel responseModel)
 11691        {
 11692            IResponseBuilder responseBuilder = Response.Create();
 693
 11694            if (responseModel.Delay > 0)
 0695            {
 0696                responseBuilder = responseBuilder.WithDelay(responseModel.Delay.Value);
 0697            }
 698
 11699            if (!string.IsNullOrEmpty(responseModel.ProxyUrl))
 0700            {
 0701                if (string.IsNullOrEmpty(responseModel.X509Certificate2ThumbprintOrSubjectName))
 0702                {
 0703                    return responseBuilder.WithProxy(responseModel.ProxyUrl);
 704                }
 705
 0706                return responseBuilder.WithProxy(responseModel.ProxyUrl, responseModel.X509Certificate2ThumbprintOrSubje
 707            }
 708
 11709            if (responseModel.StatusCode.HasValue)
 10710            {
 10711                responseBuilder = responseBuilder.WithStatusCode(responseModel.StatusCode.Value);
 10712            }
 713
 11714            if (responseModel.Headers != null)
 9715            {
 189716                foreach (var entry in responseModel.Headers)
 81717                {
 81718                    responseBuilder = entry.Value is string value ?
 81719                        responseBuilder.WithHeader(entry.Key, value) :
 81720                        responseBuilder.WithHeader(entry.Key, JsonUtils.ParseJTokenToObject<string[]>(entry.Value));
 81721                }
 9722            }
 2723            else if (responseModel.HeadersRaw != null)
 0724            {
 0725                foreach (string headerLine in responseModel.HeadersRaw.Split(new[] { "\n", "\r\n" }, StringSplitOptions.
 0726                {
 0727                    int indexColon = headerLine.IndexOf(":", StringComparison.Ordinal);
 0728                    string key = headerLine.Substring(0, indexColon).TrimStart(' ', '\t');
 0729                    string value = headerLine.Substring(indexColon + 1).TrimStart(' ', '\t');
 0730                    responseBuilder = responseBuilder.WithHeader(key, value);
 0731                }
 0732            }
 733
 11734            if (responseModel.BodyAsBytes != null)
 0735            {
 0736                responseBuilder = responseBuilder.WithBody(responseModel.BodyAsBytes, responseModel.BodyDestination, ToE
 0737            }
 11738            else if (responseModel.Body != null)
 7739            {
 7740                responseBuilder = responseBuilder.WithBody(responseModel.Body, responseModel.BodyDestination, ToEncoding
 7741            }
 4742            else if (responseModel.BodyAsJson != null)
 1743            {
 1744                responseBuilder = responseBuilder.WithBodyAsJson(responseModel.BodyAsJson, ToEncoding(responseModel.Body
 1745            }
 3746            else if (responseModel.BodyFromBase64 != null)
 0747            {
 0748                responseBuilder = responseBuilder.WithBodyFromBase64(responseModel.BodyFromBase64, ToEncoding(responseMo
 0749            }
 3750            else if (responseModel.BodyAsFile != null)
 3751            {
 3752                responseBuilder = responseBuilder.WithBodyFromFile(responseModel.BodyAsFile);
 3753            }
 754
 11755            if (responseModel.UseTransformer)
 0756            {
 0757                responseBuilder = responseBuilder.WithTransformer();
 0758            }
 759
 11760            return responseBuilder;
 11761        }
 762
 763        private ResponseMessage ToJson<T>(T result, bool keepNullValues = false)
 5764        {
 5765            return new ResponseMessage
 5766            {
 5767                Body = JsonConvert.SerializeObject(result, keepNullValues ? _settingsIncludeNullValues : _settings),
 5768                StatusCode = 200,
 5769                Headers = new Dictionary<string, WireMockList<string>> { { HttpKnownHeaderNames.ContentType, new WireMoc
 5770            };
 5771        }
 772
 773        private Encoding ToEncoding(EncodingModel encodingModel)
 8774        {
 8775            return encodingModel != null ? Encoding.GetEncoding(encodingModel.CodePage) : null;
 8776        }
 777
 778        private T DeserializeObject<T>(RequestMessage requestMessage)
 4779        {
 4780            return requestMessage.Body != null ?
 4781                JsonConvert.DeserializeObject<T>(requestMessage.Body) :
 4782                ((JObject)requestMessage.BodyAsJson).ToObject<T>();
 4783        }
 784    }
 785}

C:\Users\StefHeyenrath\Documents\GitHub\WireMock.Net\src\WireMock.Net\Server\FluentMockServer.cs

#LineLine coverage
 1using JetBrains.Annotations;
 2using System;
 3using System.Collections.Concurrent;
 4using System.Collections.Generic;
 5using System.Linq;
 6using System.Text;
 7using System.Threading;
 8using System.Threading.Tasks;
 9using Newtonsoft.Json;
 10using WireMock.Handlers;
 11using WireMock.Logging;
 12using WireMock.Matchers;
 13using WireMock.Matchers.Request;
 14using WireMock.Owin;
 15using WireMock.RequestBuilders;
 16using WireMock.ResponseProviders;
 17using WireMock.Settings;
 18using WireMock.Util;
 19using WireMock.Validation;
 20
 21namespace WireMock.Server
 22{
 23    /// <summary>
 24    /// The fluent mock server.
 25    /// </summary>
 26    public partial class FluentMockServer : IDisposable
 27    {
 28        private const int ServerStartDelayInMs = 100;
 29
 30        private readonly IWireMockLogger _logger;
 31        private readonly IFileSystemHandler _fileSystemHandler;
 32        private readonly IOwinSelfHost _httpServer;
 4733        private readonly IWireMockMiddlewareOptions _options = new WireMockMiddlewareOptions();
 34
 35        /// <summary>
 36        /// Gets a value indicating whether this server is started.
 37        /// </summary>
 38        [PublicAPI]
 039        public bool IsStarted => _httpServer != null && _httpServer.IsStarted;
 40
 41        /// <summary>
 42        /// Gets the ports.
 43        /// </summary>
 44        [PublicAPI]
 2045        public List<int> Ports { get; }
 46
 47        /// <summary>
 48        /// Gets the urls.
 49        /// </summary>
 50        [PublicAPI]
 6451        public string[] Urls { get; }
 52
 53        /// <summary>
 54        /// Gets the mappings.
 55        /// </summary>
 56        [PublicAPI]
 1857        public IEnumerable<IMapping> Mappings => _options.Mappings.Values.ToArray();
 58
 59        /// <summary>
 60        /// Gets the scenarios.
 61        /// </summary>
 62        [PublicAPI]
 1363        public ConcurrentDictionary<string, ScenarioState> Scenarios => new ConcurrentDictionary<string, ScenarioState>(
 64
 65        #region IDisposable Members
 66        /// <summary>
 67        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
 68        /// </summary>
 69        public void Dispose()
 070        {
 071            Dispose(true);
 072            GC.SuppressFinalize(this);
 073        }
 74
 75        /// <summary>
 76        /// Releases unmanaged and - optionally - managed resources.
 77        /// </summary>
 78        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release
 79        protected virtual void Dispose(bool disposing)
 080        {
 081            if (_httpServer != null)
 082            {
 083                _httpServer.StopAsync();
 084            }
 085        }
 86        #endregion
 87
 88        #region Start/Stop
 89        /// <summary>
 90        /// Starts the specified settings.
 91        /// </summary>
 92        /// <param name="settings">The FluentMockServerSettings.</param>
 93        /// <returns>The <see cref="FluentMockServer"/>.</returns>
 94        [PublicAPI]
 95        public static FluentMockServer Start(IFluentMockServerSettings settings)
 1696        {
 1697            Check.NotNull(settings, nameof(settings));
 98
 1699            return new FluentMockServer(settings);
 16100        }
 101
 102        /// <summary>
 103        /// Start this FluentMockServer.
 104        /// </summary>
 105        /// <param name="port">The port.</param>
 106        /// <param name="ssl">The SSL support.</param>
 107        /// <returns>The <see cref="FluentMockServer"/>.</returns>
 108        [PublicAPI]
 109        public static FluentMockServer Start([CanBeNull] int? port = 0, bool ssl = false)
 26110        {
 26111            return new FluentMockServer(new FluentMockServerSettings
 26112            {
 26113                Port = port,
 26114                UseSSL = ssl
 26115            });
 25116        }
 117
 118        /// <summary>
 119        /// Start this FluentMockServer.
 120        /// </summary>
 121        /// <param name="urls">The urls to listen on.</param>
 122        /// <returns>The <see cref="FluentMockServer"/>.</returns>
 123        [PublicAPI]
 124        public static FluentMockServer Start(params string[] urls)
 1125        {
 1126            Check.NotNullOrEmpty(urls, nameof(urls));
 127
 1128            return new FluentMockServer(new FluentMockServerSettings
 1129            {
 1130                Urls = urls
 1131            });
 1132        }
 133
 134        /// <summary>
 135        /// Start this FluentMockServer with the admin interface.
 136        /// </summary>
 137        /// <param name="port">The port.</param>
 138        /// <param name="ssl">The SSL support.</param>
 139        /// <returns>The <see cref="FluentMockServer"/>.</returns>
 140        [PublicAPI]
 141        public static FluentMockServer StartWithAdminInterface(int? port = 0, bool ssl = false)
 4142        {
 4143            return new FluentMockServer(new FluentMockServerSettings
 4144            {
 4145                Port = port,
 4146                UseSSL = ssl,
 4147                StartAdminInterface = true
 4148            });
 4149        }
 150
 151        /// <summary>
 152        /// Start this FluentMockServer with the admin interface.
 153        /// </summary>
 154        /// <param name="urls">The urls.</param>
 155        /// <returns>The <see cref="FluentMockServer"/>.</returns>
 156        [PublicAPI]
 157        public static FluentMockServer StartWithAdminInterface(params string[] urls)
 0158        {
 0159            Check.NotNullOrEmpty(urls, nameof(urls));
 160
 0161            return new FluentMockServer(new FluentMockServerSettings
 0162            {
 0163                Urls = urls,
 0164                StartAdminInterface = true
 0165            });
 0166        }
 167
 168        /// <summary>
 169        /// Start this FluentMockServer with the admin interface and read static mappings.
 170        /// </summary>
 171        /// <param name="urls">The urls.</param>
 172        /// <returns>The <see cref="FluentMockServer"/>.</returns>
 173        [PublicAPI]
 174        public static FluentMockServer StartWithAdminInterfaceAndReadStaticMappings(params string[] urls)
 0175        {
 0176            Check.NotNullOrEmpty(urls, nameof(urls));
 177
 0178            return new FluentMockServer(new FluentMockServerSettings
 0179            {
 0180                Urls = urls,
 0181                StartAdminInterface = true,
 0182                ReadStaticMappings = true
 0183            });
 0184        }
 185
 47186        private FluentMockServer(IFluentMockServerSettings settings)
 47187        {
 47188            settings.Logger = settings.Logger ?? new WireMockConsoleLogger();
 189
 47190            _logger = settings.Logger;
 47191            _fileSystemHandler = settings.FileSystemHandler ?? new LocalFileSystemHandler();
 192
 47193            _logger.Info("WireMock.Net by Stef Heyenrath (https://github.com/WireMock-Net/WireMock.Net)");
 47194            _logger.Debug("WireMock.Net server settings {0}", JsonConvert.SerializeObject(settings, Formatting.Indented)
 195
 47196            if (settings.Urls != null)
 1197            {
 1198                Urls = settings.Urls.ToArray();
 1199            }
 200            else
 46201            {
 46202                int port = settings.Port > 0 ? settings.Port.Value : PortUtils.FindFreeTcpPort();
 46203                Urls = new[] { $"{(settings.UseSSL == true ? "https" : "http")}://localhost:{port}" };
 46204            }
 205
 47206            _options.PreWireMockMiddlewareInit = settings.PreWireMockMiddlewareInit;
 47207            _options.PostWireMockMiddlewareInit = settings.PostWireMockMiddlewareInit;
 47208            _options.Logger = _logger;
 209
 210#if USE_ASPNETCORE
 47211            _httpServer = new AspNetCoreSelfHost(_options, Urls);
 212#else
 213            _httpServer = new OwinSelfHost(_options, Urls);
 214#endif
 47215            Ports = _httpServer.Ports;
 216
 47217            _httpServer.StartAsync();
 218
 47219            using (var ctsStartTimeout = new CancellationTokenSource(settings.StartTimeout))
 47220            {
 47221                while (!_httpServer.IsStarted)
 0222                {
 223                    // Throw out exception if service start fails
 0224                    if (_httpServer.RunningException != null)
 0225                    {
 0226                        throw new Exception($"Service start failed with error: {_httpServer.RunningException.Message}", 
 227                    }
 228
 229                    // Respect start timeout setting by throwing TimeoutException
 0230                    if (ctsStartTimeout.IsCancellationRequested)
 0231                    {
 0232                        throw new TimeoutException($"Service start timed out after {TimeSpan.FromMilliseconds(settings.S
 233                    }
 234
 0235                    ctsStartTimeout.Token.WaitHandle.WaitOne(ServerStartDelayInMs);
 0236                }
 47237            }
 238
 47239            if (settings.AllowPartialMapping == true)
 1240            {
 1241                AllowPartialMapping();
 1242            }
 243
 47244            if (settings.StartAdminInterface == true)
 11245            {
 11246                if (!string.IsNullOrEmpty(settings.AdminUsername) && !string.IsNullOrEmpty(settings.AdminPassword))
 1247                {
 1248                    SetBasicAuthentication(settings.AdminUsername, settings.AdminPassword);
 1249                }
 250
 11251                InitAdmin();
 11252            }
 253
 47254            if (settings.ReadStaticMappings == true)
 0255            {
 0256                ReadStaticMappings();
 0257            }
 258
 47259            if (settings.WatchStaticMappings == true)
 0260            {
 0261                WatchStaticMappings();
 0262            }
 263
 47264            if (settings.ProxyAndRecordSettings != null)
 2265            {
 2266                InitProxyAndRecord(settings);
 2267            }
 268
 47269            if (settings.RequestLogExpirationDuration != null)
 1270            {
 1271                SetRequestLogExpirationDuration(settings.RequestLogExpirationDuration);
 1272            }
 273
 47274            if (settings.MaxRequestLogCount != null)
 0275            {
 0276                SetMaxRequestLogCount(settings.MaxRequestLogCount);
 0277            }
 46278        }
 279
 280        /// <summary>
 281        /// Stop this server.
 282        /// </summary>
 283        [PublicAPI]
 284        public void Stop()
 2285        {
 2286            var result = _httpServer?.StopAsync();
 2287            result?.Wait(); // wait for stop to actually happen
 2288        }
 289        #endregion
 290
 291        /// <summary>
 292        /// Adds the catch all mapping.
 293        /// </summary>
 294        [PublicAPI]
 295        public void AddCatchAllMapping()
 0296        {
 0297            Given(Request.Create().WithPath("/*").UsingAnyMethod())
 0298                .WithGuid(Guid.Parse("90008000-0000-4444-a17e-669cd84f1f05"))
 0299                .AtPriority(1000)
 0300                .RespondWith(new DynamicResponseProvider(request => ResponseMessageBuilder.Create("No matching mapping f
 0301        }
 302
 303        /// <summary>
 304        /// Resets LogEntries and Mappings.
 305        /// </summary>
 306        [PublicAPI]
 307        public void Reset()
 0308        {
 0309            ResetLogEntries();
 310
 0311            ResetMappings();
 0312        }
 313
 314        /// <summary>
 315        /// Resets the Mappings.
 316        /// </summary>
 317        [PublicAPI]
 318        public void ResetMappings()
 2319        {
 18320            foreach (var nonAdmin in _options.Mappings.ToArray().Where(m => !m.Value.IsAdminInterface))
 4321            {
 4322                _options.Mappings.TryRemove(nonAdmin.Key, out _);
 4323            }
 2324        }
 325
 326        /// <summary>
 327        /// Deletes the mapping.
 328        /// </summary>
 329        /// <param name="guid">The unique identifier.</param>
 330        [PublicAPI]
 331        public bool DeleteMapping(Guid guid)
 0332        {
 333            // Check a mapping exists with the same GUID, if so, remove it.
 0334            if (_options.Mappings.ContainsKey(guid))
 0335            {
 0336                return _options.Mappings.TryRemove(guid, out _);
 337            }
 338
 0339            return false;
 0340        }
 341
 342        private bool DeleteMapping(string path)
 0343        {
 344            // Check a mapping exists with the same path, if so, remove it.
 0345            var mapping = _options.Mappings.ToArray().FirstOrDefault(entry => string.Equals(entry.Value.Path, path, Stri
 0346            return DeleteMapping(mapping.Key);
 0347        }
 348
 349        /// <summary>
 350        /// The add request processing delay.
 351        /// </summary>
 352        /// <param name="delay">The delay.</param>
 353        [PublicAPI]
 354        public void AddGlobalProcessingDelay(TimeSpan delay)
 1355        {
 1356            _options.RequestProcessingDelay = delay;
 1357        }
 358
 359        /// <summary>
 360        /// Allows the partial mapping.
 361        /// </summary>
 362        [PublicAPI]
 363        public void AllowPartialMapping(bool allow = true)
 1364        {
 1365            _logger.Info("AllowPartialMapping is set to {0}", allow);
 1366            _options.AllowPartialMapping = allow;
 1367        }
 368
 369        /// <summary>
 370        /// Sets the basic authentication.
 371        /// </summary>
 372        /// <param name="username">The username.</param>
 373        /// <param name="password">The password.</param>
 374        [PublicAPI]
 375        public void SetBasicAuthentication([NotNull] string username, [NotNull] string password)
 3376        {
 3377            Check.NotNull(username, nameof(username));
 3378            Check.NotNull(password, nameof(password));
 379
 3380            string authorization = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + p
 3381            _options.AuthorizationMatcher = new RegexMatcher(MatchBehaviour.AcceptOnMatch, "^(?i)BASIC " + authorization
 3382        }
 383
 384        /// <summary>
 385        /// Removes the basic authentication.
 386        /// </summary>
 387        [PublicAPI]
 388        public void RemoveBasicAuthentication()
 1389        {
 1390            _options.AuthorizationMatcher = null;
 1391        }
 392
 393        /// <summary>
 394        /// Sets the maximum RequestLog count.
 395        /// </summary>
 396        /// <param name="maxRequestLogCount">The maximum RequestLog count.</param>
 397        [PublicAPI]
 398        public void SetMaxRequestLogCount([CanBeNull] int? maxRequestLogCount)
 1399        {
 1400            _options.MaxRequestLogCount = maxRequestLogCount;
 1401        }
 402
 403        /// <summary>
 404        /// Sets RequestLog expiration in hours.
 405        /// </summary>
 406        /// <param name="requestLogExpirationDuration">The RequestLog expiration in hours.</param>
 407        [PublicAPI]
 408        public void SetRequestLogExpirationDuration([CanBeNull] int? requestLogExpirationDuration)
 1409        {
 1410            _options.RequestLogExpirationDuration = requestLogExpirationDuration;
 1411        }
 412
 413        /// <summary>
 414        /// Resets the Scenarios.
 415        /// </summary>
 416        [PublicAPI]
 417        public void ResetScenarios()
 0418        {
 0419            _options.Scenarios.Clear();
 0420        }
 421
 422        /// <summary>
 423        /// The given.
 424        /// </summary>
 425        /// <param name="requestMatcher">The request matcher.</param>
 426        /// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
 427        [PublicAPI]
 428        public IRespondWithAProvider Given(IRequestMatcher requestMatcher)
 249429        {
 249430            return new RespondWithAProvider(RegisterMapping, requestMatcher);
 249431        }
 432
 433        private void RegisterMapping(IMapping mapping)
 249434        {
 435            // Check a mapping exists with the same Guid, if so, replace it.
 249436            if (_options.Mappings.ContainsKey(mapping.Guid))
 1437            {
 1438                _options.Mappings[mapping.Guid] = mapping;
 1439            }
 440            else
 248441            {
 248442                _options.Mappings.TryAdd(mapping.Guid, mapping);
 248443            }
 249444        }
 445    }
 446}

C:\Users\StefHeyenrath\Documents\GitHub\WireMock.Net\src\WireMock.Net\Server\FluentMockServer.LogEntries.cs

#LineLine coverage
 1using System;
 2using System.Collections;
 3using System.Collections.Generic;
 4using System.Collections.ObjectModel;
 5using System.Collections.Specialized;
 6using JetBrains.Annotations;
 7using WireMock.Logging;
 8using WireMock.Matchers.Request;
 9using System.Linq;
 10using WireMock.Matchers;
 11
 12namespace WireMock.Server
 13{
 14    public partial class FluentMockServer
 15    {
 16        /// <summary>
 17        /// Occurs when [log entries changed].
 18        /// </summary>
 19        [PublicAPI]
 20        public event NotifyCollectionChangedEventHandler LogEntriesChanged
 21        {
 222            add => _options.LogEntries.CollectionChanged += value;
 023            remove => _options.LogEntries.CollectionChanged -= value;
 24        }
 25
 26        /// <summary>
 27        /// Gets the request logs.
 28        /// </summary>
 29        [PublicAPI]
 1030        public IEnumerable<LogEntry> LogEntries => new ReadOnlyCollection<LogEntry>(_options.LogEntries);
 31
 32        /// <summary>
 33        /// The search log-entries based on matchers.
 34        /// </summary>
 35        /// <param name="matchers">The matchers.</param>
 36        /// <returns>The <see cref="IEnumerable"/>.</returns>
 37        [PublicAPI]
 38        public IEnumerable<LogEntry> FindLogEntries([NotNull] params IRequestMatcher[] matchers)
 039        {
 040            var results = new Dictionary<LogEntry, RequestMatchResult>();
 41
 042            foreach (var log in _options.LogEntries)
 043            {
 044                var requestMatchResult = new RequestMatchResult();
 045                foreach (var matcher in matchers)
 046                {
 047                    matcher.GetMatchingScore(log.RequestMessage, requestMatchResult);
 048                }
 49
 050                if (requestMatchResult.AverageTotalScore > MatchScores.AlmostPerfect)
 051                {
 052                    results.Add(log, requestMatchResult);
 053                }
 054            }
 55
 056            return new ReadOnlyCollection<LogEntry>(results.OrderBy(x => x.Value).Select(x => x.Key).ToList());
 057        }
 58
 59        /// <summary>
 60        /// Resets the LogEntries.
 61        /// </summary>
 62        [PublicAPI]
 63        public void ResetLogEntries()
 164        {
 165            _options.LogEntries.Clear();
 166        }
 67
 68        /// <summary>
 69        /// Deletes a LogEntry.
 70        /// </summary>
 71        /// <param name="guid">The unique identifier.</param>
 72        [PublicAPI]
 73        public bool DeleteLogEntry(Guid guid)
 074        {
 75            // Check a logentry exists with the same GUID, if so, remove it.
 076            var existing = _options.LogEntries.FirstOrDefault(m => m.Guid == guid);
 077            if (existing != null)
 078            {
 079                _options.LogEntries.Remove(existing);
 080                return true;
 81            }
 82
 083            return false;
 084        }
 85    }
 86}

Methods/Properties

.ctor(WireMock.Settings.IFluentMockServerSettings)
InitAdmin()
SaveStaticMappings(System.String)
ReadStaticMappings(System.String)
WatchStaticMappings(System.String)
ReadStaticMappingAndAddOrUpdate(System.String)
InitProxyAndRecord(WireMock.Settings.IFluentMockServerSettings)
ProxyAndRecordAsync()
ToMapping(WireMock.RequestMessage,WireMock.ResponseMessage,System.String[])
SettingsGet(WireMock.RequestMessage)
SettingsUpdate(WireMock.RequestMessage)
MappingGet(WireMock.RequestMessage)
MappingPut(WireMock.RequestMessage)
MappingDelete(WireMock.RequestMessage)
MappingsSave(WireMock.RequestMessage)
SaveMappingToFile(WireMock.IMapping,System.String)
SanitizeFileName(System.String,System.Char)
MappingsGet(WireMock.RequestMessage)
MappingsPost(WireMock.RequestMessage)
DeserializeAndAddOrUpdateMapping(WireMock.Admin.Mappings.MappingModel,System.Nullable`1<System.Guid>,System.String)
MappingsDelete(WireMock.RequestMessage)
RequestGet(WireMock.RequestMessage)
RequestDelete(WireMock.RequestMessage)
RequestsGet(WireMock.RequestMessage)
RequestsDelete(WireMock.RequestMessage)
RequestsFind(WireMock.RequestMessage)
ScenariosGet(WireMock.RequestMessage)
ScenariosReset(WireMock.RequestMessage)
InitRequestBuilder(WireMock.Admin.Mappings.RequestModel,System.Boolean)
InitResponseBuilder(WireMock.Admin.Mappings.ResponseModel)
ToJson(T,System.Boolean)
ToEncoding(WireMock.Admin.Mappings.EncodingModel)
DeserializeObject(WireMock.RequestMessage)
.ctor(WireMock.Settings.IFluentMockServerSettings)
IsStarted()
Ports()
Urls()
Mappings()
Scenarios()
Dispose()
Dispose(System.Boolean)
Start(WireMock.Settings.IFluentMockServerSettings)
Start(System.Nullable`1<System.Int32>,System.Boolean)
Start(System.String[])
StartWithAdminInterface(System.Nullable`1<System.Int32>,System.Boolean)
StartWithAdminInterface(System.String[])
StartWithAdminInterfaceAndReadStaticMappings(System.String[])
Stop()
AddCatchAllMapping()
Reset()
ResetMappings()
DeleteMapping(System.Guid)
DeleteMapping(System.String)
AddGlobalProcessingDelay(System.TimeSpan)
AllowPartialMapping(System.Boolean)
SetBasicAuthentication(System.String,System.String)
RemoveBasicAuthentication()
SetMaxRequestLogCount(System.Nullable`1<System.Int32>)
SetRequestLogExpirationDuration(System.Nullable`1<System.Int32>)
ResetScenarios()
Given(WireMock.Matchers.Request.IRequestMatcher)
RegisterMapping(WireMock.IMapping)
add_LogEntriesChanged(System.Collections.Specialized.NotifyCollectionChangedEventHandler)
remove_LogEntriesChanged(System.Collections.Specialized.NotifyCollectionChangedEventHandler)
LogEntries()
FindLogEntries(WireMock.Matchers.Request.IRequestMatcher[])
ResetLogEntries()
DeleteLogEntry(System.Guid)