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

Abort image prefetch if Content-Length exceeds limit #1567

Merged
merged 1 commit into from
Sep 25, 2017

Conversation

dgw
Copy link
Contributor

@dgw dgw commented Sep 24, 2017

Does adding this beg for the addition of tests? If so, someone will probably have to guide me in doing that. 😁

Closes #1563.

} else {
// response is an image
// if Content-Length header reports a size exceeding the prefetch limit, abort fetch
const contentLength = parseInt(res.headers["content-length"], 10) || NaN;
Copy link
Member

Choose a reason for hiding this comment

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

parseInt returns NaN on it's own, I would change it to 0 though, then you don't need to the AND check below.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Testing in Chrome's dev console with a simple literal object, running parseInt on a key that didn't exist set the test var to undefined. But using 0 instead is sensible. I went with NaN and the && in case a negative limit (i.e. no limit) is/will be possible.

@@ -163,6 +163,13 @@ function fetch(uri, cb) {
// if not image, limit download to 50kb, since we need only meta tags
// twitter.com sends opengraph meta tags within ~20kb of data for individual tweets
limit = 1024 * 50;
} else {
Copy link
Member

Choose a reason for hiding this comment

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

Can you invert the if above, it will look cleaner.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure what you're asking me to do, but my interpretation is to make the first if test for whether it is an image, rather than not, and swap the code blocks.

Copy link
Member

Choose a reason for hiding this comment

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

Correct.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@xPaw xPaw added the Type: Feature Tickets that describe a desired feature or PRs that add them to the project. label Sep 24, 2017
// if Content-Length header reports a size exceeding the prefetch limit, abort fetch
const contentLength = parseInt(res.headers["content-length"], 10) || NaN;
if (contentLength && contentLength > limit) {
res.req.abort();
Copy link
Member

Choose a reason for hiding this comment

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

This can be res.abort.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK, I was copying the code in the pipe handler below because I couldn't find a reference to abort() in the docs for request. For future reference, where is it documented that you can call abort() directly on the response passed to this event handler?

if ((/^image\/.+/.test(res.headers["content-type"]))) {
// response is an image
// if Content-Length header reports a size exceeding the prefetch limit, abort fetch
const contentLength = parseInt(res.headers["content-length"], 10) || NaN;
Copy link
Member

Choose a reason for hiding this comment

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

Do the 0 as I suggested.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This and the other comments in the batch are done.

@@ -159,7 +159,14 @@ function fetch(uri, cb) {
var limit = Helper.config.prefetchMaxImageSize * 1024;
req
.on("response", function(res) {
if (!(/^image\/.+/.test(res.headers["content-type"]))) {
if ((/^image\/.+/.test(res.headers["content-type"]))) {
Copy link
Member

Choose a reason for hiding this comment

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

You can remove extra parenthesis.

// if Content-Length header reports a size exceeding the prefetch limit, abort fetch
const contentLength = parseInt(res.headers["content-length"], 10) || 0;
if (contentLength > limit) {
res.abort();
Copy link
Member

Choose a reason for hiding this comment

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

@xPaw, in #1554, we went for req.abort(). I wonder if both do the same thing, but should we use the same thing then? Which do you prefer?

Copy link
Member

Choose a reason for hiding this comment

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

abort calls abort on req internally, so yes.

Copy link
Member

Choose a reason for hiding this comment

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

@dgw, mind switching to req.abort() then?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There's no req parameter passed to this handler, only res.

Copy link
Member

Choose a reason for hiding this comment

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

You have access to req from L160. It's also being used at R179 :)

Copy link
Contributor Author

@dgw dgw Sep 25, 2017

Choose a reason for hiding this comment

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

What. Has variable scoping changed since I learned JS (over a decade ago, I feel old 😁)? L160 is outside the function definitions in both cases; how does that work? 😕

(Also, L179 seems silly with the req.response.req thing… It's not related to this PR but now I really want to make it just req.abort()…)

Copy link
Member

@xPaw xPaw Sep 25, 2017

Choose a reason for hiding this comment

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

It should be req.abort, yeah.

if (/^image\/.+/.test(res.headers["content-type"])) {
// response is an image
// if Content-Length header reports a size exceeding the prefetch limit, abort fetch
const contentLength = parseInt(res.headers["content-length"], 10) || 0;
Copy link
Member

Choose a reason for hiding this comment

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

I know you guys had some discussion about this so sorry if I missed something, but it looks to me that you don't even need || 0 (which I find more misleading than explicit):

> const limit = 2048
undefined
> parseInt({}["content-length"], 10)
NaN
> NaN > limit
false
> null > limit
false
> undefined > limit
false
> 4096 > limit
true

So whatever parseInt returns, if the value is not an integer, the check below will be false.

Copy link
Member

Choose a reason for hiding this comment

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

It's not misleading as it will force an integer type.

Copy link
Member

Choose a reason for hiding this comment

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

It's not necessary, I don't think we should do it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't like comparing the wrong data type if I can avoid it. Passing NaN into anything number-related feels kinda dirty…

Copy link
Member

Choose a reason for hiding this comment

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

Fair enough, I guess.

If the Content-Length header is present in the response when an image
is prefetched, The Lounge can avoid wasting bandwidth (both for itself
and for the image's host) if the value of the header exceeds the
prefetch size limit by aborting the request immediately.
@xPaw xPaw added this to the 2.5.0 milestone Sep 25, 2017
@xPaw xPaw merged commit 08edc43 into thelounge:master Sep 25, 2017
@astorije astorije changed the title Abort image prefetch if Content-Length exceeds limit Abort image prefetch if Content-Length exceeds limit Sep 29, 2017
@dgw dgw deleted the preview-length-abort branch June 2, 2018 18:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Feature Tickets that describe a desired feature or PRs that add them to the project.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants