Summary

Class:WireMock.Server.FluentMockServer
Assembly:WireMock.Net
File(s):C:\Users\azureuser\Documents\Github\WireMock.Net\src\WireMock.Net\Server\FluentMockServer.Admin.cs
C:\Users\azureuser\Documents\Github\WireMock.Net\src\WireMock.Net\Server\FluentMockServer.cs
C:\Users\azureuser\Documents\Github\WireMock.Net\src\WireMock.Net\Server\FluentMockServer.LogEntries.cs
Covered lines:375
Uncovered lines:352
Coverable lines:727
Total lines:1307
Line coverage:51.5%
Branch coverage:56.2%

Metrics

MethodCyclomatic complexity NPath complexity Sequence coverage Branch coverage
InitAdmin()0010
SaveStaticMappings(...)0011
ReadStaticMappings(...)000.811
WatchStaticMappings(...)000.250.75
ReadStaticMappingAndAddOrUpdate(...)0011
InitProxyAndRecord(...)0000
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(...)0000
SetBasicAuthentication(...)0000
RemoveBasicAuthentication()0000
SetMaxRequestLogCount(...)0010
SetRequestLogExpirationDuration(...)0000
ResetScenarios()0000
Given(...)0010
RegisterMapping(...)0011
.ctor(...)000.6560.594
add_LogEntriesChanged(...)0010
remove_LogEntriesChanged(...)0000
FindLogEntries(...)0011
ResetLogEntries()0010
DeleteLogEntry(...)0000

File(s)

