Example #1
0
        public void NoOverlappingRangesThrowException(
            string ranges,
            int innerStreamLength,
            string contentRange
            )
        {
            // Arrange
            string data = new String('a', innerStreamLength);

            byte[]           bytes     = Encoding.UTF8.GetBytes(data);
            MemoryStream     memStream = new MemoryStream(bytes);
            RangeHeaderValue range     = RangeHeaderValue.Parse(ranges);

            // Act
            try
            {
                new ByteRangeStreamContent(memStream, range, _expectedMediatype);
            }
            catch (InvalidByteRangeException invalidByteRangeException)
            {
                ContentRangeHeaderValue expectedContentRange = ContentRangeHeaderValue.Parse(
                    contentRange
                    );
                Assert.Equal(expectedContentRange, invalidByteRangeException.ContentRange);
            }
        }
Example #2
0
        public void SingleRangeGeneratesNonMultipartContent(
            string ranges,
            int innerStreamLength,
            string contentRange
            )
        {
            // Arrange
            string data = new String('a', innerStreamLength);

            byte[]           bytes     = Encoding.UTF8.GetBytes(data);
            MemoryStream     memStream = new MemoryStream(bytes);
            RangeHeaderValue range     = RangeHeaderValue.Parse(ranges);

            // Act
            ByteRangeStreamContent rangeContent = new ByteRangeStreamContent(
                memStream,
                range,
                _expectedMediatype
                );

            // Assert
            Assert.Equal(_expectedMediatype, rangeContent.Headers.ContentType);
            ContentRangeHeaderValue expectedContentRange = ContentRangeHeaderValue.Parse(
                contentRange
                );

            Assert.Equal(expectedContentRange, rangeContent.Headers.ContentRange);
        }
Example #3
0
        public async Task FileDownloadAsync(DownloadRequest request, HttpRequest httpRequest, HttpResponse httpResponse, CancellationToken cancellationToken = default(CancellationToken))
        {
            var fileModel = await Connection.File.GetAsync(request.FileIdentifier);

            var organization = await Connection.Organization.GetAsync(request.FileIdentifier as OrganizationIdentifier);

            var managerModel = ModelConvert(organization, fileModel, connection.UserTimeZone);

            long?from = 0;
            long?to   = null;

            httpResponse.Headers[HeaderNames.AcceptRanges] = "bytes";

            if (httpRequest.Headers["Range"].Any())
            {
                var range = RangeHeaderValue.Parse(httpRequest.Headers["Range"].ToString()).Ranges.FirstOrDefault();
                if (range.From.HasValue)
                {
                    from = range.From.Value;
                }
                if (range.To.HasValue)
                {
                    to = Math.Max(range.To.Value, 0);
                }

                if (to == null)
                {
                    to = fileModel.Length - 1;
                }
            }

            await ExecuteDownload(request, httpResponse, fileModel, from, to, cancellationToken);
        }
        public void TryParse_Invalid()
        {
            RangeHeaderValue res;

            Assert.IsFalse(RangeHeaderValue.TryParse("bytes=4,33", out res), "#1");
            Assert.IsNull(res, "#2");
        }
Example #5
0
        private void CheckInvalidParse(string input)
        {
            Assert.Throws <FormatException>(() => { RangeHeaderValue.Parse(input); });

            Assert.False(RangeHeaderValue.TryParse(input, out RangeHeaderValue result));
            Assert.Null(result);
        }
Example #6
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);
        }
