private async Task InvokeInternal(IContext ctx) { var request = await _requestMapper.MapAsync(ctx.Request, _options); bool logRequest = false; ResponseMessage response = null; (MappingMatcherResult Match, MappingMatcherResult Partial)result = (null, null); try { foreach (var mapping in _options.Mappings.Values.Where(m => m?.Scenario != null)) { // Set scenario start if (!_options.Scenarios.ContainsKey(mapping.Scenario) && mapping.IsStartState) { _options.Scenarios.TryAdd(mapping.Scenario, new ScenarioState { Name = mapping.Scenario }); } } result = _mappingMatcher.FindBestMatch(request); var targetMapping = result.Match?.Mapping; if (targetMapping == null) { logRequest = true; _options.Logger.Warn("HttpStatusCode set to 404 : No matching mapping found"); response = ResponseMessageBuilder.Create("No matching mapping found", 404); return; } logRequest = targetMapping.LogMapping; if (targetMapping.IsAdminInterface && _options.AuthorizationMatcher != null) { bool present = request.Headers.TryGetValue(HttpKnownHeaderNames.Authorization, out WireMockList <string> authorization); if (!present || _options.AuthorizationMatcher.IsMatch(authorization.ToString()) < MatchScores.Perfect) { _options.Logger.Error("HttpStatusCode set to 401"); response = ResponseMessageBuilder.Create(null, 401); return; } } if (!targetMapping.IsAdminInterface && _options.RequestProcessingDelay > TimeSpan.Zero) { await Task.Delay(_options.RequestProcessingDelay.Value); } response = await targetMapping.ProvideResponseAsync(request); var responseBuilder = targetMapping.Provider as Response; if (!targetMapping.IsAdminInterface) { if (responseBuilder?.ProxyAndRecordSettings?.SaveMapping == true || targetMapping?.Settings?.ProxyAndRecordSettings?.SaveMapping == true) { _options.Mappings.TryAdd(targetMapping.Guid, targetMapping); } if (responseBuilder?.ProxyAndRecordSettings?.SaveMappingToFile == true || targetMapping?.Settings?.ProxyAndRecordSettings?.SaveMappingToFile == true) { var matcherMapper = new MatcherMapper(targetMapping.Settings); var mappingConverter = new MappingConverter(matcherMapper); var mappingToFileSaver = new MappingToFileSaver(targetMapping.Settings, mappingConverter); mappingToFileSaver.SaveMappingToFile(targetMapping); } } if (targetMapping.Scenario != null) { UpdateScenarioState(targetMapping); } } catch (Exception ex) { _options.Logger.Error($"Providing a Response for Mapping '{result.Match?.Mapping?.Guid}' failed. HttpStatusCode set to 500. Exception: {ex}"); response = ResponseMessageBuilder.Create(ex.Message, 500); } finally { var log = new LogEntry { Guid = Guid.NewGuid(), RequestMessage = request, ResponseMessage = response, MappingGuid = result.Match?.Mapping?.Guid, MappingTitle = result.Match?.Mapping?.Title, RequestMatchResult = result.Match?.RequestMatchResult, PartialMappingGuid = result.Partial?.Mapping?.Guid, PartialMappingTitle = result.Partial?.Mapping?.Title, PartialMatchResult = result.Partial?.RequestMatchResult }; LogRequest(log, logRequest); await _responseMapper.MapAsync(response, ctx.Response); } await CompletedTask; }
/// <summary> /// Initializes a new instance of the <see cref="WireMockServer"/> class. /// </summary> /// <param name="settings">The settings.</param> /// <exception cref="WireMockException"> /// Service start failed with error: {_httpServer.RunningException.Message} /// or /// Service start failed with error: {startTask.Exception.Message} /// </exception> /// <exception cref="TimeoutException">Service start timed out after {TimeSpan.FromMilliseconds(settings.StartTimeout)}</exception> protected WireMockServer(IWireMockServerSettings settings) { _settings = settings; // Set default values if not provided _settings.Logger = settings.Logger ?? new WireMockNullLogger(); _settings.FileSystemHandler = settings.FileSystemHandler ?? new LocalFileSystemHandler(); _settings.Logger.Info("WireMock.Net by Stef Heyenrath (https://github.com/WireMock-Net/WireMock.Net)"); _settings.Logger.Debug("WireMock.Net server settings {0}", JsonConvert.SerializeObject(settings, Formatting.Indented)); HostUrlOptions urlOptions; if (settings.Urls != null) { urlOptions = new HostUrlOptions { Urls = settings.Urls }; } else { urlOptions = new HostUrlOptions { UseSSL = settings.UseSSL == true, Port = settings.Port }; } _options.FileSystemHandler = _settings.FileSystemHandler; _options.PreWireMockMiddlewareInit = _settings.PreWireMockMiddlewareInit; _options.PostWireMockMiddlewareInit = _settings.PostWireMockMiddlewareInit; _options.Logger = _settings.Logger; _options.DisableJsonBodyParsing = _settings.DisableJsonBodyParsing; _options.HandleRequestsSynchronously = settings.HandleRequestsSynchronously; if (settings.CustomCertificateDefined) { _options.X509StoreName = settings.CertificateSettings.X509StoreName; _options.X509StoreLocation = settings.CertificateSettings.X509StoreLocation; _options.X509ThumbprintOrSubjectName = settings.CertificateSettings.X509StoreThumbprintOrSubjectName; _options.X509CertificateFilePath = settings.CertificateSettings.X509CertificateFilePath; _options.X509CertificatePassword = settings.CertificateSettings.X509CertificatePassword; } _matcherMapper = new MatcherMapper(_settings); _mappingConverter = new MappingConverter(_matcherMapper); _mappingToFileSaver = new MappingToFileSaver(_settings, _mappingConverter); #if USE_ASPNETCORE _httpServer = new AspNetCoreSelfHost(_options, urlOptions); #else _httpServer = new OwinSelfHost(_options, urlOptions); #endif var startTask = _httpServer.StartAsync(); using (var ctsStartTimeout = new CancellationTokenSource(settings.StartTimeout)) { while (!_httpServer.IsStarted) { // Throw exception if service start fails if (_httpServer.RunningException != null) { throw new WireMockException($"Service start failed with error: {_httpServer.RunningException.Message}", _httpServer.RunningException); } if (ctsStartTimeout.IsCancellationRequested) { // In case of an aggregate exception, throw the exception. if (startTask.Exception != null) { throw new WireMockException($"Service start failed with error: {startTask.Exception.Message}", startTask.Exception); } // Else throw TimeoutException throw new TimeoutException($"Service start timed out after {TimeSpan.FromMilliseconds(settings.StartTimeout)}"); } ctsStartTimeout.Token.WaitHandle.WaitOne(ServerStartDelayInMs); } Urls = _httpServer.Urls.ToArray(); Ports = _httpServer.Ports; } if (settings.AllowBodyForAllHttpMethods == true) { _options.AllowBodyForAllHttpMethods = _settings.AllowBodyForAllHttpMethods; _settings.Logger.Info("AllowBodyForAllHttpMethods is set to True"); } if (settings.AllowOnlyDefinedHttpStatusCodeInResponse == true) { _options.AllowOnlyDefinedHttpStatusCodeInResponse = _settings.AllowOnlyDefinedHttpStatusCodeInResponse; _settings.Logger.Info("AllowOnlyDefinedHttpStatusCodeInResponse is set to True"); } if (settings.AllowPartialMapping == true) { AllowPartialMapping(); } if (settings.StartAdminInterface == true) { if (!string.IsNullOrEmpty(settings.AdminUsername) && !string.IsNullOrEmpty(settings.AdminPassword)) { SetBasicAuthentication(settings.AdminUsername, settings.AdminPassword); } InitAdmin(); } if (settings.ReadStaticMappings == true) { ReadStaticMappings(); } if (settings.WatchStaticMappings == true) { WatchStaticMappings(); } if (settings.ProxyAndRecordSettings != null) { InitProxyAndRecord(settings); } if (settings.RequestLogExpirationDuration != null) { SetRequestLogExpirationDuration(settings.RequestLogExpirationDuration); } if (settings.MaxRequestLogCount != null) { SetMaxRequestLogCount(settings.MaxRequestLogCount); } }