private static void StartServices(HttpServerConfiguration <TAccount> configuration) { ServiceUris.AddRange(configuration.GetReservedUris()); if (ServiceUris.Any()) { LogDebug($"Reserved sections:\n{string.Join("\n", ServiceUris)}"); } ServiceRequestProcessors.Add(_optionsController); if (configuration.FilesEnabled) { ServiceRequestProcessors.Add(_fileRequestController); } if (configuration.StatisticsEnabled) { ServiceRequestProcessors.Add(_statisticsController); } ServiceRequestProcessors.Add(_pingController); if (configuration.ConfigurationViewEnabled) { ServiceRequestProcessors.Add(_configurationController); } ServiceRequestProcessors.Add(_authentificationController); }
private static async Task HandleRequestAsync(HttpListenerContext context) { var request = context.Request; // This Stopwatch will be used by different threads, but sequentially (select processor => handle => completion) var stopWatch = Stopwatch.StartNew(); try { _statisticsController.Statistics?.AddRequest(request); var isBinaryRequest = _fileRequestController != null && _fileRequestController.RequestIsSuitable(request); if (RequestTracingEnabled) { LogTrace($"Request from {request.RemoteEndPoint}.\n{CommonHelper.SerializeHttpRequest(context, false, ! isBinaryRequest)}"); } var serviceProcessor = ServiceRequestProcessors.FirstOrDefault(sp => sp.RequestIsSuitable(context.Request)); if (serviceProcessor != null) { LogDebug($"Service {serviceProcessor.Name} requested"); await serviceProcessor.HandleRequestAsync(context); CompleteContext(context, stopWatch); return; } var requestProcessorSelectionResult = SelectRequestProcessor(request); if (requestProcessorSelectionResult == null) { ResponseFactory.BuildResponse(context, HttpStatusCode.NotFound, null); CompleteContext(context, stopWatch); return; } if (requestProcessorSelectionResult.IsRedirect) { var redirectLocation = $"{_serverAddress}{requestProcessorSelectionResult.RequestProcessor.SubUri}"; context.Response.Redirect(redirectLocation); CompleteContext(context, stopWatch); return; } if (!requestProcessorSelectionResult.MethodMatches) { ResponseFactory.BuildResponse(context, HttpStatusCode.MethodNotAllowed, null); CompleteContext(context, stopWatch); return; } var requestProcessor = requestProcessorSelectionResult.RequestProcessor; AuthorizationResult <TAccount> authResult; if (requestProcessor.AuthorizationRequired && _authorizer != null) { authResult = await _authorizer.Invoke(request, requestProcessor); } else { authResult = new AuthorizationResult <TAccount>(null, AuthorizationStatus.NotRequired); } _statisticsController.Statistics?.AddAuthResult(authResult); switch (authResult.Status) { case AuthorizationStatus.NotRequired: case AuthorizationStatus.Ok: if (requestProcessor.Handler == null) { LogDebug($"{request.HttpMethod} {request.Url.LocalPath} was requested, but no handler is provided"); ResponseFactory.BuildResponse(context, HttpStatusCode.NotImplemented, null); } else { var handleResult = await requestProcessor.Handler.Invoke(authResult.Account, request).ConfigureAwait(false); ResponseFactory.BuildResponse(context, handleResult); } break; default: ResponseFactory.BuildResponse(context, authResult); break; } CompleteContext(context, stopWatch); } catch (Exception exception) { LogMessage(LogLevel.Warning, $"Error handling client request from {request.RemoteEndPoint}"); LogException(LogLevel.Warning, exception); ResponseFactory.BuildResponse(context, HttpStatusCode.InternalServerError, null); CompleteContext(context, stopWatch); } }