Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add maxReturnSize option #90

Open
wants to merge 16 commits into
base: master
Choose a base branch
from

Conversation

ledyba
Copy link

@ledyba ledyba commented Nov 16, 2024

Currently, this library tends to send entire file when 'acceptRanges': true,

In this PR, I added maxChunkSize to send.SendOptions to limit the max chunk size.

Test case: https://hexe.net/2022/09/17/17:04:55/
Souce code is here

I'm using firefox 132.0.

Request:

GET /entity/eb3467a204907295921f367ac8187d67 HTTP/2
Host: hexe.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:132.0) Gecko/20100101 Firefox/132.0
Accept: video/webm,video/ogg,video/*;q=0.9,application/ogg;q=0.7,audio/*;q=0.6,*/*;q=0.5
Accept-Language: ja
Range: bytes=0-
DNT: 1
Connection: keep-alive
Referer: https://hexe.net/2022/09/17/17:04:55/
Sec-Fetch-Dest: video
Sec-Fetch-Mode: no-cors
Sec-Fetch-Site: same-origin
Accept-Encoding: identity
Priority: u=4
TE: trailers

Response:

HTTP/2 206 
server: nginx/1.26.1
date: Sat, 16 Nov 2024 14:48:38 GMT
content-type: video/mp4
content-length: 65347058
accept-ranges: bytes
cache-control: public, max-age=0
last-modified: Sat, 17 Sep 2022 08:04:49 GMT
etag: W/"3e51df2-1834a7a8ef4"
content-range: bytes 0-65347057/65347058
content-disposition: inline; filename="eb3467a204907295921f367ac8187d67.original.mp4"
X-Firefox-Spdy: h2

I also checked in MS Edge 131.0.2903.51.

Checklist

types/index.d.ts Outdated Show resolved Hide resolved
Copy link
Author

@ledyba ledyba left a comment

Choose a reason for hiding this comment

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

Thanks for the review. I added tsd tests for maxChunkSize and acceptRanges.

Could you take another look?

@ledyba ledyba requested a review from mcollina November 17, 2024 10:42
@Uzlopak
Copy link
Contributor

Uzlopak commented Nov 17, 2024

Is a maxChunkSize not basically a highWatermark? Should we name it like that?

@ledyba
Copy link
Author

ledyba commented Nov 17, 2024

I don't think that maxChunkSize is the best name. I'm not an English native, so I'd appreciate any advice.

@Fdawgs Fdawgs requested a review from Copilot November 20, 2024 10:33

Choose a reason for hiding this comment

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

Copilot reviewed 6 out of 6 changed files in this pull request and generated no suggestions.

Comments skipped due to low confidence (2)

test/utils.js:12

  • The function name should be 'shouldHaveHeader' instead of 'shouldNotHaveHeader'.
module.exports.shouldHaveHeader = function shouldNotHaveHeader (header, t) {

README.md:52

  • The heading should be 'maxChunkSize' instead of 'acceptRanges'.
##### acceptRanges
test/send.1.test.js Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
test/utils.js Outdated Show resolved Hide resolved
@Fdawgs Fdawgs changed the title Add maxChunkSize option to SendOptions feat: add maxChunkSize option Nov 20, 2024
Copy link
Author

@ledyba ledyba left a comment

Choose a reason for hiding this comment

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

Thank you for the review and typo suggestion!

Could you take another look?

README.md Outdated Show resolved Hide resolved
@ledyba ledyba requested a review from Fdawgs November 21, 2024 12:41
lib/send.js Outdated Show resolved Hide resolved
@Uzlopak
Copy link
Contributor

Uzlopak commented Nov 21, 2024

The name is not that nice. maxChunkSize is imho a highWatermark . @fastify/send only supports bytes for range. So it is de facto a highWaterMark

lib/send.js Outdated
@@ -546,6 +551,9 @@ function sendFileDirectly (request, path, stat, options) {

// Content-Range
statusCode = 206
if (options.maxChunkSize) {
ranges[0].end = Math.min(ranges[0].end, ranges[0].start + options.maxChunkSize - 1)
Copy link
Contributor

Choose a reason for hiding this comment

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

It doesnt seem right.

Copy link
Author

Choose a reason for hiding this comment

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

There are some unit tests that success, so I think you are pointing out some edge cases that cause bug. If so, could you tell me the condition or something?

Copy link
Contributor

@Uzlopak Uzlopak left a comment

Choose a reason for hiding this comment

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

preemptive blocker

Copy link
Member

@climba03003 climba03003 left a comment

Choose a reason for hiding this comment

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

I don't see a problem here.
In your request headers Range: bytes=0- means send me a file starting with bytes 0 to the end of the file.
And the response is actually does what it is requested.

Partial content return should be controlled by the request (client), not the response (server) to limit.

Copy link
Author

@ledyba ledyba left a comment

Choose a reason for hiding this comment

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

Thanks for the review. I renamed to highWatermark.

lib/send.js Outdated Show resolved Hide resolved
lib/send.js Outdated
@@ -546,6 +551,9 @@ function sendFileDirectly (request, path, stat, options) {

// Content-Range
statusCode = 206
if (options.maxChunkSize) {
ranges[0].end = Math.min(ranges[0].end, ranges[0].start + options.maxChunkSize - 1)
Copy link
Author

Choose a reason for hiding this comment

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

There are some unit tests that success, so I think you are pointing out some edge cases that cause bug. If so, could you tell me the condition or something?

@ledyba ledyba changed the title feat: add maxChunkSize option feat: add highWatermark option Nov 22, 2024
@ledyba
Copy link
Author

ledyba commented Nov 22, 2024

@climba03003 Thanks for the comment.

Here is the latest rfc(9110).

Here is a from 15.3.7. 206 Partial Content:

A server that supports range requests (Section 14) will usually attempt to satisfy all of the requested ranges, since sending less data will likely result in another client request for the remainder. However, a server might want to send only a subset of the data requested for reasons of its own, such as temporary unavailability, cache efficiency, load balancing, etc. Since a 206 response is self-descriptive, the client can still understand a response that only partially satisfies its range request.

So, I think this PR's behavior is, at least, compatible with RFC.

@climba03003
Copy link
Member

So, I think this PR's behavior is, at least, compatible with RFC.

Yes, a very rare use-case.

Is a maxChunkSize not basically a highWatermark? Should we name it like that?

highWaterMark is easily to mix with the stream highWaterMark option, especially when we return a stream currently.
From the operator description, it is an option to limit the whole payload size.
I am more toward something like maxReturnSize, maxStreamSize.

@ledyba
Copy link
Author

ledyba commented Nov 22, 2024

Thanks for understanding and naming recommendations!

I choiced maxReturnSize, because I thought that maxStreamSize might be confusing or difficult to understand unless you know that the underlying implementation uses fs.createReadStream.

@ledyba ledyba changed the title feat: add highWatermark option feat: add maxReturnSize option Nov 22, 2024
Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

lgtm

README.md Outdated Show resolved Hide resolved
Signed-off-by: Frazer Smith <[email protected]>
Copy link
Member

@gurgunday gurgunday left a comment

Choose a reason for hiding this comment

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

I think this is a bug fix no? Shouldn't it be on by default?

@gurgunday
Copy link
Member

Cc @climba03003

@climba03003
Copy link
Member

I think this is a bug fix no? Shouldn't it be on by default?

It is not a bugfix, but a feature request. By default, it should return as requested by the client.

@gurgunday
Copy link
Member

Oh I misunderstood

Currently, this library tends to send entire file when 'acceptRanges': true

I thought the server wasn't respecting the range headers or sth

@ledyba
Copy link
Author

ledyba commented Nov 28, 2024

Hi. I'm the author. I think this is not a bug fix. (Please see the title: it starts with feat: )

#90 (comment)
In a nutshell, even if the client requests all entire file range, the server can limit the response size. It seems allowed in RFC.
So, this feature is disabled by default.
It can be helpful for some rare cases:

However, a server might want to send only a subset of the data requested for reasons of its own, such as temporary unavailability, cache efficiency, load balancing, etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants