/// <inheritdoc />
        public async Task <Response> SendAsync(Request request, TimeSpan?connectionTimeout, TimeSpan timeout, CancellationToken cancellationToken)
        {
            if (timeout.TotalMilliseconds < 1)
            {
                LogRequestTimeout(request, timeout);
                return(new Response(ResponseCode.RequestTimeout));
            }

            var state = new WebRequestState(timeout);

            using (var timeoutCancellation = new CancellationTokenSource())
            {
                var timeoutTask   = Task.Delay(state.TimeRemaining, timeoutCancellation.Token);
                var senderTask    = SendInternalAsync(request, state, connectionTimeout, cancellationToken);
                var completedTask = await Task.WhenAny(timeoutTask, senderTask).ConfigureAwait(false);

                if (completedTask is Task <Response> taskWithResponse)
                {
                    timeoutCancellation.Cancel();
                    return(taskWithResponse.GetAwaiter().GetResult());
                }

                // If the completed task can not be cast to Task<Response>, it means that timeout task has completed.
                state.CancelRequest();
                LogRequestTimeout(request, timeout);

                // Wait a little for canceled sending task completion before returning result:
                var senderTaskContinuation = senderTask.ContinueWith(
                    t =>
                {
                    if (t.IsCompleted)
                    {
                        t.GetAwaiter().GetResult().Dispose();
                    }
                });

                var abortWaitingDelay = Task.Delay(Settings.RequestAbortTimeout);

                await Task.WhenAny(senderTaskContinuation, abortWaitingDelay).ConfigureAwait(false);

                if (!senderTask.IsCompleted)
                {
                    LogFailedToWaitForRequestAbort();
                }

                return(responseFactory.BuildResponse(ResponseCode.RequestTimeout, state));
            }
        }
Example #2
0
        public Task HandleRequestAsync(HttpListenerContext context)
        {
            var allowValues = new List <string>();
            var request     = context.Request;

            foreach (var requestProcessor in _requestProcessors)
            {
                if (request.Url.LocalPath.Trim('/') == requestProcessor.SubUri)
                {
                    allowValues.Add(requestProcessor.Method.Method);
                    if (requestProcessor.Method == HttpMethod.Get)
                    {
                        allowValues.Add("HEAD");
                    }
                }
            }


            if (allowValues.Any())
            {
                ResponseFactory.BuildResponse(context, HttpStatusCode.OK, null);
                context.Response.AddHeader("Allow", string.Join(", ", allowValues));
            }
            else
            {
                ResponseFactory.BuildResponse(context, HttpStatusCode.NotFound, null);
            }

            return(Task.FromResult(0));
        }
        private Task HandleFileHeadRequestAsync(HttpListenerContext context, string filePath)
        {
            if (FilesPreprocessingEnabled && FilePreprocessController.FileInProgress(filePath))
            {
                LogDebug($"File {filePath} was requested but is in progress");
                ResponseFactory.BuildResponse(context, HttpStatusCode.ServiceUnavailable, null);
                return(Task.FromResult(0));
            }

            if (!File.Exists(filePath))
            {
                LogDebug($"File {filePath} was requested but was not found");
                ResponseFactory.BuildResponse(context, HttpStatusCode.NotFound, null);
                return(Task.FromResult(0));
            }

            var response = context.Response;
            var fileInfo = new FileInfo(filePath);

            response.ContentLength64 = fileInfo.Length;
            response.StatusCode      = (int)HttpStatusCode.OK;
            response.ContentType     = MimeTypes.GetTypeByExtenstion(Path.GetExtension(filePath).Substring(1));

            return(Task.FromResult(0));
        }
Example #4
0
        public Task HandleRequestAsync(HttpListenerContext context)
        {
            var responseBody = new PingResponse(CommonHelper.SerializeHttpRequest(context, true));

            ResponseFactory.BuildResponse(context, HttpStatusCode.OK, responseBody);
            return(Task.FromResult(0));
        }
        public async Task HandleFaviconAsync(HttpListenerContext context)
        {
            var response = context.Response;

            LogTrace($"Favicon requested, path: {FaviconPath}");
            if (string.IsNullOrEmpty(FaviconPath) || !File.Exists(FaviconPath))
            {
                ResponseFactory.BuildResponse(context, HttpStatusCode.NotFound, null);
                return;
            }
            ResponseFactory.BuildResponse(context, HttpStatusCode.OK, null);
            response.ContentType = "image/x-icon";
            using (var fileStream = new FileStream(FaviconPath, FileMode.Open, FileAccess.Read,
                                                   FileShare.ReadWrite))
            {
                await fileStream.CopyToAsync(response.OutputStream).ConfigureAwait(false);
            }
        }