Example #7
0
        public void Parse_Invalid()
        {
            try {
                RangeHeaderValue.Parse(null);
                Assert.Fail("#1");
            } catch (FormatException) {
            }

            try {
                RangeHeaderValue.Parse("  ");
                Assert.Fail("#2");
            } catch (FormatException) {
            }

            try {
                RangeHeaderValue.Parse("5-6");
                Assert.Fail("#3");
            } catch (FormatException) {
            }

            try {
                RangeHeaderValue.Parse("bytes=");
                Assert.Fail("#4");
            } catch (FormatException) {
            }
        }
        public void MultipleRangesGeneratesMultipartByteRangesContent(string ranges, int innerStreamLength, int expectedBodyparts, string[] contentRanges)
        {
            // Arrange
            string data = new String('a', innerStreamLength);

            byte[]           bytes     = Encoding.UTF8.GetBytes(data);
            MemoryStream     memStream = new MemoryStream(bytes);
            RangeHeaderValue range     = RangeHeaderValue.Parse(ranges);

            // Act
            ByteRangeStreamContent content = new ByteRangeStreamContent(memStream, range, _expectedMediatype);
            MemoryStream           result  = new MemoryStream();

            content.CopyToAsync(result).Wait();
            MultipartMemoryStreamProvider multipart = content.ReadAsMultipartAsync().Result;

            // Assert
            Assert.Equal(expectedBodyparts, multipart.Contents.Count);
            for (int count = 0; count < multipart.Contents.Count; count++)
            {
                MediaTypeHeaderValue contentType = multipart.Contents[count].Headers.ContentType;
                Assert.Equal(_expectedMediatype, contentType);

                ContentRangeHeaderValue expectedContentRange = ContentRangeHeaderValue.Parse(contentRanges[count]);
                ContentRangeHeaderValue contentRange         = multipart.Contents[count].Headers.ContentRange;
                Assert.Equal(expectedContentRange, contentRange);
            }
        }
        private void CheckInvalidTryParse(string input)
        {
            RangeHeaderValue result = null;

            Assert.False(RangeHeaderValue.TryParse(input, out result));
            Assert.Null(result);
        }
Example #10
0
        private void CheckValidTryParse(string input, RangeHeaderValue expectedResult)
        {
            RangeHeaderValue result = null;

            Assert.True(RangeHeaderValue.TryParse(input, out result));
            Assert.Equal(expectedResult, result);
        }
Example #11
0
        public async Task ReadFileAsync(
            BackendConfiguration context,
            string id,
            Stream stream,
            long from,
            long to,
            long totalLength,
            CancellationToken cancellationToken = default(CancellationToken)
            )
        {
            using (var request = Request(context, HttpMethod.Get, $"api/backend", new {
                id,
                totalLength
            }))
            {
                var rangeHeader = new RangeHeaderValue(from, to).ToString();
                request.Headers.Add("Range", rangeHeader);
                Logger.LogDebug($"Range Header: {rangeHeader}");

                using (var response = await Client.SendAsync(
                           request,
                           HttpCompletionOption.ResponseHeadersRead,
                           cancellationToken))
                {
                    Logger.LogDebug($"Response started: Content-Length: {response.Content.Headers.ContentLength}");
                    response.EnsureSuccessStatusCode();


                    using (var responseStream = await response.Content.ReadAsStreamAsync())
                        await responseStream.CopyToAsync(stream, BUFFER_SIZE, cancellationToken);

                    Logger.LogDebug($"Complete");
                }
            }
        }
Example #12
0
        private static void CheckInvalidGetRangeLength(string input, int startIndex)
        {
            object result = null;

            Assert.Equal(0, RangeHeaderValue.GetRangeLength(input, startIndex, out result));
            Assert.Null(result);
        }
        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);
                }
            }
        }
Example #14
0
        public void Parse()
        {
            var res = RangeHeaderValue.Parse("bytes=2-40");

            Assert.AreEqual("bytes", res.Unit, "#1");
            Assert.AreEqual(2, res.Ranges.First().From, "#2");
            Assert.AreEqual(40, res.Ranges.First().To, "#3");
            Assert.AreEqual("bytes=2-40", res.ToString(), "#4");

            res = RangeHeaderValue.Parse("d-dd = 2 - ");
            Assert.AreEqual("d-dd", res.Unit, "#10");
            Assert.AreEqual(2, res.Ranges.First().From, "#11");
            Assert.IsNull(res.Ranges.First().To, "#12");
            Assert.AreEqual("d-dd=2-", res.ToString(), "#13");

            res = RangeHeaderValue.Parse("zz = - 6 , 5 - 9, -8");
            Assert.AreEqual("zz", res.Unit, "#20");
            Assert.IsNull(res.Ranges.First().From, "#21");
            Assert.AreEqual(6, res.Ranges.First().To, "#22");
            Assert.AreEqual(5, res.Ranges.Skip(1).First().From, "#21b");
            Assert.AreEqual(9, res.Ranges.Skip(1).First().To, "#22b");
            Assert.AreEqual("zz=-6, 5-9, -8", res.ToString(), "#23");

            res = RangeHeaderValue.Parse("ddd = 2 -, 1-4");
            Assert.AreEqual("ddd", res.Unit, "#30");
            Assert.AreEqual(2, res.Ranges.First().From, "#31");
            Assert.IsNull(res.Ranges.First().To, "#32");
            Assert.AreEqual("ddd=2-, 1-4", res.ToString(), "#33");
        }
