Skip to content
This repository has been archived by the owner on Nov 20, 2018. It is now read-only.

Add ByteRangeHelper #807

Closed
wants to merge 14 commits into from
Closed

Add ByteRangeHelper #807

wants to merge 14 commits into from

Conversation

jbagga
Copy link

@jbagga jbagga commented Mar 31, 2017

Moved RangeHelper from StaticFiles and added tests

See aspnet/Mvc#3702

cc @Tratcher @pranavkm

@dnfclas
Copy link

dnfclas commented Mar 31, 2017

@jbagga,
Thanks for having already signed the Contribution License Agreement. Your agreement was validated by .NET Foundation. We will now review your pull request.
Thanks,
.NET Foundation Pull Request Bot


namespace Microsoft.AspNetCore.WebUtilities
{
internal static class ByteRangeHelper
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't you using this type outside this repo?

// Adjusts ranges to be absolute and within bounds.
internal static IList<RangeItemHeaderValue> NormalizeRanges(ICollection<RangeItemHeaderValue> ranges, long length)
{
IList<RangeItemHeaderValue> normalizedRanges = new List<RangeItemHeaderValue>(ranges.Count);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var all day everyday

@jbagga
Copy link
Author

jbagga commented Apr 3, 2017

@pranavkm @Tratcher Updated

Copy link
Contributor

@pranavkm pranavkm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once @Tratcher is happy

// Adjusts ranges to be absolute and within bounds.
public static IList<RangeItemHeaderValue> NormalizeRanges(ICollection<RangeItemHeaderValue> ranges, long length)
{
var normalizedRanges = new List<RangeItemHeaderValue>(ranges.Count);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (ranges.Count == 0)
{
  return Array.Empty<RangeItemHeaderValue>();
}

var normalizedRanges = new List<RangeItemHeaderValue>(ranges.Count);
...

// first-byte-pos is less than the current length of the entity-body, or at least one suffix-byte-range-spec
// with a non-zero suffix-length, then the byte-range-set is satisfiable.
// Adjusts ranges to be absolute and within bounds.
public static IList<RangeItemHeaderValue> NormalizeRanges(ICollection<RangeItemHeaderValue> ranges, long length)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Split out a second method public static RangeItemHeaderValue NormalizeRange(RangeItemHeaderValue range, long length). Most of your tests only apply to this subset of the functionality.

@jbagga jbagga force-pushed the jbagga/ByteRangeHelper branch from b3a42c8 to 4cdc928 Compare April 3, 2017 22:18
@jbagga
Copy link
Author

jbagga commented Apr 3, 2017

@pranavkm @Tratcher Updated

@@ -2,13 +2,27 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using Microsoft.Net.Http.Headers;
using System.Collections.Generic;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

System.* goes first


var normalizedRanges = new List<RangeItemHeaderValue>(ranges.Count);

if (length == 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why doesn't this return Array.Empty<RangeItemHeaderValue>(); too?

{
if (start.Value >= length)
{
// Not satisfiable, skip/discard.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, my idea to make this a sub method just regressed this bit. You removed the continue that would have skipped adding the result. The behavior is now quite different. Is there a test case for this condition?
https://github.com/aspnet/StaticFiles/blob/f73dc5cebea6c08485662f1703d2aba1fc0cd408/src/Microsoft.AspNetCore.StaticFiles/Infrastructure/RangeHelpers.cs#L34

@jbagga
Copy link
Author

jbagga commented Apr 3, 2017

@Tratcher Added test cases to skip invalid ranges. Thank you for pointing it out!

@Tratcher Tratcher removed their assignment Apr 5, 2017
@jbagga jbagga force-pushed the jbagga/ByteRangeHelper branch from 3cbdada to 640e0ac Compare April 6, 2017 18:51
@jbagga
Copy link
Author

jbagga commented Apr 6, 2017

@Tratcher @pranavkm Added another method and tests

return normalizedRange;
}

public static bool ParseRange(HttpContext context, DateTimeOffset lastModified, EntityTagHeaderValue etag)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is less efficient the the original in StaticFiles. GetTypedHeaders creates a new structure (which you call multiple times) and .Range parses the header again without any caching. If you want to call it ParseRange then at least return the Range object.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doc comments

@@ -13,6 +13,8 @@

<ItemGroup>
<ProjectReference Include="..\Microsoft.Net.Http.Headers\Microsoft.Net.Http.Headers.csproj" />
<ProjectReference Include="..\Microsoft.AspNetCore.Http.Abstractions\Microsoft.AspNetCore.Http.Abstractions.csproj" />
<ProjectReference Include="..\Microsoft.AspNetCore.Http.Extensions\Microsoft.AspNetCore.Http.Extensions.csproj" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This layering is problematic. WebUtilities should not add these dependencies which makes it impossible to write your method here... I think you'll have to move it to Http.Extensions reduce the inputs.

@jbagga
Copy link
Author

jbagga commented Apr 6, 2017

@Tratcher @pranavkm Added doc comments and moved ParseRange to Extensions

/// <param name="lastModified">The <see cref="DateTimeOffset"/> representation of the last modified date of the file.</param>
/// <param name="etag">The <see cref="EntityTagHeaderValue"/> provided in the <see cref="HttpContext.Request"/>.</param>
/// <returns>A collection of <see cref="RangeItemHeaderValue"/> containing the ranges parsed from the <paramref name="requestHeaders"/>.</returns>
public static ICollection<RangeItemHeaderValue> ParseRange(HttpContext context, RequestHeaders requestHeaders, DateTimeOffset lastModified, EntityTagHeaderValue etag)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of your MVC file result types won't always have an etag or lastmodified right? What will you do there? or will null work as expected?

{
ignoreRangeHeader = true;
}
if (ignoreRangeHeader)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new line so this doesn't look like an else-if

@jbagga
Copy link
Author

jbagga commented Apr 7, 2017

@Tratcher I added null checks and made lastModified and etag optional params. Is that acceptable?

/// <param name="lastModified">The <see cref="DateTimeOffset"/> representation of the last modified date of the file.</param>
/// <param name="etag">The <see cref="EntityTagHeaderValue"/> provided in the <see cref="HttpContext.Request"/>.</param>
/// <returns>A collection of <see cref="RangeItemHeaderValue"/> containing the ranges parsed from the <paramref name="requestHeaders"/>.</returns>
public static ICollection<RangeItemHeaderValue> ParseRange(HttpContext context, RequestHeaders requestHeaders, DateTimeOffset? lastModified = null, EntityTagHeaderValue etag = null)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Default params are not allowed in most of our APIs.

bool ignoreRangeHeader = false;
if (ifRangeHeader.LastModified.HasValue)
{
if (lastModified != null && lastModified > ifRangeHeader.LastModified)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

!lastModified.HasValue

@jbagga
Copy link
Author

jbagga commented Apr 7, 2017

Closing as this has been addressed in aspnet/StaticFiles#185

@jbagga jbagga closed this Apr 7, 2017
@natemcmaster natemcmaster deleted the jbagga/ByteRangeHelper branch November 20, 2018 06:30
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants