-
-
Notifications
You must be signed in to change notification settings - Fork 4k
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
encode: Enhancements to content negotiation, serving precompressed content #4045
encode: Enhancements to content negotiation, serving precompressed content #4045
Conversation
3379bb5
to
7bc0930
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome, thanks so much for working on this.
This is my first pass -- see what you think!
modules/caddyhttp/encode/encode.go
Outdated
|
||
// Only encode responses that are at least this many bytes long. | ||
MinLength int `json:"minimum_length,omitempty"` | ||
|
||
// Only encode responses that match at least one of the content-types. | ||
Types []string `json:"types,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It occurred to me, would there be any value in letting the user configure a ResponseMatcher
here? This could let them choose based on other headers (and status code) too, but I'm not sure how useful that is.
(To be clear, what you have is fine, but before we introduce a non-breakable change I want to get your thoughts on this. If the ResponseMatcher approach is feasible, that might be better since it gives more flexibility.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't know a ResponseMatcher
exists. I will have a look.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#4021 is something you could reference re response matchers. Not sure if that's quite the direction we want to go, but it could be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
encode zstd gzip {
minimum_length 256
prefer zstd gzip
@text {
status 2xx 4xx
header Content-Type text/*
header Content-Type application/json
header Content-Type application/javascript
header Content-Type application/xhtml+xml
header Content-Type application/atom+xml
header Content-Type application/rss+xml
header Content-Type image/svg+xml
}
match @text
}
something like this is possible now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm. I'm thinking whether it would work better like this, in this case, since it only makes sense to define match
once for encode
, unlike reverse_proxy
's handle_response
which can appear more than once:
encode [<encoders...>] {
match [<matcher> [<args...]] {
<matcher> <args...>
}
}
Basically skip the named matcher stuff and directly read the args on the same line and/or block for the matcher. This shouldn't change the code much, and should still be reusable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome! Looks good 😄
Small thing, I think it might be better to make parseNamedResponseMatcher
return the response matcher rather than shoving it into responseMatchers
and read it back out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't touched parseNamedResponseMatcher
intentionally. If it will be reusable in that state from your pull request, the changes required to use the hopefully soon merged implementation will be minimal.
Also it ensures right now, that match
is only defined once in a encode block.
modules/caddyhttp/encode/encode.go
Outdated
if len(enc.Types) == 0 { | ||
enc.Types = []string{"*"} // backwards compatibility | ||
|
||
// sane default for text-based content ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We like sane defaults
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
with the implementation via ResponseMatcher
the default is:
header Content-Type text/*
header Content-Type application/json
header Content-Type application/javascript
header Content-Type application/xhtml+xml
header Content-Type application/atom+xml
header Content-Type application/rss+xml
header Content-Type image/svg+xml
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed the default to:
header Content-Type text/*
header Content-Type application/json*
header Content-Type application/javascript*
header Content-Type application/xhtml+xml*
header Content-Type application/atom+xml*
header Content-Type application/rss+xml*
header Content-Type image/svg+xml*
to account for any ;charset=xxx
that may be appended to the header.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there any MIME types that could match these globs except for the ;charset=...
addition?
Could we use a regexp instead (or is it too much of a performance hit, maybe?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regexps aren't supported by the ResponseMatcher
type, yet. It would be nice the have a header_regexp
directive from RequestMatcher
s as well, but I think this would be out of the scope of this PR. Maybe an additional one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree we should have a header_regexp matcher. If you want to do a follow-up with that, that'd be great 👍
I am a bit worried that it would be detrimental to performance for the encode
defaults though, so a bit of benchmarking may be beneficial to see if it makes any appreciable difference.
PrecompressRaw caddy.ModuleMap `json:"encodings,omitempty" caddy:"namespace=http.precompressed"` | ||
|
||
// If the client has no strong preference, choose these encodings in order. | ||
PrecompressOrder []string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe explain what the default is.
Would you like changes to be in additional commit or should I rebase-edit changes into the existing commits? |
We squash-merge at the end, so do whatever works best for you for now 👍 |
7bc0930
to
b1fdbf0
Compare
also change the namespace of the encoders back, I accidently changed to precompressed >.> default matchers include a * to match to any charset, that may be appended
8673868
to
67ab2d0
Compare
Could you add an adapt test as well for this? See https://github.com/caddyserver/caddy/tree/master/caddytest/integration/caddyfile_adapt, both for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome, this is looking so good!! Nice work.
Just a couple nits. But I think we're good to go. Caddyfile tests that Francis mentioned can come either in this PR or a later one. Also, if you want to make sure godoc comments end with periods (or other proper punctuation), that'd be good for legibility when they are read on the docs website.
Almost there!
modules/caddyhttp/encode/encode.go
Outdated
|
||
// Only encode responses that are at least this many bytes long. | ||
MinLength int `json:"minimum_length,omitempty"` | ||
|
||
Matcher *caddyhttp.ResponseMatcher |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs a JSON tag 😊
modules/caddyhttp/encode/encode.go
Outdated
@@ -332,6 +392,13 @@ type Encoding interface { | |||
NewEncoder() Encoder | |||
} | |||
|
|||
// Precompressed is a type which returns filename suffix of precomressed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Precompressed is a type which returns filename suffix of precomressed | |
// Precompressed is a type which returns filename suffix of precompressed |
9cd73eb
to
d8154e7
Compare
The |
Right... Dangit. Yeah, I think a string replacement for Edit: Sorry - I think the replacement might need to happen inside |
* added integration tests for new caddyfile directives * improved various doc strings (punctuation and typos) * added json tag for file_server precompress order and encode matcher
d8154e7
to
10a4f2c
Compare
I just did it here, if that's ok? It seems to work, tests are not failing anymore. |
Yeah that seems okay to me 👍 |
So, I would consider this PR ready-to-merge or at least ready-for-final-review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is excellent work! Thank you!
If you find the time, it would be great if you could update the docs for https://github.com/caddyserver/website/blob/master/src/docs/markdown/caddyfile/directives/encode.md and https://github.com/caddyserver/website/blob/master/src/docs/markdown/caddyfile/directives/file_server.md to cover the changes 📝
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome, this looks good -- let's give it a try. Thanks for your persistence in helping to get this ready! Please contribute again sometime.
This pull request partly addresses #2665
It adds:
minimum_length
of a response for encoding to happen via caddyfileprefer
setting forencode
)Precompress
, which modules can implement to provide the file extension suffix for thefile_server
to search for precompressed filesDifferences to the previous iteration of the changes (master...ueffel:file_server-precompressed):
ueffel/caddy@file_server-precompressed...ueffel:file_server-precompressed_v2
http.precompressed.*
Edit:
Instead of introducing a new dependency to "github.com/gobwas/glob" now the content-types matching uses
filepath.Match
. Maybe the "validation" by matching with an empty string does not produce aErrBadPattern
for every bad patttern 🤔