Example #15
0
    public void Equals_UseSameAndDifferentRanges_EqualOrNotEqualNoExceptions()
    {
        var range1 = new RangeHeaderValue(1, 2);
        var range2 = new RangeHeaderValue(1, 2);

        range2.Unit = "BYTES";
        var range3 = new RangeHeaderValue(1, null);
        var range4 = new RangeHeaderValue(null, 2);
        var range5 = new RangeHeaderValue();

        range5.Ranges.Add(new RangeItemHeaderValue(1, 2));
        range5.Ranges.Add(new RangeItemHeaderValue(3, 4));
        var range6 = new RangeHeaderValue();

        range6.Ranges.Add(new RangeItemHeaderValue(3, 4)); // reverse order of range5
        range6.Ranges.Add(new RangeItemHeaderValue(1, 2));
        var range7 = new RangeHeaderValue(1, 2);

        range7.Unit = "other";

        Assert.False(range1.Equals(null), "bytes=1-2 vs. <null>");
        Assert.True(range1 !.Equals(range2), "bytes=1-2 vs. BYTES=1-2");
        Assert.False(range1.Equals(range3), "bytes=1-2 vs. bytes=1-");
        Assert.False(range1.Equals(range4), "bytes=1-2 vs. bytes=-2");
        Assert.False(range1.Equals(range5), "bytes=1-2 vs. bytes=1-2,3-4");
        Assert.True(range5.Equals(range6), "bytes=1-2,3-4 vs. bytes=3-4,1-2");
        Assert.False(range1.Equals(range7), "bytes=1-2 vs. other=1-2");
    }
 /// <summary>
 /// <see cref="HttpContent"/> implementation which provides a byte range view over a stream used to generate HTTP
 /// 206 (Partial Content) byte range responses. If none of the requested ranges overlap with the current extend
 /// of the selected resource represented by the <paramref name="content"/> parameter then an
 /// <see cref="InvalidByteRangeException"/> is thrown indicating the valid Content-Range of the content.
 /// </summary>
 /// <param name="content">The stream over which to generate a byte range view.</param>
 /// <param name="range">The range or ranges, typically obtained from the Range HTTP request header field.</param>
 /// <param name="mediaType">The media type of the content stream.</param>
 public ByteRangeStreamContent(
     Stream content,
     RangeHeaderValue range,
     MediaTypeHeaderValue mediaType
     ) : this(content, range, mediaType, DefaultBufferSize)
 {
 }
 /// <summary>
 /// Sets range header.
 /// </summary>
 /// <param name="headers">The http request header.</param>
 /// <param name="value">The header value.</param>
 public static void SetRange(this HttpRequestHeaders headers, RangeHeaderValue value)
 {
     if (value != null)
     {
         headers.Range = value;
     }
 }
Example #18
0
        public async Task Get(string id, long totalLength, CancellationToken cancellationToken = default(CancellationToken))
        {
            Response.Headers.Add("Accept-Ranges", "bytes");

            var range = RangeHeaderValue.Parse(Request.Headers["Range"]).Ranges.FirstOrDefault();

            if (range == null ||
                range.From == null ||
                range.To == null)
            {
                throw new Exception("Missing Range Header");
            }

            long from = range.From.Value;
            long to   = range.To.Value;

            long contentLength = to - from + 1;

            Response.ContentLength = contentLength;

            Logger.LogInformation($"Get: id: {id} from: {from} to: {to} Content-Length {Response.ContentLength}");
            Response.StatusCode = 206;

            await backend.ReadFileAsync(context, id, Response.Body, from, to, totalLength, cancellationToken).ConfigureAwait(false);

            Logger.LogInformation($"Get: id: {id} complete");
        }
 /// <summary>
 /// <see cref="HttpContent"/> implementation which provides a byte range view over a stream used to generate HTTP
 /// 206 (Partial Content) byte range responses. If none of the requested ranges overlap with the current extend
 /// of the selected resource represented by the <paramref name="content"/> parameter then an
 /// <see cref="InvalidByteRangeException"/> is thrown indicating the valid Content-Range of the content.
 /// </summary>
 /// <param name="content">The stream over which to generate a byte range view.</param>
 /// <param name="range">The range or ranges, typically obtained from the Range HTTP request header field.</param>
 /// <param name="mediaType">The media type of the content stream.</param>
 /// <param name="bufferSize">The buffer size used when copying the content stream.</param>
 public ByteRangeStreamContent(
     Stream content,
     RangeHeaderValue range,
     string mediaType,
     int bufferSize
     ) : this(content, range, new MediaTypeHeaderValue(mediaType), bufferSize)
 {
 }