Example #6
0
        public async Task HandleRequestAsync(HttpListenerContext context)
        {
            AuthentificationResult authResult;
            var request = context.Request;

            if (_authentificator != null)
            {
                authResult = await _authentificator.Invoke(request);
            }
            else
            {
                authResult = new AuthentificationResult(null, HttpStatusCode.NotFound);
            }
            if (authResult == null)
            {
                throw new InvalidOperationException("Authentificator fault: null result");
            }
            ResponseFactory.BuildResponse(context, authResult);
        }
        private async Task HandleFileGetRequestAsync(HttpListenerContext context, string filePath)
        {
            if (FilesPreprocessingEnabled && FilePreprocessController.FileInProgress(filePath))
            {
                LogDebug($"File {filePath} was requested but is in progress");
                ResponseFactory.BuildResponse(context, HttpStatusCode.ServiceUnavailable, null);
                return;
            }

            var fileRequest = FileRequestFactory.BuildRequest(filePath, context.Request);

            if (fileRequest == null)
            {
                LogDebug($"Failed to build file request for {filePath}");
                ResponseFactory.BuildResponse(context, HttpStatusCode.BadRequest, null);
                return;
            }
            await fileRequest.BuildResponse(context);
        }
        public void Given_a_Valid_Road_Id_Is_Specified_Return_Road_Name()
        {
            //Arrange
            responseFactory = new ResponseFactory();
            var _mock = new Mock <IResponseFactory>();

            _JObjectFactory = new Mock <IJObjectFactory>();

            //Act
            _mock.Setup(x => x.BuildResponse(It.IsAny <JObject>())).Returns(responseFactory.BuildResponse(MockResponse.ValidResponse("a4")));
            _JObjectFactory.Setup(o => o.ReturnAsJObect(MockResponse.ValidHttpResponseMock("A4"))).Equals(typeof(JObject));

            //Assert
            _JObjectFactory.Verify();

            _mock.Should().NotBeNull();

            //JB. Check that the Road name is returned.
            _mock.Object.BuildResponse(MockResponse.ValidResponse("a4")).Should().Contain("A4");
        }
Example #9
0
        public static void TestResponseXml()
        {
            XmlDocument testDoc = new XmlDocument();

            // testDoc.AppendChild(testDoc.CreateElement("methodResponse"));
            // testDoc.LoadXml("<methodResponse><fault><value><struct><member><name>faultCode</name><value><int>1</int></value></member><member><name>faultString</name><value><string>Error</string></value></member></struct></value></fault></methodResponse>");
            testDoc.LoadXml("<methodResponse><params><param><value><array><data><value><int>7</int></value><value><int>11</int></value><value><int>8</int></value><value><int>44</int></value><value><int>10</int></value><value><int>12</int></value></data></array></value></param></params></methodResponse>");

            testDoc.Save(Console.Out);
            XmlRpcResponse response = ResponseFactory.BuildResponse(testDoc);

            if (response.IsFault())
            {
                Console.WriteLine(response.GetFaultString());
            }
            else
            {
                Console.WriteLine();
                Console.WriteLine();
                Console.WriteLine(response.GetString());
            }
        }
        private void HandleFileDeleteRequest(HttpListenerContext context, string filePath)
        {
            if (!File.Exists(filePath))
            {
                LogDebug($"File {filePath} does not exist and cannot be deleted");
                ResponseFactory.BuildResponse(context, HttpStatusCode.NotFound, null);
                return;
            }

            var compressed = IoHelper.LoadAllChanged(filePath);

            try
            {
                File.Delete(filePath);
                compressed.ForEach(File.Delete);
                ResponseFactory.BuildResponse(context, HttpStatusCode.OK, null);
            }
            catch (Exception ex)
            {
                LogException(LogLevel.Warning, ex);
                ResponseFactory.BuildResponse(context, HttpStatusCode.InternalServerError, null);
            }
        }
        private async Task HandleFilePostRequestAsync(HttpListenerContext context, FileSection section, string filePath)
        {
            if (File.Exists(filePath))
            {
                LogDebug($"File {filePath} already exists");
                ResponseFactory.BuildResponse(context, HttpStatusCode.Conflict, null);
                return;
            }
            var fileContent   = context.Request.InputStream;
            var contentLength = context.Request.ContentLength64;

            if (section.MaxFileSize > 0 && contentLength > section.MaxFileSize)
            {
                LogDebug($"Trying to create file of size {contentLength} in section {section.Name} with max size of {section.MaxFileSize}");
                ResponseFactory.BuildResponse(context, HttpStatusCode.RequestEntityTooLarge, null);
                return;
            }
            using (var file = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                await fileContent.CopyToAsync(file).ConfigureAwait(false);

                await file.FlushAsync();
            }
            GC.Collect(1);
            LogTrace($"Total memory: {GC.GetTotalMemory(true)}");
            LogDebug($"File {filePath} created");
            if (FilesPreprocessingEnabled)
            {
                var code = FilePreprocessController.EnqueueFile(filePath) ? HttpStatusCode.Accepted : HttpStatusCode.Created;
                ResponseFactory.BuildResponse(context, code, null);
            }
            else
            {
                ResponseFactory.BuildResponse(context, HttpStatusCode.Created, null);
            }
        }
