* reverseproxy: Adjust defaults, document defaults
Related to some of the issues in https://github.com/caddyserver/caddy/issues/4245, a complaint about the proxy transport defaults not being properly documented in https://caddy.community/t/default-values-for-directives/14254/6.
- Dug into the stdlib to find the actual defaults for some of the timeouts and buffer limits, documenting them in godoc so the JSON docs get them next release.
- Moved the keep-alive and dial-timeout defaults from `reverseproxy.go` to `httptransport.go`. It doesn't make sense to set defaults in the proxy, because then any time the transport is configured with non-defaults, the keep-alive and dial-timeout defaults are lost!
- Sped up the dial timeout from 10s to 3s, in practice it rarely makes sense to wait a whole 10s for dialing. A shorter timeout helps a lot with the load balancer retries, so using something lower helps with user experience.
* reverseproxy: Make keepalive interval configurable via Caddyfile
* fastcgi: DialTimeout default for fastcgi transport too
Fixes#4428
It's best to still log handler errors at debug level so that they're hidden by default, but still accessible if additional details are necessary.
This makes it easier for users to find the default browse template if they
want to create a custom template based on that. It also makes it easier to
view the template with proper syntax highlighting.
* caddyhttp: Sanitize scheme and host on incoming requests
* reverseproxy: Sanitize the URL scheme and host before proxying
* Apply suggestions from code review
Co-authored-by: Matt Holt <mholt@users.noreply.github.com>
Co-authored-by: Matt Holt <mholt@users.noreply.github.com>
* Update tplcontext.go
Add {{ render "/path/to/file.ext" $data }} via funcRender
* Update tplcontext.go
* Refactor funcInclude, add funcImport to enable {{block}} and {{template}}
* Fix funcImport return of nil showing up in html
* Update godocs for and
* Add tests for funcInclude
* Add tests for funcImport
* os.RemoveAll -> os.Remove for TestFuncInclude and TestFuncImport
Related to (closed) Issue #2094 on template inheritance. This PR adds a new function called "import" which works like "include", except it only takes one argument and passes it to the referenced file to be used as "." in that file.
* Update tplcontext.go
Add {{ render "/path/to/file.ext" $data }} via funcRender
* Update tplcontext.go
* Refactor funcInclude, add funcImport to enable {{block}} and {{template}}
* Fix funcImport return of nil showing up in html
* Update godocs for and
* caddyhttp: Add support for triggering errors from `try_files`
* caddyhttp: Use vars instead of placeholders/replacer for matcher errors
* caddyhttp: Add comment for matcher error var key
* encode: ignore flushing until after first write (fix#4314)
The first write will determine if encoding has to be done and will add an Content-Encoding. Until then Flushing has to be delayed so the Content-Encoding header can be added before headers and status code is written. (A passthrough flush would write header and status code)
* Update modules/caddyhttp/encode/encode.go
Co-authored-by: Matt Holt <mholt@users.noreply.github.com>
From reading through the code, I think this code path is now obsoleted by the changes made in https://github.com/caddyserver/caddy/pull/4266.
Basically, `h.flushInterval()` will set the flush interval to `-1` if we're in a bi-directional stream, and the recent PR ensured that `h.copyResponse()` properly flushes headers immediately when the flush interval is non-zero. So now there should be no need to call Flush before calling `h.copyResponse()`.
This commit fixes the `sortByNameDirFirst` variable inside fileserver to
match what browse's default template has.
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Tweak compression settings
zstd: Limit window sizes to 128K to keep memory in control both server and client size.
zstd: Write 0 length frames. This may be needed for compatibility.
zstd: Create fewer encoders. Small memory improvement.
gzip: Allow -2 (Huffman only) and -3 (stateless) compression modes.
* Update modules/caddyhttp/encode/zstd/zstd.go
Update docs.
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
This is the more correct implementation of 23dadc0d86 (#4179)... I think. This commit effectively undoes the revert in 8848df9c5d, but with corrections to the logic.
We *do* need to use the original request path (the path the browser knows) for redirects, since they are external, and rewrites are only internal.
However, if the path was rewritten to a non-canonical path, we should not redirect to canonicalize that, since rewrites are intentional by the site owner. Canonicalizing the path involves modifying only the suffix (base element, or filename) of the path. Thus, if a rewrite involves only the prefix (like how handle_path strips a path prefix), then we can (hopefully!) safely redirect using the original URI since the filename was not rewritten.
So basically, if rewrites modify the filename, we should not canonicalize those requests. If rewrites only modify another part of the path (commonly a prefix), we should be OK to redirect.
Templates are parsed at request-time (like they are in the templates middleware) to allow live changes to the template while the server is running. Fixes race condition.
Also refactored use of a buffer so a buffer put back in the pool will not continue to be used (written to client) in the meantime.
A couple of benchmarks removed due to refactor, which is fine, since we know pooling helps here.
Also split the Caddyfile subdirective keepalive_idle_conns into two properties so the conns and conns_per_host can be set separately.
This is technically a breaking change, but probably anyone who this breaks already had a broken config anyway, and silently fixing it won't help them fix their configs.
* logging: Implement dial timeout for net writer (fix#4083)
* Limit how often redials are attempted
This should cause dial blocking to occur only once every 10 seconds at most, but it also means the logger connection might be down for up to 10 seconds after it comes back online; oh well. We shouldn't block for DialTimeout at every single log emission.
* Clarify offline behavior
Turns out this was an oversight, we assumed we could use `{http.response.header.*}` but that doesn't work because those are grabbed from the response writer, and we haven't copied any headers into the response writer yet.
So the fix is to set all the response headers into the replacer at a new namespace before running the handlers.
This adds the `{http.reverse_proxy.header.*}` replacer.
See https://caddy.community/t/empty-http-response-header-x-accel-redirect/12447
* caddyfile(formatter): fix nesting not decrementing
This is an extremely weird edge-case where if you had a environment variable {}
on one line, a comment on the next line, and the closing of the block on the
following line; the rest of the Caddyfile would be indented further than it
should've been.
ref; https://github.com/matthewpi/vscode-caddyfile-support/issues/13
* run gofmt
* fmt: better way of handling edge case
Followup to #4150, #4151 /cc @ueffel @polarathene
After a bit of discussion with @mholt, we decided to remove `prefer` as a subdirective and just go with using the order implicitly always. Simpler config, simpler docs, etc.
Effectively changes 7776471 and reverts a small part of f35a7fa.
* caddyhttp: Fix fallback for the error handler chain
The fix I went with in the end (after realizing some mistaken assumptions in #4131) is to just make the routes fall back to errorEmptyHandler instead of the non-error empty handler, if Terminal is true, making the routes error-aware. Ultimately this was probably just an oversight when errors was implemented at some point in the early betas of v2.
See https://caddy.community/t/problem-with-basicauth-handle-errors/12243/9 for context.
* Revert "caddyhttp: Fix fallback for the error handler chain"
This reverts commit 95b6ac44a6.
* caddyhttp: Fix via `routes.go`
* fileserver: Fix `file` matcher with empty `try_files`
Fixes https://github.com/caddyserver/caddy/issues/4146
If `TryFiles` is empty, we fill it with `r.URL.Path`. In this case, this is `/`. Then later, in `prepareFilePath()`, we run the replacer (which turns `{path}` into `/` at that point) but `file` remains the original value (and the placeholder is still the placeholder there).
So then `strings.HasSuffix(file, "/")` will be `false` for the placeholder, but `true` for the empty `TryFiles` codepath, because `file` was `/` due to being set to the actual request value beforehand.
This means that `suffix` becomes `//` in that case, so after `sanitizedPathJoin`, it becomes `./`, so `strictFileExists`'s `strings.HasSuffix(file, separator)` codepath will return true.
I think we should change the `m.TryFiles == nil` codepath to `m.TryFiles = []string{"{http.request.uri.path}"}` for consistency. (And maybe consider hoisting this to `Provision` cause there's no point doing this on every request). I don't think this "optimization" of directly using `r.URL.Path` is so valuable, cause it causes this edgecase with directories.
* Update modules/caddyhttp/fileserver/matcher.go
Co-authored-by: Matt Holt <mholt@users.noreply.github.com>
Co-authored-by: Matt Holt <mholt@users.noreply.github.com>
* reverseproxy: Add `handle_response` blocks to `reverse_proxy` (#3710)
* reverseproxy: complete handle_response test
* reverseproxy: Change handle_response matchers to use named matchers
reverseproxy: Add support for changing status code
* fastcgi: Remove obsolete TODO
We already have d.Err("transport already specified") in the reverse_proxy parsing code which covers this case
* reverseproxy: Fix support for "4xx" type status codes
* Apply suggestions from code review
Co-authored-by: Matt Holt <mholt@users.noreply.github.com>
* caddyhttp: Reorganize response matchers
* reverseproxy: Reintroduce caddyfile.Unmarshaler
* reverseproxy: Add comment mentioning Finalize should be called
Co-authored-by: Maxime Soulé <btik-git@scoubidou.com>
Co-authored-by: Matt Holt <mholt@users.noreply.github.com>
Below is the report using `benchstat` and cmd:
`go test -run=BenchmarkHeaderREMatcher -bench=BenchmarkHeaderREMatcher -benchmem -count=10`
```
name old time/op new time/op delta
HeaderREMatcher-16 869ns ± 1% 658ns ± 0% -24.29% (p=0.000 n=10+10)
name old alloc/op new alloc/op delta
HeaderREMatcher-16 144B ± 0% 112B ± 0% -22.22% (p=0.000 n=10+10)
name old allocs/op new allocs/op delta
HeaderREMatcher-16 7.00 ± 0% 5.00 ± 0% -28.57% (p=0.000 n=10+10)
```
* caddyhttp: reverseproxy: fix hash selection policy
Fixes: #4135
Test: go test './...' -count=1
* caddyhttp: reverseproxy: add test to catch #4135
If you revert the last commit, the test will fail.
An idea that came up in https://caddy.community/t/save-internally-issued-wildcard-certificate-in-consul/11740, this a simple module that might be useful for anyone who uses storage modules that aren't filesystem, to let them load certs/keys externally issued for use by Caddy.
Bit goofy, since we need to fetch the certmagic.Storage during provisioning, it needs a wrapping struct instead of just being an array like `load_files`.
Future work might involve adding Caddyfile support via a subdirective of the `tls` directive maybe?
After reading a question about the `handle_response` feature of `reverse_proxy`, I realized that we didn't have a way of serving an arbitrary file with a status code other than 200. This is an issue in situations where you want to serve a custom error page in routes that are not errors, like the aforementioned `handle_response`, where you may want to retain the status code returned by the proxy but write a response with content from a file.
This feature is super simple, basically if a status code is configured (can be a status code number, or a placeholder string) then that status will be written out before serving the file - if we write the status code first, then the stdlib won't write its own (only the first HTTP status header wins).
* encode: implement prefer setting
* encode: minimum_length configurable via caddyfile
* encode: configurable content-types which to encode
* file_server: support precompressed files
* encode: use ReponseMatcher for conditional encoding of content
* linting error & documentation of encode.PrecompressedOrder
* encode: allow just one response matcher
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
* rounding of the PR
* 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
* file_server: add vary header, remove accept-ranges when serving precompressed files
* encode: move Suffix implementation to precompressed modules
* reverseproxy: Implement health_uri, replaces health_path, supports query
Also fixes a bug with `health_status` Caddyfile parsing , it would always only take the first character of the status code even if it didn't end with "xx".
* reverseproxy: Rename to URI, named logger, warn in Provision (for JSON)
This filter is intended to be useful in scenarios where you may want to
redact a value with a static string, giving you information that the
field did previously exist and was present, but not revealing the value
itself in the logs.
This was inspired by work on adding more complete support for removing
sensitive values from logs [1]. An example use case would be the
Authorization header in request log output, for which the value should
usually not be logged, but it may be quite useful for debugging to
confirm that the header was present in the request.
[1] https://github.com/caddyserver/caddy/issues/3958