Example #20
0
 public override Task <DownloadResult> DownloadAsync(Upload upload, RangeHeaderValue range, CancellationToken cancellationToken)
 {
     return(Task.FromResult(
                new DownloadResult
     {
         Stream = File.OpenRead(Path.Combine(_storagePath, upload.Id + upload.Extension))
     }));
 }
Example #21
0
        public void Parse()
        {
            var res = RangeHeaderValue.Parse("bytes=2-40");

            Assert.AreEqual("bytes", res.Unit, "#1");
            Assert.AreEqual(2, res.Ranges.First().From, "#2");
            Assert.AreEqual(40, res.Ranges.First().To, "#3");
        }
Example #22
0
        private static void CallGetRangeLength(string input, int startIndex, int expectedLength,
                                               out RangeHeaderValue result)
        {
            object temp = null;

            Assert.Equal(expectedLength, RangeHeaderValue.GetRangeLength(input, startIndex, out temp));
            result = temp as RangeHeaderValue;
        }
        public void TryParse()
        {
            RangeHeaderValue res;

            Assert.IsTrue(RangeHeaderValue.TryParse("bytes=4-33", out res), "#1");
            Assert.AreEqual("bytes", res.Unit, "#2");
            Assert.AreEqual(4, res.Ranges.First().From, "#3");
            Assert.AreEqual(33, res.Ranges.First().To, "#4");
        }
        /// <summary>
        /// Reads the JSON representation of the object.
        /// </summary>
        /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
        /// <param name="objectType">Type of the object.</param>
        /// <param name="existingValue">The existing property value of the JSON that is being converted.</param>
        /// <param name="serializer">The calling serializer.</param>
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.String)
            {
                return(RangeHeaderValue.Parse((string)reader.Value));
            }

            throw new JsonSerializationException();
        }
        private static bool TryHandleSpecialHeader(HttpWebRequest webRequest, Header header)
        {
            if (header.Name.Equals(HeaderNames.Accept))
            {
                webRequest.Accept = header.Value;
                return(true);
            }

            if (header.Name.Equals(HeaderNames.ContentLength))
            {
                return(true);
            }

            if (header.Name.Equals(HeaderNames.ContentType))
            {
                webRequest.ContentType = header.Value;
                return(true);
            }

            if (header.Name.Equals(HeaderNames.Host))
            {
                webRequest.Host = header.Value;
                return(true);
            }

            if (header.Name.Equals(HeaderNames.IfModifiedSince))
            {
                webRequest.IfModifiedSince = DateTime.Parse(header.Value);
                return(true);
            }

            if (header.Name.Equals(HeaderNames.Range))
            {
                var ranges = RangeHeaderValue.Parse(header.Value);

                foreach (var range in ranges.Ranges)
                {
                    webRequest.AddRange(ranges.Unit, range.From ?? 0, range.To ?? 0);
                }

                return(true);
            }

            if (header.Name.Equals(HeaderNames.Referer))
            {
                webRequest.Referer = header.Value;
                return(true);
            }

            if (header.Name.Equals(HeaderNames.UserAgent))
            {
                webRequest.UserAgent = header.Value;
                return(true);
            }

            return(false);
        }
Example #26
0
        public async Task Should_return_requested_range_not_satisfiable(string range)
        {
            //Given & When
            this.httpClient.DefaultRequestHeaders.Range = RangeHeaderValue.Parse($"bytes={range}");
            var response = await this.httpClient.GetAsync("/downloadrange");

            //Then
            Assert.Equal(HttpStatusCode.RequestedRangeNotSatisfiable, response.StatusCode);
        }
        public static bool IsRangeHeaderCorrect(this HttpRequestHeaders headerCollection, long fileLen)
        {
            RangeHeaderValue     rangeHeader             = headerCollection.Range;
            bool                 unitIsNotbytes          = rangeHeader.Unit != "bytes";
            bool                 multipleRanges          = rangeHeader.Ranges.Count > 1;
            RangeItemHeaderValue range                   = rangeHeader.Ranges.First();
            bool                 start_end_fileLen_error = !(range.RangeHeaderStart(fileLen) < fileLen && range.RangeHeaderEnd(fileLen) < fileLen);

            return(!(unitIsNotbytes || multipleRanges || start_end_fileLen_error));
        }
        public void Properties_Invalid()
        {
            var value = new RangeHeaderValue();

            try {
                value.Unit = "";
                Assert.Fail("#1");
            } catch (ArgumentException) {
            }
        }