Example #12
0
        public async Task HandleRequestAsync(HttpListenerContext context)
        {
            var response = context.Response;

            if (_statisticsAuthorizer != null)
            {
                if (await _statisticsAuthorizer.Invoke(context.Request))
                {
                    var responseBody = Statistics?.Serialize();
                    ResponseFactory.BuildResponse(context, HttpStatusCode.OK, responseBody, null, true);
                    response.ContentType = "text/plain";
                }
                else
                {
                    ResponseFactory.BuildResponse(context, HttpStatusCode.Forbidden, null);
                }
            }
            else
            {
                var responseBody = Statistics?.Serialize();
                ResponseFactory.BuildResponse(context, HttpStatusCode.OK, responseBody, null, true);
                response.ContentType = "text/plain";
            }
        }
Example #13
0
        protected async Task BuildRangeResponse(HttpListenerContext context, string fileName)
        {
            var response = context.Response;

            if (!File.Exists(fileName))
            {
                LogDebug($"File {fileName} was requested but not found");
                ResponseFactory.BuildResponse(context, HttpStatusCode.NotFound, null);
                return;
            }
            if (Range == null)
            {
                response.StatusCode  = (int)HttpStatusCode.OK;
                response.ContentType = DetermineContentType(fileName);
                var fileLength = new FileInfo(fileName).Length;
                response.ContentLength64 = fileLength;
                ResponseFactory.SerializeResponse(response, null);
                using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read,
                                                       FileShare.ReadWrite))
                {
                    try
                    {
                        var bufferSize = fileLength >= LargeFileSizeThreshold
                            ? LargeFileBufferSize
                            : SmallFileBufferSize;
                        await fileStream.CopyToAsync(response.OutputStream, bufferSize);
                    }
                    catch (HttpListenerException ex)
                    {
                        LogMessage(LogLevel.Debug, $"Error: {ex.Message}");
                    }
                }
                return;
            }
            var  fileInfo      = new FileInfo(fileName);
            long startPosition = 0;
            var  endPosition   = fileInfo.Length - 1;

            if (Range.RangeEnd != null)
            {
                var rangeEnd = Range.RangeEnd.Value;
                if (rangeEnd < 0)
                {
                    if (fileInfo.Length < -rangeEnd)
                    {
                        response.StatusCode = (int)HttpStatusCode.RequestedRangeNotSatisfiable;
                        response.AddHeader("Content-Range", $"bytes 0-{fileInfo.Length - 1}");
                        ResponseFactory.SerializeResponse(response, null);
                        return;
                    }
                    startPosition = fileInfo.Length + rangeEnd;
                    endPosition   = fileInfo.Length - 1;
                }
                if (rangeEnd > 0)
                {
                    if (fileInfo.Length < rangeEnd)
                    {
                        response.StatusCode = (int)HttpStatusCode.RequestedRangeNotSatisfiable;
                        response.AddHeader("Content-Range", $"bytes 0-{fileInfo.Length - 1}");
                        ResponseFactory.SerializeResponse(response, null);
                        return;
                    }
                    endPosition = rangeEnd;
                }
            }
            if (Range.RangeStart != null)
            {
                startPosition = Range.RangeStart.Value;
            }

            byte[] buffer;
            var    length = endPosition - startPosition + 1;

            using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                using (var reader = new BinaryReader(fileStream))
                {
                    reader.BaseStream.Seek(startPosition, SeekOrigin.Begin);
                    buffer = reader.ReadBytes((int)length);
                }
            }

            response.StatusCode = (int)HttpStatusCode.PartialContent;
            response.AddHeader("Content-Range", $"bytes {startPosition}-{endPosition}");
            response.ContentType     = DetermineContentType(fileName);
            response.ContentLength64 = buffer.Length;
            ResponseFactory.SerializeResponse(response, null);
            try
            {
                await response.OutputStream.WriteAsync(buffer, 0, buffer.Length);
            }
            catch (HttpListenerException ex)
            {
                LogMessage(LogLevel.Debug, $"Error: {ex.Message}");
            }
        }
 public Task HandleRequestAsync(HttpListenerContext context)
 {
     ResponseFactory.BuildResponse(context, HttpStatusCode.OK, _configuration);
     return(Task.FromResult(0));
 }
        public void Given_a_Valid_Road_Id_Is_Specified_Return_Road_Status()
        {
            //Arrange
            responseFactory  = new ResponseFactory();
            _ResponseFactory = new Mock <IResponseFactory>();

            //Act
            _ResponseFactory.Setup(x => x.BuildResponse(It.IsAny <JObject>())).Returns(responseFactory.BuildResponse(MockResponse.ValidResponse("a4")));
            _ResponseFactory.Verify();

            //Assert
            //Assert.That(_ResponseFactory.Object, Is.Not.Null);
            _ResponseFactory.Object.Should().NotBeNull();

            //JB. Check that the Road status is returned
            //Assert.That(_ResponseFactory.Object.BuildResponse(MockResponse.ValidResponse("a4")), Contains.Substring("Road status"));
            _ResponseFactory.Object.BuildResponse(MockResponse.ValidResponse("a4")).Should().Contain("Road status");
        }
        public void Given_a_Valid_Road_Id_Is_Specified_Return_Road_Status_Description()
        {
            //Arrange
            responseFactory  = new ResponseFactory();
            _ResponseFactory = new Mock <IResponseFactory>();
            _ResponseFactory.Setup(x => x.BuildResponse(It.IsAny <JObject>())).Returns(responseFactory.BuildResponse(MockResponse.ValidResponse("a4")));

            //Act
            _ResponseFactory.Verify();

            //Assert
            _ResponseFactory.Object.Should().NotBeNull();

            //JB. Check that the Road status Description is returned
            _ResponseFactory.Object.BuildResponse(MockResponse.ValidResponse("a2")).Should().Contain("Road status Description");
        }
        public async Task HandleFileRequestAsync(HttpListenerContext context)
        {
            if (!_started)
            {
                ResponseFactory.BuildResponse(context, HttpStatusCode.NotImplemented, null);
                return;
            }

            var request = context.Request;

            try
            {
                var filename = ExtractFileName(request.Url.LocalPath);
                var section  = ExtractFileSection(request.Url.LocalPath);
                if (filename == null || section == null || filename.Contains("_CHANGED_"))
                {
                    ResponseFactory.BuildResponse(context, HttpStatusCode.BadRequest, null);
                    return;
                }
                var filePath = FilesLocation + Path.DirectorySeparatorChar + section.Folder + Path.DirectorySeparatorChar + filename;

                AuthorizationResult <TAccount> authResult;
                if (FilesNeedAuthorization)
                {
                    authResult = await _filesAuthorizer.Invoke(request, section, filename).ConfigureAwait(false);
                }
                else
                {
                    authResult = new AuthorizationResult <TAccount>(null, AuthorizationStatus.NotRequired);
                }
                _statistics?.AddAuthResult(authResult);
                switch (authResult.Status)
                {
                case AuthorizationStatus.NotRequired:
                case AuthorizationStatus.Ok:
                    if (CommonHelper.HttpMethodToEnum(request.HttpMethod) == HttpMethod.Get)
                    {
                        await HandleFileGetRequestAsync(context, filePath).ConfigureAwait(false);

                        return;
                    }
                    if (CommonHelper.HttpMethodToEnum(request.HttpMethod) == HttpMethod.Head)
                    {
                        await HandleFileHeadRequestAsync(context, filePath).ConfigureAwait(false);

                        return;
                    }
                    if (CommonHelper.HttpMethodToEnum(request.HttpMethod) == HttpMethod.Post)
                    {
                        await HandleFilePostRequestAsync(context, section, filePath).ConfigureAwait(false);

                        return;
                    }
                    if (CommonHelper.HttpMethodToEnum(request.HttpMethod) == HttpMethod.Delete)
                    {
                        HandleFileDeleteRequest(context, filePath);
                        return;
                    }
                    ResponseFactory.BuildResponse(context, HttpStatusCode.MethodNotAllowed, null);
                    return;

                default:
                    ResponseFactory.BuildResponse(context, authResult);
                    return;
                }
            }
            catch (Exception exception)
            {
                LogException(LogLevel.Warning, exception);
                ResponseFactory.BuildResponse(context, HttpStatusCode.InternalServerError, null);
            }
        }