Exemplo n.º 1
0
 private static IEnumerable <Tuple <long, long> > CreateByteRanges(string rangeString, int size)
 {
     return(RangeHeader.Parse(new Dictionary <string, string[]>(StringComparer.OrdinalIgnoreCase)
     {
         { "Range", new[] { rangeString } }
     }, size));
 }
        public async Task GetWithUnsatisfiableRangeTest()
        {
            var ct       = CancellationToken.None;
            var root     = await FileSystem.Root;
            var testFile = await root.CreateDocumentAsync("test1.txt", ct);

            await FillAsync(testFile, int.MaxValue, ct);

            using (var client = Server.CreateClient())
            {
                var range   = new RangeHeader("bytes", new RangeHeaderItem(_testBlock.Value.Length - 1, _testBlock.Value.Length));
                var request = new HttpRequestMessage(HttpMethod.Get, "test1.txt")
                {
                    Headers =
                    {
                        Range = RangeHeaderValue.Parse(range.ToString()),
                    },
                };

                using (var response = await client.SendAsync(request, ct))
                {
                    Assert.Equal(HttpStatusCode.RequestedRangeNotSatisfiable, response.StatusCode);
                }
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Create an instance of RangeHeader using RangeHeaderValues
        /// </summary>
        /// <param name="values">A collection of RangeHeaderValues that represent upper and lower byte ranges</param>
        /// <returns></returns>
        public static RangeHeader Create(RangeHeaderValue value)
        {
            var toReturn = new RangeHeader();

            toReturn.RawRange = value;
            return(toReturn);
        }
    public void CheckHeaderRangePopulatedCorrectly()
    {
        var headers = new ServerResponseHeaders();

        headers.SetRange(RangeHeader.Create(new RangeHeaderValue(0, 50)));
        Assert.AreEqual("bytes 0-50/50", headers.Range);

        headers.SetRange(RangeHeader.Create(new RangeHeaderValue()));
        Assert.AreEqual("bytes 0-0/0", headers.Range);

        headers = new ServerResponseHeaders();
        Assert.AreEqual(null, headers.Range);
    }
Exemplo n.º 5
0
        public void RangeHeader_Reports_Syntactically_Invalid_Byte_Ranges()
        {
            Assert.IsFalse(RangeHeader.IsValid(CreateHeadersWithRange("")));
            Assert.IsFalse(RangeHeader.IsValid(CreateHeadersWithRange("foobar")));
            Assert.IsFalse(RangeHeader.IsValid(CreateHeadersWithRange("furlongs=123-456")));
            Assert.IsFalse(RangeHeader.IsValid(CreateHeadersWithRange("bytes=")));
            Assert.IsFalse(RangeHeader.IsValid(CreateHeadersWithRange("")));

            // A range of non-positive length is syntactically invalid and ignored:
            Assert.IsNull(CreateByteRanges("bytes=123,456", 500));
            Assert.IsNull(CreateByteRanges("bytes=456-123", 500));
            Assert.IsNull(CreateByteRanges("bytes=456-455", 500));
        }
Exemplo n.º 6
0
        public void OverlapDescendingTest()
        {
            var range      = RangeHeader.Parse("bytes=300-599,0-499");
            var rangeItems = range.Normalize(10000);

            Assert.Collection(
                rangeItems,
                rangeItem =>
            {
                Assert.Equal(0, rangeItem.From);
                Assert.Equal(599, rangeItem.To);
            });
        }
Exemplo n.º 7
0
        public void FromToTest()
        {
            var range      = RangeHeader.Parse("bytes=0-499");
            var rangeItems = range.Normalize(10000);

            Assert.Collection(
                rangeItems,
                rangeItem =>
            {
                Assert.Equal(0, rangeItem.From);
                Assert.Equal(499, rangeItem.To);
            });
        }
Exemplo n.º 8
0
        public void OverlapWithFromTest()
        {
            var range      = RangeHeader.Parse("bytes=4000-5999,5000-");
            var rangeItems = range.Normalize(10000);

            Assert.Collection(
                rangeItems,
                rangeItem =>
            {
                Assert.Equal(4000, rangeItem.From);
                Assert.Equal(9999, rangeItem.To);
            });
        }
        public async Task OnRequest(HttpContext context)
        {
            var request     = context.Request;
            var requestPath = request.Path;

            if (string.Equals(requestPath, "/favicon.ico", StringComparison.OrdinalIgnoreCase))
            {
                context.Response.StatusCode = 200;
                await context.Response.Body.WriteAsync(Resources.Favicon);

                return;
            }

            var decodedPath  = HttpUtility.UrlDecode(requestPath);
            var physicalPath = _webHostEnvironment.ContentRootFileProvider.GetFileInfo(decodedPath).PhysicalPath;

            if (Directory.Exists(physicalPath) && request.Method == "GET" || request.Method == "HEAD")
            {
                var url = $"{request.Scheme}://{request.Host}{requestPath}";
                var uri = new Uri(url);

                var isRootPath  = string.Equals(requestPath, "/") || true;
                var mainPayload = _tinfoilIndexBuilder.Build(physicalPath, uri, _appSettings.IndexType, isRootPath ? _appSettings.MessageOfTheDay : null);

                var json = JsonSerializer.Serialize(mainPayload, new JsonSerializerOptions {
                    WriteIndented = true
                });

                context.Response.StatusCode  = 200;
                context.Response.ContentType = "application/json";

                await context.Response.WriteAsync(json, Encoding.UTF8);
            }
            else if (_fileFilter.IsFileAllowed(physicalPath) && File.Exists(physicalPath) && request.Method == "GET" || request.Method == "HEAD")
            {
                var rangeHeader = new RangeHeader
                {
                    RawValue = request.Headers["range"]
                };

                var ranges = rangeHeader.Ranges;
                var range  = ranges.Count == 1 ? ranges[0] : null;

                await context.Response.WriteFile(physicalPath, range : range);
            }
            else
            {
                context.Response.StatusCode = 404;
                await context.Response.WriteAsync("<!DOCTYPE html><http><head><title>Oops!</title></head><body style='text-align:center'>404<br>Not found...</body></html>");
            }
        }
Exemplo n.º 10
0
        private Task Serve(IDictionary <string, object> env)
        {
            Request  request  = new Request(env);
            Response response = new Response(env);

            var fileInfo = new FileInfo(path);
            var size     = fileInfo.Length;

            if (!RangeHeader.IsValid(request.Headers))
            {
                response.StatusCode = OK;
                range = new Tuple <long, long>(0, size - 1);
            }
            else
            {
                var ranges = RangeHeader.Parse(request.Headers, size);

                if (ranges == null)
                {
                    // Unsatisfiable.  Return error and file size.
                    return(Fail(
                               RequestedRangeNotSatisfiable,
                               "Byte range unsatisfiable",
                               "Content-Range", "bytes */" + size)
                           .Invoke(env));
                }

                if (ranges.Count() > 1)
                {
                    // TODO: Support multiple byte ranges.
                    response.StatusCode = OK;
                    range = new Tuple <long, long>(0, size - 1);
                }
                else
                {
                    // Partial content
                    range = ranges.First();
                    response.StatusCode = PartialContent;
                    response.Headers.SetHeader("Content-Range", "bytes " + range.Item1 + "-" + range.Item2 + "/" + size);
                    size = range.Item2 - range.Item1 + 1;
                }
            }

            response.Headers
            .SetHeader("Last-Modified", fileInfo.LastWriteTimeUtc.ToHttpDateString())
            .SetHeader("Content-Type", Mime.MimeType(fileInfo.Extension, "text/plain"))
            .SetHeader("Content-Length", size.ToString(CultureInfo.InvariantCulture));

            return(new FileBody(path, range).Start(response.OutputStream));
        }
Exemplo n.º 11
0
            public void Must_parse_correctly(object[] parameters)
            {
                var headerValue = (string)parameters[0];
                var byteRanges  = new List <Tuple <ulong?, ulong?> >();

                for (int i = 1; i < parameters.Length; i += 2)
                {
                    byteRanges.Add(new Tuple <ulong?, ulong?>((ulong?)parameters[i], (ulong?)parameters[i + 1]));
                }

                IEnumerable <RangeHeader> headers = RangeHeader.ParseMany(headerValue);

                Assert.That(headers.Select(arg => new Tuple <ulong?, ulong?>(arg.FirstBytePos, arg.LastBytePos)), Is.EquivalentTo(byteRanges));
            }
Exemplo n.º 12
0
        public async Task GetWithTwoRangesTest()
        {
            var ct       = CancellationToken.None;
            var root     = await FileSystem.Root;
            var testFile = await root.CreateDocumentAsync("test1.txt", ct);

            await FillAsync(testFile, int.MaxValue, ct);

            using (var client = Server.CreateClient())
            {
                var range   = new RangeHeader("bytes", new RangeHeaderItem(0, 1), new RangeHeaderItem(3, 4));
                var request = new HttpRequestMessage(HttpMethod.Get, "test1.txt")
                {
                    Headers =
                    {
                        Range = RangeHeaderValue.Parse(range.ToString()),
                    },
                };

                using (var response = await client.SendAsync(request, ct))
                {
                    var content = response
                                  .EnsureSuccessStatusCode().Content;

                    Assert.Equal(HttpStatusCode.PartialContent, response.StatusCode);

                    var multipart = await ReadMultipartAsync(content, ct);

                    Assert.Equal(2, multipart.Count);
                    Assert.All(multipart, entity => Assert.True(entity.ContentType.IsMimeType("text", "plain")));
                    Assert.Collection(
                        multipart,
                        entity =>
                    {
                        var textPart = Assert.IsType <TextPart>(entity);
                        Assert.Equal($"bytes 0-1/{_testBlock.Value.Length}", textPart.Headers["Content-Range"]);
                        Assert.Equal("12", textPart.Text);
                    },
                        entity =>
                    {
                        var textPart = Assert.IsType <TextPart>(entity);
                        Assert.Equal($"bytes 3-4/{_testBlock.Value.Length}", textPart.Headers["Content-Range"]);
                        Assert.Equal("45", textPart.Text);
                    });
                }
            }
        }
Exemplo n.º 13
0
        public async Task <HttpResponseMessage> Stream(int id)
        {
            Media media = await _mediaService.Get(id);

            HttpResponseMessage response = new HttpResponseMessage();

            //Check if media exists
            if (media == null)
            {
                response.StatusCode = HttpStatusCode.NotFound;
                return(response);
            }

            FileInfo fileInfo = new FileInfo(media.FileLocation);

            if (!FileHelper.FileExists(fileInfo))
            {
                response.StatusCode = HttpStatusCode.NotFound;
                return(response);
            }

            string rangeHeaderString = Request.Headers["range"];

            response.Headers.AcceptRanges.Add("bytes");

            // The request will be treated as normal request if there is no Range header.
            if (rangeHeaderString == null)
            {
                CreateNoRangeResponse(response, fileInfo);
                return(response);
            }

            RangeHeader rangeHeader = StreamHelper.ParseRangeHeader(rangeHeaderString);

            //If the range is not satisfiable, return a RequestedRangeNotSatisfiable response
            if (rangeHeader.Unit != "bytes" || /*rangeHeader.Ranges.Count > 1 ||*/
                !FileHelper.TryReadRangeItem(rangeHeader.Value, fileInfo.Length, out long start, out long end))
            {
                CreateRangeNotSatisfiableResponse(response, fileInfo);
                return(response);
            }

            //The range header is fine, return partial content
            CreatePartialContentResponse(response, fileInfo, start, end);
            return(response);
        }
Exemplo n.º 14
0
        public async Task GetWithSingleRangeTest()
        {
            var ct       = CancellationToken.None;
            var root     = await FileSystem.Root;
            var testFile = await root.CreateDocumentAsync("test1.txt", ct);

            await FillAsync(testFile, int.MaxValue, ct);

            using (var client = Server.CreateClient())
            {
                var range   = new RangeHeader("bytes", new RangeHeaderItem(0, 1));
                var request = new HttpRequestMessage(HttpMethod.Get, "test1.txt")
                {
                    Headers =
                    {
                        Range = RangeHeaderValue.Parse(range.ToString()),
                    },
                };

                using (var response = await client.SendAsync(request, ct))
                {
                    var content = response
                                  .EnsureSuccessStatusCode().Content;

                    Assert.Equal(HttpStatusCode.PartialContent, response.StatusCode);
                    Assert.Equal(2, content.Headers.ContentLength);

                    var contentRange = content.Headers.ContentRange;
                    Assert.NotNull(contentRange);
                    Assert.Equal(0, contentRange.From);
                    Assert.Equal(1, contentRange.To);
                    Assert.Equal(_testBlock.Value.Length, contentRange.Length);

                    var data = await content
                               .ReadAsByteArrayAsync();

                    var s = Encoding.UTF8.GetString(data);
                    Assert.Equal("12", s);
                }
            }
        }
Exemplo n.º 15
0
 public void SetRange(RangeHeader header)
 {
     Range = header.Range;
 }
Exemplo n.º 16
0
        private Task Serve(IDictionary <string, object> env, string path)
        {
            Request  request  = new Request(env);
            Response response = new Response(env);

            var fileInfo = new FileInfo(path);
            var size     = fileInfo.Length;
            Tuple <long, long> range;

            if (!RangeHeader.IsValid(request.Headers))
            {
                response.StatusCode = OK;
                range = new Tuple <long, long>(0, size - 1);
            }
            else
            {
                var ranges = RangeHeader.Parse(request.Headers, size);

                if (ranges == null)
                {
                    // Unsatisfiable.  Return error and file size.
                    return(Fail(
                               RequestedRangeNotSatisfiable,
                               "Byte range unsatisfiable",
                               "Content-Range", "bytes */" + size)
                           .Invoke(env));
                }

                if (ranges.Count() > 1)
                {
                    // TODO: Support multiple byte ranges.
                    response.StatusCode = OK;
                    range = new Tuple <long, long>(0, size - 1);
                }
                else
                {
                    // Partial content
                    range = ranges.First();
                    response.StatusCode = PartialContent;
                    response.Headers.SetHeader("Content-Range", "bytes " + range.Item1 + "-" + range.Item2 + "/" + size);
                    size = range.Item2 - range.Item1 + 1;
                }
            }

            response.Headers
            .SetHeader("Last-Modified", fileInfo.LastWriteTimeUtc.ToHttpDateString())
            .SetHeader("Content-Type", Mime.MimeType(fileInfo.Extension, "text/plain"))
            .SetHeader("Content-Length", size.ToString(CultureInfo.InvariantCulture));

            if ("HEAD".Equals(request.Method, StringComparison.OrdinalIgnoreCase))
            {
                // Suppress the body.
                return(TaskHelpers.Completed());
            }

            FileBody body = new FileBody(path, range);

            //TODO: update for current send file spec
            //var req = new Request(env);
            //SendFileFunc sendFile = env.Get<SendFileFunc>("sendfile.Func");
            //if (sendFile != null)
            //{
            //    return body.Start(sendFile);
            //}

            return(body.Start(response.OutputStream));
        }
 public RangeHeaderTest()
 {
     _rangeHeader = new RangeHeader();
 }
Exemplo n.º 18
0
 public void Must_not_result_in_header(string headerValue)
 {
     Assert.That(RangeHeader.ParseMany(headerValue), Is.Empty);
 }