Example #29
0
        /// <summary>
        /// Write video stream to response body
        /// </summary>
        /// <param name="request"></param>
        /// <param name="response"></param>
        /// <returns></returns>
        protected async Task WriteVideoStreamToBody(HttpRequest request, HttpResponse response)
        {
            var bufferingFeature = response.HttpContext.Features.Get <IHttpBufferingFeature>();

            bufferingFeature?.DisableResponseBuffering();

            RangeHeaderValue rangeHeader = request.GetTypedHeaders().Range;

            if (IsRangeRequest(rangeHeader))
            {
                long totalLength = this.FileStream.Length;
                var  range       = rangeHeader.Ranges.First();
                var  start       = range.From ?? 0;
                var  end         = range.To ?? totalLength - 1;

                response.Headers.Add("Accept-Ranges", "bytes");
                // response.GetTypedHeaders().ContentRange = new ContentRangeHeaderValue(start, end, totalLength);
                response.Headers.Add("Content-Range", $"bytes {start}-{end}/{totalLength}");
                response.ContentLength = end - start + 1;
                response.StatusCode    = StatusCodes.Status206PartialContent;


                // Read video by range header
                try
                {
                    var buffer = new byte[BUFFER_SIZE];

                    var position  = start;
                    var bytesLeft = end - start + 1;
                    this.FileStream.Seek(position, SeekOrigin.Begin);
                    while (position <= end)
                    {
                        var bytesRead = this.FileStream.Read(buffer, 0, (int)Math.Min(bytesLeft, buffer.Length));
                        await response.Body.WriteAsync(buffer, 0, bytesRead);

                        position += bytesRead;
                        bytesLeft = end - position + 1;
                    }
                }
                catch (IndexOutOfRangeException ex)
                {
                    await response.Body.FlushAsync();

                    return;
                }
                finally
                {
                    await response.Body.FlushAsync();
                }
            }
            else
            {
                await this.FileStream.CopyToAsync(response.Body);
            }
        }
Example #30
0
    public void TryParse_SetOfValidValueStrings_ParsedCorrectly()
    {
        CheckValidTryParse(" bytes=1-2 ", new RangeHeaderValue(1, 2));

        var expected = new RangeHeaderValue();

        expected.Unit = "custom";
        expected.Ranges.Add(new RangeItemHeaderValue(null, 5));
        expected.Ranges.Add(new RangeItemHeaderValue(1, 4));
        CheckValidTryParse("custom = -  5 , 1 - 4 ,,", expected);
    }
Example #31
0
        /// <summary>
        /// Byte Range Response
        /// </summary>
        /// <param name="content">source content stream</param>
        /// <param name="range">range header</param>
        /// <param name="mediaType">MIME</param>
        /// <exception cref="NotSupportedException"></exception>
        public ByteRangeResponse(Stream content, RangeHeaderValue range, string mediaType)
            
        {
            if (!range.Unit.Equals("BYTES",StringComparison.InvariantCultureIgnoreCase))
            {
                throw new NotSupportedException();
            }
            if (!range.Any())
            {
                throw new ArgumentException("range");
            }

            if (string.IsNullOrEmpty(mediaType))
            {
                mediaType = MimeTypes.GetMimeType("application/octet-stream");
            }

            var contentLength = content.Length - content.Position;
            var itemCount = range.RangeItemHeaderValues.Count();

            if (itemCount == 1)
            {
                var rangeItem = range.First();
                base.Contents = x =>
                {
                    var temStream = new ByteRangeStream(content, rangeItem);
                    temStream.CopyTo(x);
                };
                base.ContentType = mediaType;
                base.Headers.Add("Content-Range", $"{range.Unit} {rangeItem.From}-{rangeItem.To}/{contentLength}");
                base.StatusCode = HttpStatusCode.PartialContent;
            }
            else
            {
                throw new NotSupportedException();
            }
        }