Exemple #1
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);
        }
Exemple #2
0
        public void RangesOverZeroLengthStream(string ranges)
        {
            // Arrange
            RangeHeaderValue range = RangeHeaderValue.Parse(ranges);

            // Act
            try
            {
                new ByteRangeStreamContent(Stream.Null, range, _expectedMediatype);
            }
            catch (InvalidByteRangeException invalidByteRangeException)
            {
                ContentRangeHeaderValue expectedContentRange = new ContentRangeHeaderValue(
                    length: 0
                    );
                Assert.Equal(expectedContentRange, invalidByteRangeException.ContentRange);
            }
        }
        public void GetHashCode_UseSameAndDifferentRanges_SameOrDifferentHashCodes()
        {
            ContentRangeHeaderValue range1 = new ContentRangeHeaderValue(1, 2, 5);
            ContentRangeHeaderValue range2 = new ContentRangeHeaderValue(1, 2);
            ContentRangeHeaderValue range3 = new ContentRangeHeaderValue(5);
            ContentRangeHeaderValue range4 = new ContentRangeHeaderValue(1, 2, 5);

            range4.Unit = "BYTES";
            ContentRangeHeaderValue range5 = new ContentRangeHeaderValue(1, 2, 5);

            range5.Unit = "myunit";

            Assert.NotEqual(range1.GetHashCode(), range2.GetHashCode()); // "bytes 1-2/5 vs. bytes 1-2/*"
            Assert.NotEqual(range1.GetHashCode(), range3.GetHashCode()); // "bytes 1-2/5 vs. bytes */5"
            Assert.NotEqual(range2.GetHashCode(), range3.GetHashCode()); // "bytes 1-2/* vs. bytes */5"
            Assert.Equal(range1.GetHashCode(), range4.GetHashCode());    // "bytes 1-2/5 vs. BYTES 1-2/5"
            Assert.NotEqual(range1.GetHashCode(), range5.GetHashCode()); // "bytes 1-2/5 vs. myunit 1-2/5"
        }
