Expand documentation
slanden opened this issue · 12 comments
This middleware looks useful, but I'm not sure how to use it. Perhaps more examples with explanations would help?
I'd like to use brotli if the client accepts it, and fallback to gzip if not. In the readme, your example disables brotli and later states,
Brotli compression is supported in node v11.7.0+, which includes it natively.
Is brotli disabled because Node includes it natively or because that's just the example?
The current encodings are, in order of preference: br, gzip, deflate
Does the order of the encodings in the options object matter or is the "preference" always the same order?
Does one encoding fallback to another if not supported?
I'm unable to help with contributing these changes because I don't understand how it works, but I think answering these questions in the readme would help others understand. Or maybe it's just me..
PR welcome!
The user/client is the one that ultimately determines what compression methods it accepts.
Is brotli disabled because Node includes it natively or because that's just the example?
It is just an example. If you don't do anything, clients supporting br
will get a br
response, if your server is running on v11.7.0+.
Does one encoding fallback to another if not supported?
If a client or a server doesn't support an encoding from the list, the next one will be checked and used.
Does this explanation work for you? If not, ask away and let's refine our message. If it does, I'll be happy to submit a PR to update the docs.
@uhop Thank you, yes I think your answers make sense. It'd be helpful as well to be clear about what will happen by default (whether Node 11.7+ or an unsupported version), and then the order the fallbacks will happen.
So, here's my understanding based on what you've said:
app.use(compress())
will result in responses using brotli compression if using Node 11.7+, and otherwise return gzip responses. If for some reason gzip doesn't work or is not an option (again, I don't know anything about compression), then deflate is used.
This is always the order of selection. If an Options object is passed, the order of its keys doesn't change this order.
Is that correct?
Also, for options.defaultEncoding
An optional string, which specifies what encoders to use for requests without Accept-Encoding
does this mean that in all cases, Koa Compress checks the request's Accept-Encoding header to further eliminate compression options from the selection?
It seems natural that this would be the case, but I'm not one for assumptions..
options.defaultEncoding
is also stated to be set to identity
by default. What does that do?
So, here's my understanding based on what you've said
Encoders are going to be tried in this order: ['br', 'gzip', 'deflate']
unless eliminated by Accept-Encoding
and availability of actual encoders (brotli).
Also, for options.defaultEncoding
When a client sends Accept-Encoding
, its value is a list/set of accepted encodings. The rest is trivial. But there are two edge cases:
- The client does not send
Accept-Encoding
at all. - The client sends
Accept-Encoding
set to"*"
.
In the former case, options.defaultEncoding
is used. By default, it is identity
. By the standard, it should be "*"
, which gets many people with curl
or wget
puzzled.
In the latter case, it will be ['gzip', 'deflate']
.
What if all encoders are somehow eliminated? The catch-all will be identity
.
options.defaultEncoding is also stated to be set to identity by default. What does that do?
identity
means "no compression". Data will be left unchanged and no encoding is going to be used.
options.defaultEncoding
is documented. Two other arrays (the order of encoders and the "*"
substitute) are not, but they are available to be replaced by a user. Probably they should be documented, and even made available through options
.
In the latter case, it will be
['gzip', 'deflate']
.
Why is 'br' not listed here also?
Beats me. TBH using "*"
doesn't make much sense at all. What does it mean? All possible encodings, including uninvented yet? I never saw it being used in the wild. I suspect that if some client uses it, it is probably a legacy one, which doesn't know about brotli
. That's probably why.
IMHO the only plausible scenario for "*"
is a closed system. For example, I have a client, which talks only to a certain server. The server can use only a set of predefined encodings. My client may understand all of them and indicate it with "*"
. In this scenario, the set of supported encodings on both sides is implicitly defined and cannot change.
I think you've cleared up everything that was missing from the docs, thank you! I don't understand the relation between our last two comments, but
Beats me.
tells me you didn't leave out the 'br'
from that list by accident so that's good enough for me.
Beats me.
I guess that the authors decided to be reasonably conservative and in the case of "*"
they will serve gzip
. I don't see any other possible scenario when any other encoding is going to be selected. br
is not included to prevent it from being selected instead of gzip
.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding we are just trying to be as true to the specs as possible :) it's very confusing
Hello there! Catching up with this thread. Have a question for a simple general use case using Koa for an API for a website. Can just use compress()
without any customizations? It seems to work fine. As a library user, I'd like to trust the defaults.
In examples around the internet, I've seen gzip: { flush: require('zlib').constants.Z_SYNC_FLUSH }
passed very frequently. What does this do, and is it required to explicitly pass?
Thanks to all for contributing and maintaining koa-compress
!
Here's what we do for @forwardemail and @ladjs:
// https://github.com/koajs/compress
app.use(compress({
br: {
params: {
[zlib.constants.BROTLI_PARAM_MODE]: zlib.constants.BROTLI_MODE_TEXT,
[zlib.constants.BROTLI_PARAM_QUALITY]: 4
}
}
}));