C:\Users\azureuser\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 string ContentTypeJson = "application/json";
 34
 35        private const string AdminMappings = "/__admin/mappings";
 36        private const string AdminRequests = "/__admin/requests";
 37        private const string AdminSettings = "/__admin/settings";
 38        private const string AdminScenarios = "/__admin/scenarios";
 39
 4940        private readonly RegexMatcher _adminMappingsGuidPathMatcher = new RegexMatcher(MatchBehaviour.AcceptOnMatch, @"^
 4941        private readonly RegexMatcher _adminRequestsGuidPathMatcher = new RegexMatcher(MatchBehaviour.AcceptOnMatch, @"^
 42
 4943        private readonly JsonSerializerSettings _settings = new JsonSerializerSettings
 4944        {
 4945            Formatting = Formatting.Indented,
 4946            NullValueHandling = NullValueHandling.Ignore
 4947        };
 48
 4949        private readonly JsonSerializerSettings _settingsIncludeNullValues = new JsonSerializerSettings
 4950        {
 4951            Formatting = Formatting.Indented,
 4952            NullValueHandling = NullValueHandling.Include
 4953        };
 54
 55        #region InitAdmin
 56        private void InitAdmin()
 857        {
 58            // __admin/settings
 859            Given(Request.Create().WithPath(AdminSettings).UsingGet()).RespondWith(new DynamicResponseProvider(SettingsG
 860            Given(Request.Create().WithPath(AdminSettings).UsingMethod("PUT", "POST").WithHeader(HttpKnownHeaderNames.Co
 61
 62
 63            // __admin/mappings
 864            Given(Request.Create().WithPath(AdminMappings).UsingGet()).RespondWith(new DynamicResponseProvider(MappingsG
 865            Given(Request.Create().WithPath(AdminMappings).UsingPost().WithHeader(HttpKnownHeaderNames.ContentType, Cont
 866            Given(Request.Create().WithPath(AdminMappings).UsingDelete()).RespondWith(new DynamicResponseProvider(Mappin
 67
 68            // __admin/mappings/reset
 869            Given(Request.Create().WithPath(AdminMappings + "/reset").UsingPost()).RespondWith(new DynamicResponseProvid
 70
 71            // __admin/mappings/{guid}
 872            Given(Request.Create().WithPath(_adminMappingsGuidPathMatcher).UsingGet()).RespondWith(new DynamicResponsePr
 873            Given(Request.Create().WithPath(_adminMappingsGuidPathMatcher).UsingPut().WithHeader(HttpKnownHeaderNames.Co
 874            Given(Request.Create().WithPath(_adminMappingsGuidPathMatcher).UsingDelete()).RespondWith(new DynamicRespons
 75
 76            // __admin/mappings/save
 877            Given(Request.Create().WithPath(AdminMappings + "/save").UsingPost()).RespondWith(new DynamicResponseProvide
 78
 79
 80            // __admin/requests
 881            Given(Request.Create().WithPath(AdminRequests).UsingGet()).RespondWith(new DynamicResponseProvider(RequestsG
 882            Given(Request.Create().WithPath(AdminRequests).UsingDelete()).RespondWith(new DynamicResponseProvider(Reques
 83
 84            // __admin/requests/reset
 885            Given(Request.Create().WithPath(AdminRequests + "/reset").UsingPost()).RespondWith(new DynamicResponseProvid
 86
 87            // __admin/request/{guid}
 888            Given(Request.Create().WithPath(_adminRequestsGuidPathMatcher).UsingGet()).RespondWith(new DynamicResponsePr
 889            Given(Request.Create().WithPath(_adminRequestsGuidPathMatcher).UsingDelete()).RespondWith(new DynamicRespons
 90
 91            // __admin/requests/find
 892            Given(Request.Create().WithPath(AdminRequests + "/find").UsingPost()).RespondWith(new DynamicResponseProvide
 93
 94
 95            // __admin/scenarios
 896            Given(Request.Create().WithPath(AdminScenarios).UsingGet()).RespondWith(new DynamicResponseProvider(Scenario
 897            Given(Request.Create().WithPath(AdminScenarios).UsingDelete()).RespondWith(new DynamicResponseProvider(Scena
 98
 99            // __admin/scenarios/reset
 8100            Given(Request.Create().WithPath(AdminScenarios + "/reset").UsingPost()).RespondWith(new DynamicResponseProvi
 8101        }
 102        #endregion
 103
 104        #region StaticMappings
 105        /// <summary>
 106        /// Saves the static mappings.
 107        /// </summary>
 108        /// <param name="folder">The optional folder. If not defined, use {CurrentFolder}/__admin/mappings</param>
 109        [PublicAPI]
 110        public void SaveStaticMappings([CanBeNull] string folder = null)
 1111        {
 6112            foreach (var mapping in Mappings.Where(m => !m.IsAdminInterface))
 1113            {
 1114                SaveMappingToFile(mapping, folder);
 1115            }
 1116        }
 117
 118        /// <summary>
 119        /// Reads the static mappings from a folder.
 120        /// </summary>
 121        /// <param name="folder">The optional folder. If not defined, use {CurrentFolder}/__admin/mappings</param>
 122        [PublicAPI]
 123        public void ReadStaticMappings([CanBeNull] string folder = null)
 4124        {
 4125            if (folder == null)
 1126            {
 1127                folder = _fileSystemHandler.GetMappingFolder();
 1128            }
 129
 4130            if (!_fileSystemHandler.FolderExists(folder))
 1131            {
 1132                _logger.Info("The Static Mapping folder '{0}' does not exist, reading Static MappingFiles will be skippe
 1133                return;
 134            }
 135
 27136            foreach (string filename in _fileSystemHandler.EnumerateFiles(folder).OrderBy(f => f))
 6137            {
 6138                _logger.Info("Reading Static MappingFile : '{0}'", filename);
 139
 140                try
 6141                {
 6142                    ReadStaticMappingAndAddOrUpdate(filename);
 6143                }
 0144                catch
 0145                {
 0146                    _logger.Error("Static MappingFile : '{0}' could not be read. This file will be skipped.", filename);
 0147                }
 6148            }
 4149        }
 150
 151        /// <summary>
 152        /// Watches the static mappings for changes.
 153        /// </summary>
 154        /// <param name="folder">The optional folder. If not defined, use {CurrentFolder}/__admin/mappings</param>
 155        [PublicAPI]
 156        public void WatchStaticMappings([CanBeNull] string folder = null)
 1157        {
 1158            if (folder == null)
 1159            {
 1160                folder = _fileSystemHandler.GetMappingFolder();
 1161            }
 162
 1163            if (!_fileSystemHandler.FolderExists(folder))
 1164            {
 1165                return;
 166            }
 167
 0168            _logger.Info("Watching folder '{0}' for new, updated and deleted MappingFiles.", folder);
 169
 0170            var watcher = new EnhancedFileSystemWatcher(folder, "*.json", 1000);
 0171            watcher.Created += (sender, args) =>
 0172            {
 0173                _logger.Info("New MappingFile created : '{0}'", args.FullPath);
 0174                ReadStaticMappingAndAddOrUpdate(args.FullPath);
 0175            };
 0176            watcher.Changed += (sender, args) =>
 0177            {
 0178                _logger.Info("New MappingFile updated : '{0}'", args.FullPath);
 0179                ReadStaticMappingAndAddOrUpdate(args.FullPath);
 0180            };
 0181            watcher.Deleted += (sender, args) =>
 0182            {
 0183                _logger.Info("New MappingFile deleted : '{0}'", args.FullPath);
 0184                string filenameWithoutExtension = Path.GetFileNameWithoutExtension(args.FullPath);
 0185
 0186                if (Guid.TryParse(filenameWithoutExtension, out Guid guidFromFilename))
 0187                {
 0188                    DeleteMapping(guidFromFilename);
 0189                }
 0190                else
 0191                {
 0192                    DeleteMapping(args.FullPath);
 0193                }
 0194            };
 195
 0196            watcher.EnableRaisingEvents = true;
 1197        }
 198
 199        /// <summary>
 200        /// Reads a static mapping file and adds or updates the mapping.
 201        /// </summary>
 202        /// <param name="path">The path.</param>
 203        [PublicAPI]
 204        public void ReadStaticMappingAndAddOrUpdate([NotNull] string path)
 10205        {
 10206            Check.NotNull(path, nameof(path));
 207
 10208            string filenameWithoutExtension = Path.GetFileNameWithoutExtension(path);
 209
 10210            MappingModel mappingModel = JsonConvert.DeserializeObject<MappingModel>(_fileSystemHandler.ReadMappingFile(p
 10211            if (Guid.TryParse(filenameWithoutExtension, out Guid guidFromFilename))
 6212            {
 6213                DeserializeAndAddOrUpdateMapping(mappingModel, guidFromFilename, path);
 6214            }
 215            else
 4216            {
 4217                DeserializeAndAddOrUpdateMapping(mappingModel, null, path);
 4218            }
 10219        }
 220        #endregion
 221
 222        #region Proxy and Record
 223        private HttpClient _httpClientForProxy;
 224
 225        private void InitProxyAndRecord(IProxyAndRecordSettings settings)
 0226        {
 0227            _httpClientForProxy = HttpClientHelper.CreateHttpClient(settings.ClientX509Certificate2ThumbprintOrSubjectNa
 0228            Given(Request.Create().WithPath("/*").UsingAnyMethod()).RespondWith(new ProxyAsyncResponseProvider(ProxyAndR
 0229        }
 230
 231        private async Task<ResponseMessage> ProxyAndRecordAsync(RequestMessage requestMessage, IProxyAndRecordSettings s
 0232        {
 0233            var requestUri = new Uri(requestMessage.Url);
 0234            var proxyUri = new Uri(settings.Url);
 0235            var proxyUriWithRequestPathAndQuery = new Uri(proxyUri, requestUri.PathAndQuery);
 236
 0237            var responseMessage = await HttpClientHelper.SendAsync(_httpClientForProxy, requestMessage, proxyUriWithRequ
 238
 0239            if (settings.SaveMapping)
 0240            {
 0241                var mapping = ToMapping(requestMessage, responseMessage, settings.BlackListedHeaders ?? new string[] { }
 0242                _options.Mappings.TryAdd(mapping.Guid, mapping);
 243
 0244                if (settings.SaveMappingToFile)
 0245                {
 0246                    SaveMappingToFile(mapping);
 0247                }
 0248            }
 249
 0250            return responseMessage;
 0251        }
 252
 253        private Mapping ToMapping(RequestMessage requestMessage, ResponseMessage responseMessage, string[] blacklistedHe
 0254        {
 0255            var request = Request.Create();
 0256            request.WithPath(requestMessage.Path);
 0257            request.UsingMethod(requestMessage.Method);
 258
 0259            requestMessage.Query.Loop((key, value) => request.WithParam(key, value.ToArray()));
 0260            requestMessage.Cookies.Loop((key, value) => request.WithCookie(key, value));
 261
 0262            var allBlackListedHeaders = new List<string>(blacklistedHeaders) { "Cookie" };
 0263            requestMessage.Headers.Loop((key, value) =>
 0264            {
 0265                if (!allBlackListedHeaders.Any(b => string.Equals(key, b, StringComparison.OrdinalIgnoreCase)))
 0266                {
 0267                    request.WithHeader(key, value.ToArray());
 0268                }
 0269            });
 270
 0271            if (requestMessage.BodyAsJson != null)
 0272            {
 0273                request.WithBody(new JsonMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyAsJson));
 0274            }
 0275            else if (requestMessage.Body != null)
 0276            {
 0277                request.WithBody(new ExactMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.Body));
 0278            }
 279
 0280            var response = Response.Create(responseMessage);
 281
 0282            return new Mapping(Guid.NewGuid(), string.Empty, null, request, response, 0, null, null, null);
 0283        }
 284        #endregion
 285
 286        #region Settings
 287        private ResponseMessage SettingsGet(RequestMessage requestMessage)
 1288        {
 1289            var model = new SettingsModel
 1290            {
 1291                AllowPartialMapping = _options.AllowPartialMapping,
 1292                MaxRequestLogCount = _options.MaxRequestLogCount,
 1293                RequestLogExpirationDuration = _options.RequestLogExpirationDuration,
 1294                GlobalProcessingDelay = (int?)_options.RequestProcessingDelay?.TotalMilliseconds
 1295            };
 296
 1297            return ToJson(model);
 1298        }
 299
 300        private ResponseMessage SettingsUpdate(RequestMessage requestMessage)
 2301        {
 2302            var settings = DeserializeObject<SettingsModel>(requestMessage);
 2303            _options.MaxRequestLogCount = settings.MaxRequestLogCount;
 2304            _options.RequestLogExpirationDuration = settings.RequestLogExpirationDuration;
 305
 2306            if (settings.AllowPartialMapping != null)
 0307            {
 0308                _options.AllowPartialMapping = settings.AllowPartialMapping.Value;
 0309            }
 310
 2311            if (settings.GlobalProcessingDelay != null)
 0312            {
 0313                _options.RequestProcessingDelay = TimeSpan.FromMilliseconds(settings.GlobalProcessingDelay.Value);
 0314            }
 315
 2316            return ResponseMessageBuilder.Create("Settings updated");
 2317        }
 318        #endregion Settings
 319
 320        #region Mapping/{guid}
 321        private ResponseMessage MappingGet(RequestMessage requestMessage)
 0322        {
 0323            Guid guid = Guid.Parse(requestMessage.Path.Substring(AdminMappings.Length + 1));
 0324            var mapping = Mappings.FirstOrDefault(m => !m.IsAdminInterface && m.Guid == guid);
 325
 0326            if (mapping == null)
 0327            {
 0328                _logger.Warn("HttpStatusCode set to 404 : Mapping not found");
 0329                return ResponseMessageBuilder.Create("Mapping not found", 404);
 330            }
 331
 0332            var model = MappingConverter.ToMappingModel(mapping);
 333
 0334            return ToJson(model);
 0335        }
 336
 337        private ResponseMessage MappingPut(RequestMessage requestMessage)
 0338        {
 0339            Guid guid = Guid.Parse(requestMessage.Path.TrimStart(AdminMappings.ToCharArray()));
 340
 0341            var mappingModel = DeserializeObject<MappingModel>(requestMessage);
 0342            Guid? guidFromPut = DeserializeAndAddOrUpdateMapping(mappingModel, guid);
 343
 0344            return ResponseMessageBuilder.Create("Mapping added or updated", 200, guidFromPut);
 0345        }
 346
 347        private ResponseMessage MappingDelete(RequestMessage requestMessage)
 0348        {
 0349            Guid guid = Guid.Parse(requestMessage.Path.Substring(AdminMappings.Length + 1));
 350
 0351            if (DeleteMapping(guid))
 0352            {
 0353                return ResponseMessageBuilder.Create("Mapping removed", 200, guid);
 354            }
 355
 0356            return ResponseMessageBuilder.Create("Mapping not found", 404);
 0357        }
 358        #endregion Mapping/{guid}
 359
 360        #region Mappings
 361        private ResponseMessage MappingsSave(RequestMessage requestMessage)
 0362        {
 0363            SaveStaticMappings();
 364
 0365            return ResponseMessageBuilder.Create("Mappings saved to disk");
 0366        }
 367
 368        private void SaveMappingToFile(Mapping mapping, string folder = null)
 1369        {
 1370            if (folder == null)
 1371            {
 1372                folder = _fileSystemHandler.GetMappingFolder();
 1373            }
 374
 1375            if (!_fileSystemHandler.FolderExists(folder))
 0376            {
 0377                _fileSystemHandler.CreateFolder(folder);
 0378            }
 379
 1380            var model = MappingConverter.ToMappingModel(mapping);
 1381            string filename = (!string.IsNullOrEmpty(mapping.Title) ? SanitizeFileName(mapping.Title) : mapping.Guid.ToS
 382
 1383            string path = Path.Combine(folder, filename);
 384
 1385            _logger.Info("Saving Mapping file {0}", filename);
 386
 1387            _fileSystemHandler.WriteMappingFile(path, JsonConvert.SerializeObject(model, _settings));
 1388        }
 389
 390        private static string SanitizeFileName(string name, char replaceChar = '_')
 0391        {
 0392            return Path.GetInvalidFileNameChars().Aggregate(name, (current, c) => current.Replace(c, replaceChar));
 0393        }
 394
 395        private ResponseMessage MappingsGet(RequestMessage requestMessage)
 0396        {
 0397            var result = new List<MappingModel>();
 0398            foreach (var mapping in Mappings.Where(m => !m.IsAdminInterface))
 0399            {
 0400                var model = MappingConverter.ToMappingModel(mapping);
 0401                result.Add(model);
 0402            }
 403
 0404            return ToJson(result);
 0405        }
 406
 407        private ResponseMessage MappingsPost(RequestMessage requestMessage)
 1408        {
 409            Guid? guid;
 410            try
 1411            {
 1412                var mappingModel = DeserializeObject<MappingModel>(requestMessage);
 1413                guid = DeserializeAndAddOrUpdateMapping(mappingModel);
 1414            }
 0415            catch (ArgumentException a)
 0416            {
 0417                _logger.Error("HttpStatusCode set to 400 {0}", a);
 0418                return ResponseMessageBuilder.Create(a.Message, 400);
 419            }
 0420            catch (Exception e)
 0421            {
 0422                _logger.Error("HttpStatusCode set to 500 {0}", e);
 0423                return ResponseMessageBuilder.Create(e.ToString(), 500);
 424            }
 425
 1426            return ResponseMessageBuilder.Create("Mapping added", 201, guid);
 1427        }
 428
 429        private Guid? DeserializeAndAddOrUpdateMapping(MappingModel mappingModel, Guid? guid = null, string path = null)
 11430        {
 11431            Check.NotNull(mappingModel, nameof(mappingModel));
 11432            Check.NotNull(mappingModel.Request, nameof(mappingModel.Request));
 11433            Check.NotNull(mappingModel.Response, nameof(mappingModel.Response));
 434
 11435            var requestBuilder = InitRequestBuilder(mappingModel.Request, true);
 11436            if (requestBuilder == null)
 0437            {
 0438                return null;
 439            }
 440
 11441            var responseBuilder = InitResponseBuilder(mappingModel.Response);
 442
 11443            var respondProvider = Given(requestBuilder);
 444
 11445            if (guid != null)
 6446            {
 6447                respondProvider = respondProvider.WithGuid(guid.Value);
 6448            }
 5449            else if (mappingModel.Guid != null && mappingModel.Guid != Guid.Empty)
 3450            {
 3451                respondProvider = respondProvider.WithGuid(mappingModel.Guid.Value);
 3452            }
 453
 11454            if (path != null)
 10455            {
 10456                respondProvider = respondProvider.WithPath(path);
 10457            }
 458
 11459            if (!string.IsNullOrEmpty(mappingModel.Title))
 4460            {
 4461                respondProvider = respondProvider.WithTitle(mappingModel.Title);
 4462            }
 463
 11464            if (mappingModel.Priority != null)
 10465            {
 10466                respondProvider = respondProvider.AtPriority(mappingModel.Priority.Value);
 10467            }
 468
 11469            if (mappingModel.Scenario != null)
 0470            {
 0471                respondProvider = respondProvider.InScenario(mappingModel.Scenario);
 0472                respondProvider = respondProvider.WhenStateIs(mappingModel.WhenStateIs);
 0473                respondProvider = respondProvider.WillSetStateTo(mappingModel.SetStateTo);
 0474            }
 475
 11476            respondProvider.RespondWith(responseBuilder);
 477
 11478            return respondProvider.Guid;
 11479        }
 480
 481        private ResponseMessage MappingsDelete(RequestMessage requestMessage)
 0482        {
 0483            ResetMappings();
 484
 0485            ResetScenarios();
 486
 0487            return ResponseMessageBuilder.Create("Mappings deleted");
 0488        }
 489        #endregion Mappings
 490
 491        #region Request/{guid}
 492        private ResponseMessage RequestGet(RequestMessage requestMessage)
 0493        {
 0494            Guid guid = Guid.Parse(requestMessage.Path.Substring(AdminRequests.Length + 1));
 0495            var entry = LogEntries.FirstOrDefault(r => !r.RequestMessage.Path.StartsWith("/__admin/") && r.Guid == guid)
 496
 0497            if (entry == null)
 0498            {
 0499                _logger.Warn("HttpStatusCode set to 404 : Request not found");
 0500                return ResponseMessageBuilder.Create("Request not found", 404);
 501            }
 502
 0503            var model = LogEntryMapper.Map(entry);
 504
 0505            return ToJson(model);
 0506        }
 507
 508        private ResponseMessage RequestDelete(RequestMessage requestMessage)
 0509        {
 0510            Guid guid = Guid.Parse(requestMessage.Path.Substring(AdminRequests.Length + 1));
 511
 0512            if (DeleteLogEntry(guid))
 0513            {
 0514                return ResponseMessageBuilder.Create("Request removed");
 515            }
 516
 0517            return ResponseMessageBuilder.Create("Request not found", 404);
 0518        }
 519        #endregion Request/{guid}
 520
 521        #region Requests
 522        private ResponseMessage RequestsGet(RequestMessage requestMessage)
 3523        {
 3524            var result = LogEntries
 6525                .Where(r => !r.RequestMessage.Path.StartsWith("/__admin/"))
 3526                .Select(LogEntryMapper.Map);
 527
 3528            return ToJson(result);
 3529        }
 530
 531        private ResponseMessage RequestsDelete(RequestMessage requestMessage)
 0532        {
 0533            ResetLogEntries();
 534
 0535            return ResponseMessageBuilder.Create("Requests deleted");
 0536        }
 537        #endregion Requests
 538
 539        #region Requests/find
 540        private ResponseMessage RequestsFind(RequestMessage requestMessage)
 1541        {
 1542            var requestModel = DeserializeObject<RequestModel>(requestMessage);
 543
 1544            var request = (Request)InitRequestBuilder(requestModel, false);
 545
 1546            var dict = new Dictionary<LogEntry, RequestMatchResult>();
 6547            foreach (var logEntry in LogEntries.Where(le => !le.RequestMessage.Path.StartsWith("/__admin/")))
 1548            {
 1549                var requestMatchResult = new RequestMatchResult();
 1550                if (request.GetMatchingScore(logEntry.RequestMessage, requestMatchResult) > MatchScores.AlmostPerfect)
 1551                {
 1552                    dict.Add(logEntry, requestMatchResult);
 1553                }
 1554            }
 555
 3556            var result = dict.OrderBy(x => x.Value.AverageTotalScore).Select(x => x.Key).Select(LogEntryMapper.Map);
 557
 1558            return ToJson(result);
 1559        }
 560        #endregion Requests/find
 561
 562        #region Scenarios
 563        private ResponseMessage ScenariosGet(RequestMessage requestMessage)
 0564        {
 0565            var scenariosStates = Scenarios.Values.Select(s => new ScenarioStateModel
 0566            {
 0567                Name = s.Name,
 0568                NextState = s.NextState,
 0569                Started = s.Started,
 0570                Finished = s.Finished
 0571            });
 572
 0573            return ToJson(scenariosStates, true);
 0574        }
 575
 576        private ResponseMessage ScenariosReset(RequestMessage requestMessage)
 0577        {
 0578            ResetScenarios();
 579
 0580            return ResponseMessageBuilder.Create("Scenarios reset");
 0581        }
 582        #endregion
 583
 584        private IRequestBuilder InitRequestBuilder(RequestModel requestModel, bool pathOrUrlRequired)
 12585        {
 12586            IRequestBuilder requestBuilder = Request.Create();
 587
 12588            if (requestModel.ClientIP != null)
 0589            {
 0590                if (requestModel.ClientIP is string clientIP)
 0591                {
 0592                    requestBuilder = requestBuilder.WithClientIP(clientIP);
 0593                }
 594                else
 0595                {
 0596                    var clientIPModel = JsonUtils.ParseJTokenToObject<ClientIPModel>(requestModel.ClientIP);
 0597                    if (clientIPModel?.Matchers != null)
 0598                    {
 0599                        requestBuilder = requestBuilder.WithPath(clientIPModel.Matchers.Select(MatcherMapper.Map).Cast<I
 0600                    }
 0601                }
 0602            }
 603
 12604            bool pathOrUrlmatchersValid = false;
 12605            if (requestModel.Path != null)
 11606            {
 11607                if (requestModel.Path is string path)
 1608                {
 1609                    requestBuilder = requestBuilder.WithPath(path);
 1610                    pathOrUrlmatchersValid = true;
 1611                }
 612                else
 10613                {
 10614                    var pathModel = JsonUtils.ParseJTokenToObject<PathModel>(requestModel.Path);
 10615                    if (pathModel?.Matchers != null)
 10616                    {
 10617                        requestBuilder = requestBuilder.WithPath(pathModel.Matchers.Select(MatcherMapper.Map).Cast<IStri
 10618                        pathOrUrlmatchersValid = true;
 10619                    }
 10620                }
 11621            }
 1622            else if (requestModel.Url != null)
 0623            {
 0624                if (requestModel.Url is string url)
 0625                {
 0626                    requestBuilder = requestBuilder.WithUrl(url);
 0627                    pathOrUrlmatchersValid = true;
 0628                }
 629                else
 0630                {
 0631                    var urlModel = JsonUtils.ParseJTokenToObject<UrlModel>(requestModel.Url);
 0632                    if (urlModel?.Matchers != null)
 0633                    {
 0634                        requestBuilder = requestBuilder.WithUrl(urlModel.Matchers.Select(MatcherMapper.Map).Cast<IString
 0635                        pathOrUrlmatchersValid = true;
 0636                    }
 0637                }
 0638            }
 639
 12640            if (pathOrUrlRequired && !pathOrUrlmatchersValid)
 0641            {
 0642                _logger.Error("Path or Url matcher is missing for this mapping, this mapping will not be added.");
 0643                return null;
 644            }
 645
 12646            if (requestModel.Methods != null)
 11647            {
 11648                requestBuilder = requestBuilder.UsingMethod(requestModel.Methods);
 11649            }
 650
 12651            if (requestModel.Headers != null)
 0652            {
 0653                foreach (var headerModel in requestModel.Headers.Where(h => h.Matchers != null))
 0654                {
 0655                    requestBuilder = requestBuilder.WithHeader(headerModel.Name, headerModel.Matchers.Select(MatcherMapp
 0656                }
 0657            }
 658
 12659            if (requestModel.Cookies != null)
 0660            {
 0661                foreach (var cookieModel in requestModel.Cookies.Where(c => c.Matchers != null))
 0662                {
 0663                    requestBuilder = requestBuilder.WithCookie(cookieModel.Name, cookieModel.Matchers.Select(MatcherMapp
 0664                }
 0665            }
 666
 12667            if (requestModel.Params != null)
 0668            {
 0669                foreach (var paramModel in requestModel.Params.Where(c => c.Matchers != null))
 0670                {
 0671                    requestBuilder = requestBuilder.WithParam(paramModel.Name, paramModel.Matchers.Select(MatcherMapper.
 0672                }
 0673            }
 674
 12675            if (requestModel.Body?.Matcher != null)
 3676            {
 3677                var bodyMatcher = MatcherMapper.Map(requestModel.Body.Matcher);
 3678                requestBuilder = requestBuilder.WithBody(bodyMatcher);
 3679            }
 680
 12681            return requestBuilder;
 12682        }
 683
 684        private IResponseBuilder InitResponseBuilder(ResponseModel responseModel)
 11685        {
 11686            IResponseBuilder responseBuilder = Response.Create();
 687
 11688            if (responseModel.Delay > 0)
 0689            {
 0690                responseBuilder = responseBuilder.WithDelay(responseModel.Delay.Value);
 0691            }
 692
 11693            if (!string.IsNullOrEmpty(responseModel.ProxyUrl))
 0694            {
 0695                if (string.IsNullOrEmpty(responseModel.X509Certificate2ThumbprintOrSubjectName))
 0696                {
 0697                    return responseBuilder.WithProxy(responseModel.ProxyUrl);
 698                }
 699
 0700                return responseBuilder.WithProxy(responseModel.ProxyUrl, responseModel.X509Certificate2ThumbprintOrSubje
 701            }
 702
 11703            if (responseModel.StatusCode.HasValue)
 10704            {
 10705                responseBuilder = responseBuilder.WithStatusCode(responseModel.StatusCode.Value);
 10706            }
 707
 11708            if (responseModel.Headers != null)
 9709            {
 189710                foreach (var entry in responseModel.Headers)
 81711                {
 81712                    responseBuilder = entry.Value is string value ?
 81713                        responseBuilder.WithHeader(entry.Key, value) :
 81714                        responseBuilder.WithHeader(entry.Key, JsonUtils.ParseJTokenToObject<string[]>(entry.Value));
 81715                }
 9716            }
 2717            else if (responseModel.HeadersRaw != null)
 0718            {
 0719                foreach (string headerLine in responseModel.HeadersRaw.Split(new[] { "\n", "\r\n" }, StringSplitOptions.
 0720                {
 0721                    int indexColon = headerLine.IndexOf(":", StringComparison.Ordinal);
 0722                    string key = headerLine.Substring(0, indexColon).TrimStart(' ', '\t');
 0723                    string value = headerLine.Substring(indexColon + 1).TrimStart(' ', '\t');
 0724                    responseBuilder = responseBuilder.WithHeader(key, value);
 0725                }
 0726            }
 727
 11728            if (responseModel.BodyAsBytes != null)
 0729            {
 0730                responseBuilder = responseBuilder.WithBody(responseModel.BodyAsBytes, responseModel.BodyDestination, ToE
 0731            }
 11732            else if (responseModel.Body != null)
 7733            {
 7734                responseBuilder = responseBuilder.WithBody(responseModel.Body, responseModel.BodyDestination, ToEncoding
 7735            }
 4736            else if (responseModel.BodyAsJson != null)
 1737            {
 1738                responseBuilder = responseBuilder.WithBodyAsJson(responseModel.BodyAsJson, ToEncoding(responseModel.Body
 1739            }
 3740            else if (responseModel.BodyFromBase64 != null)
 0741            {
 0742                responseBuilder = responseBuilder.WithBodyFromBase64(responseModel.BodyFromBase64, ToEncoding(responseMo
 0743            }
 3744            else if (responseModel.BodyAsFile != null)
 3745            {
 3746                responseBuilder = responseBuilder.WithBodyFromFile(responseModel.BodyAsFile);
 3747            }
 748
 11749            if (responseModel.UseTransformer)
 0750            {
 0751                responseBuilder = responseBuilder.WithTransformer();
 0752            }
 753
 11754            return responseBuilder;
 11755        }
 756
 757        private ResponseMessage ToJson<T>(T result, bool keepNullValues = false)
 5758        {
 5759            return new ResponseMessage
 5760            {
 5761                Body = JsonConvert.SerializeObject(result, keepNullValues ? _settingsIncludeNullValues : _settings),
 5762                StatusCode = 200,
 5763                Headers = new Dictionary<string, WireMockList<string>> { { HttpKnownHeaderNames.ContentType, new WireMoc
 5764            };
 5765        }
 766
 767        private Encoding ToEncoding(EncodingModel encodingModel)
 8768        {
 8769            return encodingModel != null ? Encoding.GetEncoding(encodingModel.CodePage) : null;
 8770        }
 771
 772        private T DeserializeObject<T>(RequestMessage requestMessage)
 4773        {
 4774            return requestMessage.Body != null ?
 4775                JsonConvert.DeserializeObject<T>(requestMessage.Body) :
 4776                ((JObject)requestMessage.BodyAsJson).ToObject<T>();
 4777        }
 778    }
 779}

C:\Users\azureuser\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.Http;
 12using WireMock.Logging;
 13using WireMock.Matchers;
 14using WireMock.Matchers.Request;
 15using WireMock.Owin;
 16using WireMock.RequestBuilders;
 17using WireMock.ResponseProviders;
 18using WireMock.Settings;
 19using WireMock.Util;
 20using WireMock.Validation;
 21
 22namespace WireMock.Server
 23{
 24    /// <summary>
 25    /// The fluent mock server.
 26    /// </summary>
 27    public partial class FluentMockServer : IDisposable
 28    {
 29        private readonly IWireMockLogger _logger;
 30        private readonly IFileSystemHandler _fileSystemHandler;
 31
 32        private const int ServerStartDelay = 100;
 33        private readonly IOwinSelfHost _httpServer;
 4934        private readonly WireMockMiddlewareOptions _options = new WireMockMiddlewareOptions();
 35
 36        /// <summary>
 37        /// Gets a value indicating whether this server is started.
 38        /// </summary>
 39        [PublicAPI]
 040        public bool IsStarted => _httpServer != null && _httpServer.IsStarted;
 41
 42        /// <summary>
 43        /// Gets the ports.
 44        /// </summary>
 45        [PublicAPI]
 4046        public List<int> Ports { get; }
 47
 48        /// <summary>
 49        /// Gets the urls.
 50        /// </summary>
 51        [PublicAPI]
 6752        public string[] Urls { get; }
 53
 54        /// <summary>
 55        /// Gets the mappings.
 56        /// </summary>
 57        [PublicAPI]
 1558        public IEnumerable<Mapping> Mappings => _options.Mappings.Values.ToArray();
 59
 60        /// <summary>
 61        /// Gets the scenarios.
 62        /// </summary>
 63        [PublicAPI]
 1364        public ConcurrentDictionary<string, ScenarioState> Scenarios => new ConcurrentDictionary<string, ScenarioState>(
 65
 66        #region IDisposable Members
 67        /// <summary>
 68        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
 69        /// </summary>
 70        public void Dispose()
 071        {
 072            Dispose(true);
 073            GC.SuppressFinalize(this);
 074        }
 75
 76        /// <summary>
 77        /// Releases unmanaged and - optionally - managed resources.
 78        /// </summary>
 79        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release
 80        protected virtual void Dispose(bool disposing)
 081        {
 082            if (_httpServer != null)
 083            {
 084                _httpServer.StopAsync();
 085            }
 086        }
 87        #endregion
 88
 89        #region Start/Stop
 90        /// <summary>
 91        /// Starts the specified settings.
 92        /// </summary>
 93        /// <param name="settings">The FluentMockServerSettings.</param>
 94        /// <returns>The <see cref="FluentMockServer"/>.</returns>
 95        [PublicAPI]
 96        public static FluentMockServer Start(IFluentMockServerSettings settings)
 997        {
 998            Check.NotNull(settings, nameof(settings));
 99
 9100            return new FluentMockServer(settings);
 9101        }
 102
 103        /// <summary>
 104        /// Start this FluentMockServer.
 105        /// </summary>
 106        /// <param name="port">The port.</param>
 107        /// <param name="ssl">The SSL support.</param>
 108        /// <returns>The <see cref="FluentMockServer"/>.</returns>
 109        [PublicAPI]
 110        public static FluentMockServer Start([CanBeNull] int? port = 0, bool ssl = false)
 34111        {
 34112            return new FluentMockServer(new FluentMockServerSettings
 34113            {
 34114                Port = port,
 34115                UseSSL = ssl
 34116            });
 34117        }
 118
 119        /// <summary>
 120        /// Start this FluentMockServer.
 121        /// </summary>
 122        /// <param name="urls">The urls to listen on.</param>
 123        /// <returns>The <see cref="FluentMockServer"/>.</returns>
 124        [PublicAPI]
 125        public static FluentMockServer Start(params string[] urls)
 2126        {
 2127            Check.NotNullOrEmpty(urls, nameof(urls));
 128
 2129            return new FluentMockServer(new FluentMockServerSettings
 2130            {
 2131                Urls = urls
 2132            });
 2133        }
 134
 135        /// <summary>
 136        /// Start this FluentMockServer with the admin interface.
 137        /// </summary>
 138        /// <param name="port">The port.</param>
 139        /// <param name="ssl">The SSL support.</param>
 140        /// <returns>The <see cref="FluentMockServer"/>.</returns>
 141        [PublicAPI]
 142        public static FluentMockServer StartWithAdminInterface(int? port = 0, bool ssl = false)
 4143        {
 4144            return new FluentMockServer(new FluentMockServerSettings
 4145            {
 4146                Port = port,
 4147                UseSSL = ssl,
 4148                StartAdminInterface = true
 4149            });
 4150        }
 151
 152        /// <summary>
 153        /// Start this FluentMockServer with the admin interface.
 154        /// </summary>
 155        /// <param name="urls">The urls.</param>
 156        /// <returns>The <see cref="FluentMockServer"/>.</returns>
 157        [PublicAPI]
 158        public static FluentMockServer StartWithAdminInterface(params string[] urls)
 0159        {
 0160            Check.NotNullOrEmpty(urls, nameof(urls));
 161
 0162            return new FluentMockServer(new FluentMockServerSettings
 0163            {
 0164                Urls = urls,
 0165                StartAdminInterface = true
 0166            });
 0167        }
 168
 169        /// <summary>
 170        /// Start this FluentMockServer with the admin interface and read static mappings.
 171        /// </summary>
 172        /// <param name="urls">The urls.</param>
 173        /// <returns>The <see cref="FluentMockServer"/>.</returns>
 174        [PublicAPI]
 175        public static FluentMockServer StartWithAdminInterfaceAndReadStaticMappings(params string[] urls)
 0176        {
 0177            Check.NotNullOrEmpty(urls, nameof(urls));
 178
 0179            return new FluentMockServer(new FluentMockServerSettings
 0180            {
 0181                Urls = urls,
 0182                StartAdminInterface = true,
 0183                ReadStaticMappings = true
 0184            });
 0185        }
 186
 49187        private FluentMockServer(IFluentMockServerSettings settings)
 49188        {
 49189            settings.Logger = settings.Logger ?? new WireMockConsoleLogger();
 190
 49191            _logger = settings.Logger;
 49192            _fileSystemHandler = settings.FileSystemHandler ?? new LocalFileSystemHandler();
 193
 49194            _logger.Info("WireMock.Net by Stef Heyenrath (https://github.com/WireMock-Net/WireMock.Net)");
 49195            _logger.Debug("WireMock.Net server settings {0}", JsonConvert.SerializeObject(settings, Formatting.Indented)
 196
 49197            if (settings.Urls != null)
 2198            {
 2199                Urls = settings.Urls.ToArray();
 2200            }
 201            else
 47202            {
 47203                int port = settings.Port > 0 ? settings.Port.Value : PortUtils.FindFreeTcpPort();
 47204                Urls = new[] { $"{(settings.UseSSL == true ? "https" : "http")}://localhost:{port}" };
 47205            }
 206
 49207            _options.PreWireMockMiddlewareInit = settings.PreWireMockMiddlewareInit;
 49208            _options.PostWireMockMiddlewareInit = settings.PostWireMockMiddlewareInit;
 49209            _options.Logger = _logger;
 210
 211#if USE_ASPNETCORE
 49212            _httpServer = new AspNetCoreSelfHost(_options, Urls);
 213#else
 214            _httpServer = new OwinSelfHost(_options, Urls);
 215#endif
 49216            Ports = _httpServer.Ports;
 217
 49218            _httpServer.StartAsync();
 219
 49220            using (var ctsStartTimeout = new CancellationTokenSource(settings.StartTimeout))
 49221            {
 382222                while (!_httpServer.IsStarted)
 333223                {
 224                    // Throw out exception if service start fails
 333225                    if (_httpServer.RunningException != null)
 0226                    {
 0227                        throw new Exception($"Service start failed with error: {_httpServer.RunningException.Message}", 
 228                    }
 229
 230                    // Respect start timeout setting by throwing TimeoutException
 333231                    if (ctsStartTimeout.IsCancellationRequested)
 0232                    {
 0233                        throw new TimeoutException($"Service start timed out after {TimeSpan.FromMilliseconds(settings.S
 234                    }
 235
 333236                    ctsStartTimeout.Token.WaitHandle.WaitOne(ServerStartDelay);
 333237                }
 49238            }
 239
 49240            if (settings.AllowPartialMapping == true)
 0241            {
 0242                AllowPartialMapping();
 0243            }
 244
 49245            if (settings.StartAdminInterface == true)
 8246            {
 8247                if (!string.IsNullOrEmpty(settings.AdminUsername) && !string.IsNullOrEmpty(settings.AdminPassword))
 0248                {
 0249                    SetBasicAuthentication(settings.AdminUsername, settings.AdminPassword);
 0250                }
 251
 8252                InitAdmin();
 8253            }
 254
 49255            if (settings.ReadStaticMappings == true)
 0256            {
 0257                ReadStaticMappings();
 0258            }
 259
 49260            if (settings.WatchStaticMappings == true)
 0261            {
 0262                WatchStaticMappings();
 0263            }
 264
 49265            if (settings.ProxyAndRecordSettings != null)
 0266            {
 0267                InitProxyAndRecord(settings.ProxyAndRecordSettings);
 0268            }
 269
 49270            if (settings.MaxRequestLogCount != null)
 0271            {
 0272                SetMaxRequestLogCount(settings.MaxRequestLogCount);
 0273            }
 49274        }
 275
 276        /// <summary>
 277        /// Stop this server.
 278        /// </summary>
 279        [PublicAPI]
 280        public void Stop()
 3281        {
 3282            var result = _httpServer?.StopAsync();
 3283            result?.Wait(); // wait for stop to actually happen
 3284        }
 285        #endregion
 286
 287        /// <summary>
 288        /// Adds the catch all mapping.
 289        /// </summary>
 290        [PublicAPI]
 291        public void AddCatchAllMapping()
 0292        {
 0293            Given(Request.Create().WithPath("/*").UsingAnyMethod())
 0294                .WithGuid(Guid.Parse("90008000-0000-4444-a17e-669cd84f1f05"))
 0295                .AtPriority(1000)
 0296                .RespondWith(new DynamicResponseProvider(request => ResponseMessageBuilder.Create("No matching mapping f
 0297        }
 298
 299        /// <summary>
 300        /// Resets LogEntries and Mappings.
 301        /// </summary>
 302        [PublicAPI]
 303        public void Reset()
 0304        {
 0305            ResetLogEntries();
 306
 0307            ResetMappings();
 0308        }
 309
 310        /// <summary>
 311        /// Resets the Mappings.
 312        /// </summary>
 313        [PublicAPI]
 314        public void ResetMappings()
 10315        {
 66316            foreach (var nonAdmin in _options.Mappings.ToArray().Where(m => !m.Value.IsAdminInterface))
 12317            {
 12318                _options.Mappings.TryRemove(nonAdmin.Key, out _);
 12319            }
 10320        }
 321
 322        /// <summary>
 323        /// Deletes the mapping.
 324        /// </summary>
 325        /// <param name="guid">The unique identifier.</param>
 326        [PublicAPI]
 327        public bool DeleteMapping(Guid guid)
 0328        {
 329            // Check a mapping exists with the same GUID, if so, remove it.
 0330            if (_options.Mappings.ContainsKey(guid))
 0331            {
 0332                return _options.Mappings.TryRemove(guid, out _);
 333            }
 334
 0335            return false;
 0336        }
 337
 338        private bool DeleteMapping(string path)
 0339        {
 340            // Check a mapping exists with the same path, if so, remove it.
 0341            var mapping = _options.Mappings.ToArray().FirstOrDefault(entry => string.Equals(entry.Value.Path, path, Stri
 0342            return DeleteMapping(mapping.Key);
 0343        }
 344
 345        /// <summary>
 346        /// The add request processing delay.
 347        /// </summary>
 348        /// <param name="delay">The delay.</param>
 349        [PublicAPI]
 350        public void AddGlobalProcessingDelay(TimeSpan delay)
 1351        {
 1352            _options.RequestProcessingDelay = delay;
 1353        }
 354
 355        /// <summary>
 356        /// Allows the partial mapping.
 357        /// </summary>
 358        [PublicAPI]
 359        public void AllowPartialMapping(bool allow = true)
 0360        {
 0361            _logger.Info("AllowPartialMapping is set to {0}", allow);
 0362            _options.AllowPartialMapping = allow;
 0363        }
 364
 365        /// <summary>
 366        /// Sets the basic authentication.
 367        /// </summary>
 368        /// <param name="username">The username.</param>
 369        /// <param name="password">The password.</param>
 370        [PublicAPI]
 371        public void SetBasicAuthentication([NotNull] string username, [NotNull] string password)
 0372        {
 0373            Check.NotNull(username, nameof(username));
 0374            Check.NotNull(password, nameof(password));
 375
 0376            string authorization = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + p
 0377            _options.AuthorizationMatcher = new RegexMatcher(MatchBehaviour.AcceptOnMatch, "^(?i)BASIC " + authorization
 0378        }
 379
 380        /// <summary>
 381        /// Removes the basic authentication.
 382        /// </summary>
 383        [PublicAPI]
 384        public void RemoveBasicAuthentication()
 0385        {
 0386            _options.AuthorizationMatcher = null;
 0387        }
 388
 389        /// <summary>
 390        /// Sets the maximum RequestLog count.
 391        /// </summary>
 392        /// <param name="maxRequestLogCount">The maximum RequestLog count.</param>
 393        [PublicAPI]
 394        public void SetMaxRequestLogCount([CanBeNull] int? maxRequestLogCount)
 1395        {
 1396            _options.MaxRequestLogCount = maxRequestLogCount;
 1397        }
 398
 399        /// <summary>
 400        /// Sets RequestLog expiration in hours.
 401        /// </summary>
 402        /// <param name="requestLogExpirationDuration">The RequestLog expiration in hours.</param>
 403        [PublicAPI]
 404        public void SetRequestLogExpirationDuration([CanBeNull] int? requestLogExpirationDuration)
 0405        {
 0406            _options.RequestLogExpirationDuration = requestLogExpirationDuration;
 0407        }
 408
 409        /// <summary>
 410        /// Resets the Scenarios.
 411        /// </summary>
 412        [PublicAPI]
 413        public void ResetScenarios()
 0414        {
 0415            _options.Scenarios.Clear();
 0416        }
 417
 418        /// <summary>
 419        /// The given.
 420        /// </summary>
 421        /// <param name="requestMatcher">The request matcher.</param>
 422        /// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
 423        [PublicAPI]
 424        public IRespondWithAProvider Given(IRequestMatcher requestMatcher)
 205425        {
 205426            return new RespondWithAProvider(RegisterMapping, requestMatcher);
 205427        }
 428
 429        private void RegisterMapping(Mapping mapping)
 205430        {
 431            // Check a mapping exists with the same Guid, if so, replace it.
 205432            if (_options.Mappings.ContainsKey(mapping.Guid))
 1433            {
 1434                _options.Mappings[mapping.Guid] = mapping;
 1435            }
 436            else
 204437            {
 204438                _options.Mappings.TryAdd(mapping.Guid, mapping);
 204439            }
 205440        }
 441    }
 442}

C:\Users\azureuser\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]
 1230        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)
 139        {
 140            var results = new Dictionary<LogEntry, RequestMatchResult>();
 41
 742            foreach (var log in _options.LogEntries)
 243            {
 244                var requestMatchResult = new RequestMatchResult();
 1045                foreach (var matcher in matchers)
 246                {
 247                    matcher.GetMatchingScore(log.RequestMessage, requestMatchResult);
 248                }
 49
 250                if (requestMatchResult.AverageTotalScore > MatchScores.AlmostPerfect)
 151                {
 152                    results.Add(log, requestMatchResult);
 153                }
 254            }
 55
 356            return new ReadOnlyCollection<LogEntry>(results.OrderBy(x => x.Value).Select(x => x.Key).ToList());
 157        }
 58
 59        /// <summary>
 60        /// Resets the LogEntries.
 61        /// </summary>
 62        [PublicAPI]
 63        public void ResetLogEntries()
 964        {
 965            _options.LogEntries.Clear();
 966        }
 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.IProxyAndRecordSettings)
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.Mapping,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.Mapping)
add_LogEntriesChanged(System.Collections.Specialized.NotifyCollectionChangedEventHandler)
remove_LogEntriesChanged(System.Collections.Specialized.NotifyCollectionChangedEventHandler)
LogEntries()
FindLogEntries(WireMock.Matchers.Request.IRequestMatcher[])
ResetLogEntries()
DeleteLogEntry(System.Guid)