Exemple #4
0
        public async Task TestResponseContentHeaders()
        {
            var mock = new MockHttpClient();

            var currentDate       = DateTime.UtcNow;
            var expectedExpires   = new DateTimeOffset(currentDate.AddSeconds(60));
            var expectedByteArray = new byte[] { 65 };

            var expected = new ByteArrayContent(expectedByteArray);

            expected.Headers.Allow.Add("GET");
            expected.Headers.Allow.Add("POST");
            expected.Headers.ContentDisposition = ContentDispositionHeaderValue.Parse("attachment");
            expected.Headers.ContentLength      = expectedByteArray.Length;
            expected.Headers.ContentLocation    = new Uri("https://example.com");
            expected.Headers.ContentRange       = ContentRangeHeaderValue.Parse("bytes 200-1000/67589");
            expected.Headers.ContentType        = MediaTypeHeaderValue.Parse("text/plain");
            expected.Headers.ContentMD5         = new byte[] { 1 };
            expected.Headers.ContentLanguage.Add("en-US");
            expected.Headers.ContentEncoding.Add("gzip");
            expected.Headers.Expires      = expectedExpires;
            expected.Headers.LastModified = currentDate;

            mock.SetupGet("/").ReturnsAsync(content: expected);

            var result = await mock.Object.GetAsync("/");

            var resultByteArray = await result.Content.ReadAsByteArrayAsync();

            Assert.Equal(expectedByteArray, resultByteArray);
            Assert.Equal("GET, POST", result.Content.Headers.Allow.ToString());
            Assert.Equal("attachment", result.Content.Headers.ContentDisposition.ToString());
            Assert.Equal(expectedByteArray.Length, result.Content.Headers.ContentLength);
            Assert.Equal("https://example.com/", result.Content.Headers.ContentLocation.AbsoluteUri);
            Assert.Equal("bytes 200-1000/67589", result.Content.Headers.ContentRange.ToString());
            Assert.Equal("text/plain", result.Content.Headers.ContentType.ToString());
            Assert.Equal(new byte[] { 1 }, result.Content.Headers.ContentMD5);
            Assert.Equal("en-US", result.Content.Headers.ContentLanguage.ToString());
            Assert.Equal("gzip", result.Content.Headers.ContentEncoding.ToString());
            Assert.NotNull(result.Content.Headers.Expires);
            Assert.NotNull(result.Content.Headers.LastModified);
            Assert.Equal(expectedExpires.ToString("s"), result.Content.Headers.Expires.Value.ToString("s"));
            Assert.Equal(currentDate.ToString("s"), result.Content.Headers.LastModified.Value.ToString("s"));
        }
        public async Task WriteFileAsync_IfRangeHeaderValid_WritesRequestedRange()
        {
            // Arrange
            var contentType  = "text/plain";
            var lastModified = DateTimeOffset.MinValue;
            var entityTag    = new EntityTagHeaderValue("\"Etag\"");
            var byteArray    = Encoding.ASCII.GetBytes("Hello World");
            var readStream   = new MemoryStream(byteArray);

            readStream.SetLength(11);

            var httpContext    = GetHttpContext();
            var requestHeaders = httpContext.Request.GetTypedHeaders();

            requestHeaders.IfMatch = new[]
            {
                new EntityTagHeaderValue("\"Etag\""),
            };
            requestHeaders.Range       = new RangeHeaderValue(0, 4);
            requestHeaders.IfRange     = new RangeConditionHeaderValue(new EntityTagHeaderValue("\"Etag\""));
            httpContext.Request.Method = HttpMethods.Get;
            httpContext.Response.Body  = new MemoryStream();

            // Act
            await ExecuteAsync(httpContext, readStream, contentType, lastModified, entityTag, enableRangeProcessing : true);

            // Assert
            var httpResponse = httpContext.Response;

            httpResponse.Body.Seek(0, SeekOrigin.Begin);
            var streamReader = new StreamReader(httpResponse.Body);
            var body         = streamReader.ReadToEndAsync().Result;

            Assert.Equal(lastModified.ToString("R"), httpResponse.Headers.LastModified);
            Assert.Equal(entityTag.ToString(), httpResponse.Headers.ETag);
            var contentRange = new ContentRangeHeaderValue(0, 4, byteArray.Length);

            Assert.Equal(StatusCodes.Status206PartialContent, httpResponse.StatusCode);
            Assert.Equal("bytes", httpResponse.Headers.AcceptRanges);
            Assert.Equal(contentRange.ToString(), httpResponse.Headers.ContentRange);
            Assert.Equal(5, httpResponse.ContentLength);
            Assert.Equal("Hello", body);
            Assert.False(readStream.CanSeek);
        }
        public async Task WriteFileAsync_RangeRequested_FileLengthZeroOrNull(long?fileLength)
        {
            // Arrange
            var contentType  = "text/plain";
            var lastModified = new DateTimeOffset();
            var entityTag    = new EntityTagHeaderValue("\"Etag\"");
            var byteArray    = Encoding.ASCII.GetBytes("");
            var readStream   = new MemoryStream(byteArray);

            fileLength = fileLength ?? 0L;
            readStream.SetLength(fileLength.Value);

            var httpContext    = GetHttpContext();
            var requestHeaders = httpContext.Request.GetTypedHeaders();

            requestHeaders.Range   = new RangeHeaderValue(0, 5);
            requestHeaders.IfMatch = new[]
            {
                new EntityTagHeaderValue("\"Etag\""),
            };
            httpContext.Request.Method = HttpMethods.Get;
            httpContext.Response.Body  = new MemoryStream();

            // Act
            await ExecuteAsync(httpContext, readStream, contentType, lastModified, entityTag, enableRangeProcessing : true);

            // Assert
            var httpResponse = httpContext.Response;

            httpResponse.Body.Seek(0, SeekOrigin.Begin);
            var streamReader = new StreamReader(httpResponse.Body);
            var body         = streamReader.ReadToEndAsync().Result;

            Assert.Equal(lastModified.ToString("R"), httpResponse.Headers.LastModified);
            Assert.Equal(entityTag.ToString(), httpResponse.Headers.ETag);
            var contentRange = new ContentRangeHeaderValue(byteArray.Length);

            Assert.Equal(StatusCodes.Status416RangeNotSatisfiable, httpResponse.StatusCode);
            Assert.Equal("bytes", httpResponse.Headers.AcceptRanges);
            Assert.Equal(contentRange.ToString(), httpResponse.Headers.ContentRange);
            Assert.Equal(0, httpResponse.ContentLength);
            Assert.Empty(body);
            Assert.False(readStream.CanSeek);
        }
        public async Task WriteFileAsync_PreconditionStateShouldProcess_WritesRangeRequested(long?start, long?end, string expectedString, long contentLength)
        {
            // Arrange
            var contentType  = "text/plain";
            var lastModified = new DateTimeOffset();
            var entityTag    = new EntityTagHeaderValue("\"Etag\"");
            var byteArray    = Encoding.ASCII.GetBytes("Hello World");
            var readStream   = new MemoryStream(byteArray);

            readStream.SetLength(11);

            var httpContext    = GetHttpContext();
            var requestHeaders = httpContext.Request.GetTypedHeaders();

            requestHeaders.Range   = new RangeHeaderValue(start, end);
            requestHeaders.IfMatch = new[]
            {
                new EntityTagHeaderValue("\"Etag\""),
            };
            httpContext.Request.Method = HttpMethods.Get;
            httpContext.Response.Body  = new MemoryStream();

            // Act
            await ExecuteAsync(httpContext, readStream, contentType, lastModified, entityTag, enableRangeProcessing : true);

            // Assert
            start = start ?? 11 - end;
            end   = start + contentLength - 1;
            var httpResponse = httpContext.Response;

            httpResponse.Body.Seek(0, SeekOrigin.Begin);
            var streamReader = new StreamReader(httpResponse.Body);
            var body         = streamReader.ReadToEndAsync().Result;
            var contentRange = new ContentRangeHeaderValue(start.Value, end.Value, byteArray.Length);

            Assert.Equal(lastModified.ToString("R"), httpResponse.Headers.LastModified);
            Assert.Equal(entityTag.ToString(), httpResponse.Headers.ETag);
            Assert.Equal(StatusCodes.Status206PartialContent, httpResponse.StatusCode);
            Assert.Equal("bytes", httpResponse.Headers.AcceptRanges);
            Assert.Equal(contentRange.ToString(), httpResponse.Headers.ContentRange);
            Assert.Equal(contentLength, httpResponse.ContentLength);
            Assert.Equal(expectedString, body);
            Assert.False(readStream.CanSeek);
        }
        public static async Task WriteFileAsync_WritesRangeRequested <TContext>(
            long?start,
            long?end,
            string expectedString,
            long contentLength,
            Func <PhysicalFileResult, TContext, Task> function)
        {
            // Arrange
            var path   = Path.GetFullPath(Path.Combine("TestFiles", "FilePathResultTestFile.txt"));
            var result = new TestPhysicalFileResult(path, "text/plain");

            result.EnableRangeProcessing = true;
            var sendFile    = new TestSendFileFeature();
            var httpContext = GetHttpContext();

            httpContext.Features.Set <IHttpResponseBodyFeature>(sendFile);
            var requestHeaders = httpContext.Request.GetTypedHeaders();

            requestHeaders.IfModifiedSince = DateTimeOffset.MinValue;
            requestHeaders.Range           = new RangeHeaderValue(start, end);
            httpContext.Request.Method     = HttpMethods.Get;
            var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

            // Act
            object context = typeof(TContext) == typeof(HttpContext) ? httpContext : actionContext;

            await function(result, (TContext)context);

            // Assert
            var startResult  = start ?? 34 - end;
            var endResult    = startResult + contentLength - 1;
            var httpResponse = actionContext.HttpContext.Response;
            var contentRange = new ContentRangeHeaderValue(startResult.Value, endResult.Value, 34);

            Assert.Equal(StatusCodes.Status206PartialContent, httpResponse.StatusCode);
            Assert.Equal("bytes", httpResponse.Headers.AcceptRanges);
            Assert.Equal(contentRange.ToString(), httpResponse.Headers.ContentRange);
            Assert.NotEmpty(httpResponse.Headers.LastModified);
            Assert.Equal(contentLength, httpResponse.ContentLength);
            Assert.Equal(Path.GetFullPath(Path.Combine("TestFiles", "FilePathResultTestFile.txt")), sendFile.Name);
            Assert.Equal(startResult, sendFile.Offset);
            Assert.Equal((long?)contentLength, sendFile.Length);
        }
        public void CreateErrorResponseRangeNotSatisfiable_SetsCorrectStatusCodeAndContentRangeHeader()
        {
            // Arrange
            var context = new DefaultHttpContext();

            context.RequestServices = CreateServices(new DefaultContentNegotiator());

            var request = CreateRequest(context);

            var expectedContentRange      = new ContentRangeHeaderValue(length: 128);
            var invalidByteRangeException = new InvalidByteRangeException(expectedContentRange);

            // Act
            var response = request.CreateErrorResponse(invalidByteRangeException);

            // Assert
            Assert.Equal(HttpStatusCode.RequestedRangeNotSatisfiable, response.StatusCode);
            Assert.Same(expectedContentRange, response.Content.Headers.ContentRange);
        }
        public async Task WriteFileAsync_PreconditionStateUnspecified_RangeRequestedNotSatisfiable(string rangeString)
        {
            // Arrange
            var contentType  = "text/plain";
            var lastModified = new DateTimeOffset();
            var entityTag    = new EntityTagHeaderValue("\"Etag\"");
            var byteArray    = Encoding.ASCII.GetBytes("Hello World");
            var readStream   = new MemoryStream(byteArray);

            var result = new FileStreamResult(readStream, contentType)
            {
                LastModified          = lastModified,
                EntityTag             = entityTag,
                EnableRangeProcessing = true,
            };

            var httpContext = GetHttpContext();

            httpContext.Request.Headers[HeaderNames.Range] = rangeString;
            httpContext.Request.Method = HttpMethods.Get;
            httpContext.Response.Body  = new MemoryStream();
            var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

            // Act
            await result.ExecuteResultAsync(actionContext);

            // Assert
            var httpResponse = actionContext.HttpContext.Response;

            httpResponse.Body.Seek(0, SeekOrigin.Begin);
            var streamReader = new StreamReader(httpResponse.Body);
            var body         = streamReader.ReadToEndAsync().Result;
            var contentRange = new ContentRangeHeaderValue(byteArray.Length);

            Assert.Equal(lastModified.ToString("R"), httpResponse.Headers[HeaderNames.LastModified]);
            Assert.Equal(entityTag.ToString(), httpResponse.Headers[HeaderNames.ETag]);
            Assert.Equal(StatusCodes.Status416RangeNotSatisfiable, httpResponse.StatusCode);
            Assert.Equal("bytes", httpResponse.Headers[HeaderNames.AcceptRanges]);
            Assert.Equal(contentRange.ToString(), httpResponse.Headers[HeaderNames.ContentRange]);
            Assert.Equal(11, httpResponse.ContentLength);
            Assert.Empty(body);
            Assert.False(readStream.CanSeek);
        }
Exemple #11
0
    public async Task WriteFileAsync_WritesRangeRequested(
        long?start,
        long?end,
        long contentLength)
    {
        // Arrange
        var path           = Path.GetFullPath("helllo.txt");
        var contentType    = "text/plain; charset=us-ascii; p1=p1-value";
        var appEnvironment = new Mock <IWebHostEnvironment>();

        appEnvironment.Setup(app => app.WebRootFileProvider)
        .Returns(GetFileProvider(path));

        var sendFileFeature = new TestSendFileFeature();
        var httpContext     = GetHttpContext(GetFileProvider(path));

        httpContext.Features.Set <IHttpResponseBodyFeature>(sendFileFeature);


        var requestHeaders = httpContext.Request.GetTypedHeaders();

        requestHeaders.Range             = new RangeHeaderValue(start, end);
        requestHeaders.IfUnmodifiedSince = DateTimeOffset.MinValue.AddDays(1);
        httpContext.Request.Method       = HttpMethods.Get;

        // Act
        await ExecuteAsync(httpContext, path, contentType, enableRangeProcessing : true);

        // Assert
        var startResult  = start ?? 33 - end;
        var endResult    = startResult + contentLength - 1;
        var httpResponse = httpContext.Response;
        var contentRange = new ContentRangeHeaderValue(startResult.Value, endResult.Value, 33);

        Assert.Equal(StatusCodes.Status206PartialContent, httpResponse.StatusCode);
        Assert.Equal("bytes", httpResponse.Headers.AcceptRanges);
        Assert.Equal(contentRange.ToString(), httpResponse.Headers.ContentRange);
        Assert.NotEmpty(httpResponse.Headers.LastModified);
        Assert.Equal(contentLength, httpResponse.ContentLength);
        Assert.Equal(path, sendFileFeature.Name);
        Assert.Equal(startResult, sendFileFeature.Offset);
        Assert.Equal((long?)contentLength, sendFileFeature.Length);
    }
        public void Properties()
        {
            var value = new ContentRangeHeaderValue(4);

            Assert.IsNull(value.From, "#1");
            Assert.IsTrue(value.HasLength, "#2");
            Assert.IsFalse(value.HasRange, "#3");
            Assert.AreEqual(4, value.Length, "#4");
            Assert.IsNull(value.To, "#5");
            Assert.AreEqual("bytes", value.Unit, "#6");

            value      = new ContentRangeHeaderValue(1, 10, 20);
            value.Unit = "mu";
            Assert.AreEqual(1, value.From, "#11");
            Assert.IsTrue(value.HasLength, "#12");
            Assert.IsTrue(value.HasRange, "#13");
            Assert.AreEqual(20, value.Length, "#14");
            Assert.AreEqual(10, value.To, "#15");
            Assert.AreEqual("mu", value.Unit, "#16");
        }
        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);
            }
        }
        public static async Task WriteFileAsync_IfRangeHeaderValid_WritesRequestedRange <TContext>(
            Func <PhysicalFileResult, TContext, Task> function)
        {
            // Arrange
            var path      = Path.GetFullPath(Path.Combine("TestFiles", "FilePathResultTestFile.txt"));
            var result    = new TestPhysicalFileResult(path, "text/plain");
            var entityTag = result.EntityTag = new EntityTagHeaderValue("\"Etag\"");

            result.EnableRangeProcessing = true;
            var sendFile    = new TestSendFileFeature();
            var httpContext = GetHttpContext();

            httpContext.Features.Set <IHttpResponseBodyFeature>(sendFile);
            var requestHeaders = httpContext.Request.GetTypedHeaders();

            requestHeaders.IfModifiedSince = DateTimeOffset.MinValue;
            requestHeaders.Range           = new RangeHeaderValue(0, 3);
            requestHeaders.IfRange         = new RangeConditionHeaderValue(new EntityTagHeaderValue("\"Etag\""));
            httpContext.Request.Method     = HttpMethods.Get;
            var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

            // Act
            object context = typeof(TContext) == typeof(HttpContext) ? httpContext : actionContext;

            await function(result, (TContext)context);

            // Assert
            var httpResponse = actionContext.HttpContext.Response;

            Assert.Equal(StatusCodes.Status206PartialContent, httpResponse.StatusCode);
            Assert.Equal("bytes", httpResponse.Headers.AcceptRanges);
            var contentRange = new ContentRangeHeaderValue(0, 3, 34);

            Assert.Equal(contentRange.ToString(), httpResponse.Headers.ContentRange);
            Assert.NotEmpty(httpResponse.Headers.LastModified);
            Assert.Equal(entityTag.ToString(), httpResponse.Headers.ETag);
            Assert.Equal(4, httpResponse.ContentLength);
            Assert.Equal(Path.GetFullPath(Path.Combine("TestFiles", "FilePathResultTestFile.txt")), sendFile.Name);
            Assert.Equal(0, sendFile.Offset);
            Assert.Equal(4, sendFile.Length);
        }
        public void Parse()
        {
            var res = ContentRangeHeaderValue.Parse("bytes  0 - 499/ 1234");

            Assert.AreEqual(0, res.From, "#1");
            Assert.AreEqual(499, res.To, "#2");
            Assert.AreEqual(1234, res.Length, "#3");
            Assert.AreEqual("bytes 0-499/1234", res.ToString(), "#4");

            res = ContentRangeHeaderValue.Parse("bytes  */ 8");
            Assert.IsNull(res.From, "#11");
            Assert.IsNull(res.To, "#12");
            Assert.AreEqual(8, res.Length, "#13");
            Assert.AreEqual("bytes */8", res.ToString(), "#14");

            res = ContentRangeHeaderValue.Parse("by  */*");
            Assert.IsNull(res.From, "#21");
            Assert.IsNull(res.To, "#22");
            Assert.IsNull(res.Length, "#23");
            Assert.AreEqual("by */*", res.ToString(), "#24");
        }
Exemple #16
0
    public async Task WriteFileAsync_IfRangeHeaderValid_WritesRequestedRange()
    {
        // Arrange
        var path           = Path.GetFullPath("helllo.txt");
        var contentType    = "text/plain; charset=us-ascii; p1=p1-value";
        var appEnvironment = new Mock <IWebHostEnvironment>();

        appEnvironment.Setup(app => app.WebRootFileProvider)
        .Returns(GetFileProvider(path));

        var sendFileFeature = new TestSendFileFeature();
        var httpContext     = GetHttpContext(GetFileProvider(path));

        httpContext.Features.Set <IHttpResponseBodyFeature>(sendFileFeature);

        var entityTag      = new EntityTagHeaderValue("\"Etag\"");
        var requestHeaders = httpContext.Request.GetTypedHeaders();

        requestHeaders.IfModifiedSince = DateTimeOffset.MinValue;
        requestHeaders.Range           = new RangeHeaderValue(0, 3);
        requestHeaders.IfRange         = new RangeConditionHeaderValue(new EntityTagHeaderValue("\"Etag\""));
        httpContext.Request.Method     = HttpMethods.Get;

        // Act
        await ExecuteAsync(httpContext, path, contentType, entityTag : entityTag, enableRangeProcessing : true);

        // Assert
        var httpResponse = httpContext.Response;

        Assert.Equal(StatusCodes.Status206PartialContent, httpResponse.StatusCode);
        Assert.Equal("bytes", httpResponse.Headers.AcceptRanges);
        var contentRange = new ContentRangeHeaderValue(0, 3, 33);

        Assert.Equal(contentRange.ToString(), httpResponse.Headers.ContentRange);
        Assert.Equal(entityTag.ToString(), httpResponse.Headers.ETag);
        Assert.Equal(4, httpResponse.ContentLength);
        Assert.Equal(path, sendFileFeature.Name);
        Assert.Equal(0, sendFileFeature.Offset);
        Assert.Equal(4, sendFileFeature.Length);
    }
Exemple #17
0
        public async Task 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();
            await content.CopyToAsync(result);

            MultipartMemoryStreamProvider multipart = await content.ReadAsMultipartAsync();

            // 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);
            }
        }
Exemple #18
0
    public async Task ExecuteResultAsync_CallsSendFileAsyncWithRequestedRange_IfIHttpSendFilePresent(long?start, long?end, long contentLength)
    {
        // Arrange
        var path = Path.Combine("TestFiles", "FilePathResultTestFile.txt");

        var sendFile    = new TestSendFileFeature();
        var httpContext = GetHttpContext(GetFileProvider(path));

        httpContext.Features.Set <IHttpResponseBodyFeature>(sendFile);
        var appEnvironment = new Mock <IWebHostEnvironment>();

        appEnvironment.Setup(app => app.WebRootFileProvider)
        .Returns(GetFileProvider(path));

        var requestHeaders = httpContext.Request.GetTypedHeaders();

        requestHeaders.Range             = new RangeHeaderValue(start, end);
        requestHeaders.IfUnmodifiedSince = DateTimeOffset.MinValue.AddDays(1);
        httpContext.Request.Method       = HttpMethods.Get;

        // Act
        await ExecuteAsync(httpContext, path, "text/plain", enableRangeProcessing : true);

        // Assert
        start = start ?? 33 - end;
        end   = start + contentLength - 1;
        var httpResponse = httpContext.Response;

        Assert.Equal(Path.Combine("TestFiles", "FilePathResultTestFile.txt"), sendFile.Name);
        Assert.Equal(start, sendFile.Offset);
        Assert.Equal(contentLength, sendFile.Length);
        Assert.Equal(CancellationToken.None, sendFile.Token);
        var contentRange = new ContentRangeHeaderValue(start.Value, end.Value, 33);

        Assert.Equal(StatusCodes.Status206PartialContent, httpResponse.StatusCode);
        Assert.Equal("bytes", httpResponse.Headers.AcceptRanges);
        Assert.Equal(contentRange.ToString(), httpResponse.Headers.ContentRange);
        Assert.NotEmpty(httpResponse.Headers.LastModified);
        Assert.Equal(contentLength, httpResponse.ContentLength);
    }
        public void GetContentRangeLength_DifferentValidScenarios_AllReturnNonZero()
        {
            ContentRangeHeaderValue result = null;

            CallGetContentRangeLength("bytes 1-2/3", 0, 11, out result);
            Assert.Equal("bytes", result.Unit);
            Assert.Equal(1, result.From);
            Assert.Equal(2, result.To);
            Assert.Equal(3, result.Length);
            Assert.True(result.HasRange);
            Assert.True(result.HasLength);

            CallGetContentRangeLength(" custom 1234567890123456789-1234567890123456799/*", 1, 48, out result);
            Assert.Equal("custom", result.Unit);
            Assert.Equal(1234567890123456789, result.From);
            Assert.Equal(1234567890123456799, result.To);
            Assert.Null(result.Length);
            Assert.True(result.HasRange);
            Assert.False(result.HasLength);

            // Note that the final space should be skipped by GetContentRangeLength() and be considered by the returned
            // value.
            CallGetContentRangeLength(" custom * / 123 ", 1, 15, out result);
            Assert.Equal("custom", result.Unit);
            Assert.Null(result.From);
            Assert.Null(result.To);
            Assert.Equal(123, result.Length);
            Assert.False(result.HasRange);
            Assert.True(result.HasLength);

            // Note that we don't have a public constructor for value 'bytes */*' since the RFC doesn't mention a
            // scenario for it. However, if a server returns this value, we're flexible and accept it.
            CallGetContentRangeLength("bytes */*", 0, 9, out result);
            Assert.Equal("bytes", result.Unit);
            Assert.Null(result.From);
            Assert.Null(result.To);
            Assert.Null(result.Length);
            Assert.False(result.HasRange);
            Assert.False(result.HasLength);
        }
Exemple #20
0
        public async Task ExecuteResultAsync_CallsSendFileAsyncWithRequestedRange_IfIHttpSendFilePresent(long?start, long?end, long contentLength)
        {
            // Arrange
            var path   = Path.GetFullPath(Path.Combine("TestFiles", "FilePathResultTestFile.txt"));
            var result = new TestPhysicalFileResult(path, "text/plain");

            result.EnableRangeProcessing = true;
            var sendFile    = new TestSendFileFeature();
            var httpContext = GetHttpContext();

            httpContext.Features.Set <IHttpSendFileFeature>(sendFile);
            var context        = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
            var requestHeaders = httpContext.Request.GetTypedHeaders();

            requestHeaders.Range             = new RangeHeaderValue(start, end);
            requestHeaders.IfUnmodifiedSince = DateTimeOffset.MinValue.AddDays(1);
            httpContext.Request.Method       = HttpMethods.Get;
            var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

            // Act
            await result.ExecuteResultAsync(actionContext);

            // Assert
            start = start ?? 34 - end;
            end   = start + contentLength - 1;
            var httpResponse = actionContext.HttpContext.Response;

            Assert.Equal(Path.GetFullPath(Path.Combine("TestFiles", "FilePathResultTestFile.txt")), sendFile.Name);
            Assert.Equal(start, sendFile.Offset);
            Assert.Equal(contentLength, sendFile.Length);
            Assert.Equal(CancellationToken.None, sendFile.Token);
            var contentRange = new ContentRangeHeaderValue(start.Value, end.Value, 34);

            Assert.Equal(StatusCodes.Status206PartialContent, httpResponse.StatusCode);
            Assert.Equal("bytes", httpResponse.Headers[HeaderNames.AcceptRanges]);
            Assert.Equal(contentRange.ToString(), httpResponse.Headers[HeaderNames.ContentRange]);
            Assert.NotEmpty(httpResponse.Headers[HeaderNames.LastModified]);
            Assert.Equal(contentLength, httpResponse.ContentLength);
        }
Exemple #21
0
    public async Task WriteFileAsync_RangeRequestedNotSatisfiable(string rangeString)
    {
        // Arrange
        var path           = Path.GetFullPath("helllo.txt");
        var contentType    = "text/plain; charset=us-ascii; p1=p1-value";
        var appEnvironment = new Mock <IWebHostEnvironment>();

        appEnvironment.Setup(app => app.WebRootFileProvider)
        .Returns(GetFileProvider(path));

        var httpContext = GetHttpContext(GetFileProvider(path));

        httpContext.Response.Body = new MemoryStream();

        var requestHeaders = httpContext.Request.GetTypedHeaders();

        httpContext.Request.Headers.Range = rangeString;
        requestHeaders.IfUnmodifiedSince  = DateTimeOffset.MinValue.AddDays(1);
        httpContext.Request.Method        = HttpMethods.Get;
        httpContext.Response.Body         = new MemoryStream();

        // Act
        await ExecuteAsync(httpContext, path, contentType, enableRangeProcessing : true);

        // Assert
        var httpResponse = httpContext.Response;

        httpResponse.Body.Seek(0, SeekOrigin.Begin);
        var streamReader = new StreamReader(httpResponse.Body);
        var body         = streamReader.ReadToEndAsync().Result;
        var contentRange = new ContentRangeHeaderValue(33);

        Assert.Equal(StatusCodes.Status416RangeNotSatisfiable, httpResponse.StatusCode);
        Assert.Equal("bytes", httpResponse.Headers.AcceptRanges);
        Assert.Equal(contentRange.ToString(), httpResponse.Headers.ContentRange);
        Assert.NotEmpty(httpResponse.Headers.LastModified);
        Assert.Equal(0, httpResponse.ContentLength);
        Assert.Empty(body);
    }
Exemple #22
0
        public async Task WriteFileAsync_IfRangeHeaderValid_WritesRequestedRange()
        {
            // Arrange
            var path      = Path.GetFullPath(Path.Combine("TestFiles", "FilePathResultTestFile.txt"));
            var result    = new TestPhysicalFileResult(path, "text/plain");
            var entityTag = result.EntityTag = new EntityTagHeaderValue("\"Etag\"");

            result.EnableRangeProcessing = true;
            var httpContext    = GetHttpContext();
            var requestHeaders = httpContext.Request.GetTypedHeaders();

            requestHeaders.IfModifiedSince = DateTimeOffset.MinValue;
            requestHeaders.Range           = new RangeHeaderValue(0, 3);
            requestHeaders.IfRange         = new RangeConditionHeaderValue(new EntityTagHeaderValue("\"Etag\""));
            httpContext.Request.Method     = HttpMethods.Get;
            httpContext.Response.Body      = new MemoryStream();
            var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

            // Act
            await result.ExecuteResultAsync(actionContext);

            // Assert
            var httpResponse = actionContext.HttpContext.Response;

            httpResponse.Body.Seek(0, SeekOrigin.Begin);
            var streamReader = new StreamReader(httpResponse.Body);
            var body         = streamReader.ReadToEndAsync().Result;

            Assert.Equal(StatusCodes.Status206PartialContent, httpResponse.StatusCode);
            Assert.Equal("bytes", httpResponse.Headers[HeaderNames.AcceptRanges]);
            var contentRange = new ContentRangeHeaderValue(0, 3, 34);

            Assert.Equal(contentRange.ToString(), httpResponse.Headers[HeaderNames.ContentRange]);
            Assert.NotEmpty(httpResponse.Headers[HeaderNames.LastModified]);
            Assert.Equal(entityTag.ToString(), httpResponse.Headers[HeaderNames.ETag]);
            Assert.Equal(4, httpResponse.ContentLength);
            Assert.Equal("File", body);
        }
        public static async Task WriteFileAsync_RangeRequestedNotSatisfiable <TContext>(
            string rangeString,
            Func <PhysicalFileResult, TContext, Task> function)
        {
            // Arrange
            var path   = Path.GetFullPath(Path.Combine("TestFiles", "FilePathResultTestFile.txt"));
            var result = new TestPhysicalFileResult(path, "text/plain");

            result.EnableRangeProcessing = true;
            var httpContext    = GetHttpContext();
            var requestHeaders = httpContext.Request.GetTypedHeaders();

            requestHeaders.IfModifiedSince    = DateTimeOffset.MinValue;
            httpContext.Request.Headers.Range = rangeString;
            httpContext.Request.Method        = HttpMethods.Get;
            httpContext.Response.Body         = new MemoryStream();
            var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

            // Act
            object context = typeof(TContext) == typeof(HttpContext) ? httpContext : actionContext;

            await function(result, (TContext)context);

            // Assert
            var httpResponse = actionContext.HttpContext.Response;

            httpResponse.Body.Seek(0, SeekOrigin.Begin);
            var streamReader = new StreamReader(httpResponse.Body);
            var body         = streamReader.ReadToEndAsync().Result;
            var contentRange = new ContentRangeHeaderValue(34);

            Assert.Equal(StatusCodes.Status416RangeNotSatisfiable, httpResponse.StatusCode);
            Assert.Equal("bytes", httpResponse.Headers.AcceptRanges);
            Assert.Equal(contentRange.ToString(), httpResponse.Headers.ContentRange);
            Assert.NotEmpty(httpResponse.Headers.LastModified);
            Assert.Equal(0, httpResponse.ContentLength);
            Assert.Empty(body);
        }
Exemple #24
0
        /// <summary>
        /// Copies content headers.
        /// </summary>
        /// <param name="httpContent">Http content.</param>
        /// <param name="headerCollection">Header collection.</param>
        private static void CopyContentHeader(HttpContent httpContent, WebHeaderCollection headerCollection)
        {
            if (headerCollection["Content-Disposition"] != null)
            {
                httpContent.Headers.ContentDisposition = ContentDispositionHeaderValue.Parse(headerCollection["Content-Disposition"]);
            }

            if (headerCollection[HttpRequestHeader.ContentLocation] != null)
            {
                httpContent.Headers.ContentLocation = new Uri(headerCollection[HttpRequestHeader.ContentLocation]);
            }

            if (headerCollection[HttpRequestHeader.ContentRange] != null)
            {
                httpContent.Headers.ContentRange = ContentRangeHeaderValue.Parse(headerCollection[HttpRequestHeader.ContentRange]);
            }

            if (headerCollection[HttpRequestHeader.ContentType] != null)
            {
                httpContent.Headers.ContentType = MediaTypeHeaderValue.Parse(headerCollection[HttpRequestHeader.ContentType]);
            }

            if (headerCollection[HttpRequestHeader.Expires] != null)
            {
                httpContent.Headers.Expires = DateTimeOffset.Parse(headerCollection[HttpRequestHeader.Expires], CultureInfo.InvariantCulture);
            }

            if (headerCollection[HttpRequestHeader.LastModified] != null)
            {
                httpContent.Headers.LastModified = DateTimeOffset.Parse(headerCollection[HttpRequestHeader.LastModified], CultureInfo.InvariantCulture);
            }

            if (headerCollection[HttpRequestHeader.ContentLength] != null)
            {
                httpContent.Headers.ContentLength = long.Parse(headerCollection[HttpRequestHeader.ContentLength], CultureInfo.InvariantCulture);
            }
        }
Exemple #25
0
        /// <summary>
        /// Perform the WebDAV call and fire the callback when finished.
        /// </summary>
        /// <param name="uri"></param>
        /// <param name="headers"></param>
        /// <param name="method"></param>
        /// <param name="content"></param>
        private async Task <HttpResponseMessage> HttpUploadRequest(Uri uri, HttpMethod method, Stream content, IDictionary <string, string> headers = null, long?startbytes = null, long?endbytes = null, long?totalLength = null)
        {
            using (var request = new HttpRequestMessage(method, uri))
            {
                request.Headers.Connection.Add("Keep-Alive");
                if (!string.IsNullOrWhiteSpace(UserAgent))
                {
                    request.Headers.UserAgent.Add(new ProductInfoHeaderValue(UserAgent, UserAgentVersion));
                }
                else
                {
                    request.Headers.UserAgent.Add(new ProductInfoHeaderValue("WebDAVClient", AssemblyVersion));
                }

                if (headers != null)
                {
                    foreach (string key in headers.Keys)
                    {
                        request.Headers.Add(key, headers[key]);
                    }
                }

                // Need to send along content?
                if (content != null)
                {
                    request.Content = new StreamContent(content);
                    if (startbytes.HasValue && endbytes.HasValue)
                    {
                        var len = totalLength.HasValue ? totalLength.ToString() : "*";
                        request.Content.Headers.ContentRange  = ContentRangeHeaderValue.Parse($"bytes {startbytes}-{endbytes}/{len}");
                        request.Content.Headers.ContentLength = endbytes - startbytes + 1;
                    }
                }

                return(await _httpClientWrapper.SendUploadAsync(request).ConfigureAwait(false));
            }
        }
Exemple #26
0
        public async Task WriteFileAsync_WritesRangeRequested(long?start, long?end, string expectedString, long contentLength)
        {
            // Arrange
            var path   = Path.GetFullPath(Path.Combine("TestFiles", "FilePathResultTestFile.txt"));
            var result = new TestPhysicalFileResult(path, "text/plain");

            result.EnableRangeProcessing = true;
            var httpContext    = GetHttpContext();
            var requestHeaders = httpContext.Request.GetTypedHeaders();

            requestHeaders.IfModifiedSince = DateTimeOffset.MinValue;
            requestHeaders.Range           = new RangeHeaderValue(start, end);
            httpContext.Request.Method     = HttpMethods.Get;
            httpContext.Response.Body      = new MemoryStream();
            var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

            // Act
            await result.ExecuteResultAsync(actionContext);

            // Assert
            start = start ?? 34 - end;
            end   = start + contentLength - 1;
            var httpResponse = actionContext.HttpContext.Response;

            httpResponse.Body.Seek(0, SeekOrigin.Begin);
            var streamReader = new StreamReader(httpResponse.Body);
            var body         = streamReader.ReadToEndAsync().Result;
            var contentRange = new ContentRangeHeaderValue(start.Value, end.Value, 34);

            Assert.Equal(StatusCodes.Status206PartialContent, httpResponse.StatusCode);
            Assert.Equal("bytes", httpResponse.Headers[HeaderNames.AcceptRanges]);
            Assert.Equal(contentRange.ToString(), httpResponse.Headers[HeaderNames.ContentRange]);
            Assert.NotEmpty(httpResponse.Headers[HeaderNames.LastModified]);
            Assert.Equal(contentLength, httpResponse.ContentLength);
            Assert.Equal(expectedString, body);
        }
Exemple #27
0
        public HttpResponseMessage Play(string filePath)
        {
            if (string.IsNullOrWhiteSpace(filePath))
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }

            var fileInfo = new FileInfo(filePath);

            if (!fileInfo.Exists)
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }

            string val;

            if (!MimeNames.TryGetValue(Path.GetExtension(filePath), out val))
            {
                fileInfo = new FileInfo(Path.ChangeExtension(filePath, ".mp4"));
                if (!fileInfo.Exists)
                {
                    var fileName = Conversion.RemuxVideoToMp4(filePath, true);
                    fileInfo = new FileInfo(fileName);
                }
            }

            var totalLength = fileInfo.Length;

            var rangeHeader = Request.Headers.Range;
            var response    = new HttpResponseMessage();

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

            // The request will be treated as normal request if there is no Range header.
            if (rangeHeader == null || !rangeHeader.Ranges.Any())
            {
                response.StatusCode = HttpStatusCode.OK;
                response.Content    = new PushStreamContent((outputStream, httpContent, transpContext)
                                                            =>
                {
                    using (outputStream) // Copy the file to output stream straightforward.
                        using (Stream inputStream = fileInfo.OpenRead())
                        {
                            try
                            {
                                inputStream.CopyTo(outputStream, ReadStreamBufferSize);
                            }
                            catch (Exception error)
                            {
                                Debug.WriteLine(error);
                            }
                        }
                }, GetMimeNameFromExt(fileInfo.Extension));

                response.Content.Headers.ContentLength = totalLength;
                return(response);
            }

            long start = 0, end = 0;

            // 1. If the unit is not 'bytes'.
            // 2. If there are multiple ranges in header value.
            // 3. If start or end position is greater than file length.
            if (rangeHeader.Unit != "bytes" || rangeHeader.Ranges.Count > 1 ||
                !TryReadRangeItem(rangeHeader.Ranges.First(), totalLength, out start, out end))
            {
                response.StatusCode = HttpStatusCode.RequestedRangeNotSatisfiable;
                response.Content    = new StreamContent(Stream.Null); // No content for this status.
                response.Content.Headers.ContentRange = new ContentRangeHeaderValue(totalLength);
                response.Content.Headers.ContentType  = GetMimeNameFromExt(fileInfo.Extension);

                return(response);
            }

            var contentRange = new ContentRangeHeaderValue(start, end, totalLength);

            // We are now ready to produce partial content.
            response.StatusCode = HttpStatusCode.PartialContent;
            response.Content    = new PushStreamContent((outputStream, httpContent, transpContext)
                                                        =>
            {
                using (outputStream) // Copy the file to output stream in indicated range.
                    using (Stream inputStream = fileInfo.OpenRead())
                        CreatePartialContent(inputStream, outputStream, start, end);
            }, GetMimeNameFromExt(fileInfo.Extension));

            response.Content.Headers.ContentLength = end - start + 1;
            response.Content.Headers.ContentRange  = contentRange;

            return(response);
        }
Exemple #28
0
 /// <summary>
 /// Returns ContentRange from headers.
 /// </summary>
 /// <param name="headers">Headers collection</param>
 /// <returns>ContentRange object</returns>
 public static ContentRangeHeaderValue GetContentRange(this WebHeaderCollection headers)
 {
     Contract.Requires(headers != null);
     return(ContentRangeHeaderValue.Parse(headers["Content-Range"]));
 }
 private void CheckInvalidParse(string input)
 {
     Assert.Throws <FormatException>(() => { ContentRangeHeaderValue.Parse(input); });
 }
        private void CheckValidParse(string input, ContentRangeHeaderValue expectedResult)
        {
            ContentRangeHeaderValue result = ContentRangeHeaderValue.Parse(input);

            Assert.Equal(expectedResult, result);
        }