Merge current v2.11 into v3.1
This commit is contained in:
commit
b641d5cf2a
17 changed files with 50 additions and 128 deletions
|
@ -640,3 +640,15 @@ Increasing the `readTimeout` value could be the solution notably if you are deal
|
|||
- TCP: `Error while handling TCP connection: readfrom tcp X.X.X.X:X->X.X.X.X:X: read tcp X.X.X.X:X->X.X.X.X:X: i/o timeout`
|
||||
- HTTP: `'499 Client Closed Request' caused by: context canceled`
|
||||
- HTTP: `ReverseProxy read error during body copy: read tcp X.X.X.X:X->X.X.X.X:X: use of closed network connection`
|
||||
|
||||
## v2.11.3
|
||||
|
||||
### Connection headers
|
||||
|
||||
In `v2.11.3`, the handling of the request Connection headers directives has changed to prevent any abuse.
|
||||
Before, Traefik removed any header listed in the Connection header just before forwarding the request to the backends.
|
||||
Now, Traefik removes the headers listed in the Connection header as soon as the request is handled.
|
||||
As a consequence, middlewares do not have access to those Connection headers,
|
||||
and a new option has been introduced to specify which ones could go through the middleware chain before being removed: `<entrypoint>.forwardedHeaders.connection`.
|
||||
|
||||
Please check out the [entrypoint forwarded headers connection option configuration](../routing/entrypoints.md#forwarded-headers) documentation.
|
||||
|
|
|
@ -67,6 +67,8 @@ accessLog:
|
|||
|
||||
### `format`
|
||||
|
||||
_Optional, Default="common"_
|
||||
|
||||
By default, logs are written using the Common Log Format (CLF).
|
||||
To write logs in JSON, use `json` in the `format` option.
|
||||
If the given format is unsupported, the default (CLF) is used instead.
|
||||
|
|
|
@ -136,6 +136,15 @@ api:
|
|||
|
||||
All the following endpoints must be accessed with a `GET` HTTP request.
|
||||
|
||||
!!! info "Pagination"
|
||||
|
||||
By default, up to 100 results are returned per page, and the next page can be checked using the `X-Next-Page` HTTP Header.
|
||||
To control pagination, use the `page` and `per_page` query parameters.
|
||||
|
||||
```bash
|
||||
curl https://traefik.example.com:8080/api/http/routers?page=2&per_page=20
|
||||
```
|
||||
|
||||
| Path | Description |
|
||||
|--------------------------------|---------------------------------------------------------------------------------------------|
|
||||
| `/api/http/routers` | Lists all the HTTP routers information. |
|
||||
|
|
2
go.mod
2
go.mod
|
@ -33,7 +33,7 @@ require (
|
|||
github.com/http-wasm/http-wasm-host-go v0.6.0
|
||||
github.com/influxdata/influxdb-client-go/v2 v2.7.0
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab // No tag on the repo.
|
||||
github.com/klauspost/compress v1.17.9
|
||||
github.com/klauspost/compress v1.17.11-0.20240927175842-8e14b1b5a913 // Required to have the content-type fix: https://github.com/klauspost/compress/pull/1011
|
||||
github.com/kvtools/consul v1.0.2
|
||||
github.com/kvtools/etcdv3 v1.0.2
|
||||
github.com/kvtools/redis v1.1.0
|
||||
|
|
4
go.sum
4
go.sum
|
@ -595,8 +595,8 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
|
|||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/klauspost/compress v1.17.11-0.20240927175842-8e14b1b5a913 h1:7s7Xd7zVElAw1qh/eh+tXDNfDNXXj38Tpq54eeG6/BM=
|
||||
github.com/klauspost/compress v1.17.11-0.20240927175842-8e14b1b5a913/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
|
|
|
@ -13,22 +13,21 @@ const (
|
|||
upgradeHeader = "Upgrade"
|
||||
)
|
||||
|
||||
// Remover removes hop-by-hop headers listed in the "Connection" header.
|
||||
// RemoveConnectionHeaders removes hop-by-hop headers listed in the "Connection" header.
|
||||
// See RFC 7230, section 6.1.
|
||||
func Remover(next http.Handler) http.HandlerFunc {
|
||||
return func(rw http.ResponseWriter, req *http.Request) {
|
||||
next.ServeHTTP(rw, Remove(req))
|
||||
}
|
||||
}
|
||||
|
||||
// Remove removes hop-by-hop header on the request.
|
||||
func Remove(req *http.Request) *http.Request {
|
||||
func RemoveConnectionHeaders(req *http.Request) {
|
||||
var reqUpType string
|
||||
if httpguts.HeaderValuesContainsToken(req.Header[connectionHeader], upgradeHeader) {
|
||||
reqUpType = req.Header.Get(upgradeHeader)
|
||||
}
|
||||
|
||||
removeConnectionHeaders(req.Header)
|
||||
for _, f := range req.Header[connectionHeader] {
|
||||
for _, sf := range strings.Split(f, ",") {
|
||||
if sf = textproto.TrimString(sf); sf != "" {
|
||||
req.Header.Del(sf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if reqUpType != "" {
|
||||
req.Header.Set(connectionHeader, upgradeHeader)
|
||||
|
@ -36,16 +35,4 @@ func Remove(req *http.Request) *http.Request {
|
|||
} else {
|
||||
req.Header.Del(connectionHeader)
|
||||
}
|
||||
|
||||
return req
|
||||
}
|
||||
|
||||
func removeConnectionHeaders(h http.Header) {
|
||||
for _, f := range h[connectionHeader] {
|
||||
for _, sf := range strings.Split(f, ",") {
|
||||
if sf = textproto.TrimString(sf); sf != "" {
|
||||
h.Del(sf)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,19 +50,13 @@ func TestRemover(t *testing.T) {
|
|||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
next := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {})
|
||||
|
||||
h := Remover(next)
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "https://localhost", nil)
|
||||
|
||||
for k, v := range test.reqHeaders {
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
|
||||
rw := httptest.NewRecorder()
|
||||
|
||||
h.ServeHTTP(rw, req)
|
||||
RemoveConnectionHeaders(req)
|
||||
|
||||
assert.Equal(t, test.expected, req.Header)
|
||||
})
|
||||
|
|
|
@ -120,8 +120,6 @@ func (fa *forwardAuth) GetTracingInformation() (string, string, trace.SpanKind)
|
|||
func (fa *forwardAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
logger := middlewares.GetLogger(req.Context(), fa.name, typeNameForward)
|
||||
|
||||
req = Remove(req)
|
||||
|
||||
forwardReq, err := http.NewRequestWithContext(req.Context(), http.MethodGet, fa.address, nil)
|
||||
if err != nil {
|
||||
logger.Debug().Msgf("Error calling %s. Cause %s", fa.address, err)
|
||||
|
@ -262,6 +260,8 @@ func (fa *forwardAuth) buildModifier(authCookies []*http.Cookie) func(res *http.
|
|||
|
||||
func writeHeader(req, forwardReq *http.Request, trustForwardHeader bool, allowedHeaders []string) {
|
||||
utils.CopyHeaders(forwardReq.Header, req.Header)
|
||||
|
||||
RemoveConnectionHeaders(forwardReq)
|
||||
utils.RemoveHeaders(forwardReq.Header, hopHeaders...)
|
||||
|
||||
forwardReq.Header = filterForwardRequestHeaders(forwardReq.Header, allowedHeaders)
|
||||
|
|
|
@ -554,8 +554,11 @@ func (p *Provider) resolveDefaultCertificate(ctx context.Context, domains []stri
|
|||
|
||||
p.resolvingDomainsMutex.Lock()
|
||||
|
||||
sort.Strings(domains)
|
||||
domainKey := strings.Join(domains, ",")
|
||||
sortedDomains := make([]string, len(domains))
|
||||
copy(sortedDomains, domains)
|
||||
sort.Strings(sortedDomains)
|
||||
|
||||
domainKey := strings.Join(sortedDomains, ",")
|
||||
|
||||
if _, ok := p.resolvingDomains[domainKey]; ok {
|
||||
p.resolvingDomainsMutex.Unlock()
|
||||
|
@ -955,12 +958,14 @@ func (p *Provider) certExists(validDomains []string) bool {
|
|||
p.certificatesMu.RLock()
|
||||
defer p.certificatesMu.RUnlock()
|
||||
|
||||
sort.Strings(validDomains)
|
||||
sortedDomains := make([]string, len(validDomains))
|
||||
copy(sortedDomains, validDomains)
|
||||
sort.Strings(sortedDomains)
|
||||
|
||||
for _, cert := range p.certificates {
|
||||
domains := cert.Certificate.Domain.ToStrArray()
|
||||
sort.Strings(domains)
|
||||
if reflect.DeepEqual(domains, validDomains) {
|
||||
if reflect.DeepEqual(domains, sortedDomains) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ import (
|
|||
"io/fs"
|
||||
)
|
||||
|
||||
// Files starting with . and _ are excluded by default
|
||||
//
|
||||
//go:embed static
|
||||
var assets embed.FS
|
||||
|
||||
|
|
|
@ -20,16 +20,13 @@
|
|||
"dependencies": {
|
||||
"@quasar/extras": "^1.16.12",
|
||||
"axios": "^1.7.4",
|
||||
"bowser": "^2.11.0",
|
||||
"chart.js": "^4.4.1",
|
||||
"core-js": "^3.35.1",
|
||||
"dot-prop": "^8.0.2",
|
||||
"iframe-resizer": "^4.3.9",
|
||||
"lodash.isequal": "4.5.0",
|
||||
"moment": "^2.30.1",
|
||||
"quasar": "^2.16.6",
|
||||
"query-string": "^8.1.0",
|
||||
"vh-check": "^2.0.5",
|
||||
"vue": "^3.0.0",
|
||||
"vue-chartjs": "^5.3.0",
|
||||
"vue-router": "^4.0.12",
|
||||
|
|
|
@ -13,9 +13,7 @@ module.exports = configure(function (ctx) {
|
|||
// app boot file (/src/boot)
|
||||
// --> boot files are part of "main.js"
|
||||
boot: [
|
||||
'api',
|
||||
'_hacks',
|
||||
'_init'
|
||||
'api'
|
||||
],
|
||||
|
||||
css: [
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
import iframeResize from 'iframe-resizer/js/iframeResizer'
|
||||
|
||||
const resize = {
|
||||
mounted (el, binding) {
|
||||
const options = binding.value || {}
|
||||
el.addEventListener('load', () => iframeResize(options, el))
|
||||
},
|
||||
unmounted (el) {
|
||||
const resizableEl = el
|
||||
if (resizableEl.iFrameResizer) {
|
||||
resizableEl.iFrameResizer.removeListeners()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default resize
|
|
@ -1,10 +0,0 @@
|
|||
import { APP } from '../_helpers/APP'
|
||||
import Boot from '../_middleware/Boot'
|
||||
|
||||
export default async ({ app, router, store }) => {
|
||||
app.use(Boot)
|
||||
|
||||
APP.root = app
|
||||
APP.router = router
|
||||
APP.store = store
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
import Bowser from 'bowser'
|
||||
import vhCheck from 'vh-check'
|
||||
|
||||
const browser = Bowser.getParser(window.navigator.userAgent)
|
||||
|
||||
// In Mobile
|
||||
if (browser.getPlatform().type === 'mobile') {
|
||||
vhCheck()
|
||||
}
|
||||
|
||||
export default async ({ app, Vue }) => {
|
||||
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
import { APP } from '../_helpers/APP'
|
||||
import errors from '../_helpers/Errors'
|
||||
import resize from '../_directives/resize'
|
||||
|
||||
export default async ({ app, router }) => {
|
||||
// Directives
|
||||
app.directive('resize', resize)
|
||||
|
||||
// Router
|
||||
// ----------------------------------------------
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
// Set APP
|
||||
APP.routeTo = to
|
||||
APP.routeFrom = from
|
||||
next()
|
||||
})
|
||||
|
||||
// Api (axios)
|
||||
// ----------------------------------------------
|
||||
APP.api.interceptors.request.use((config) => {
|
||||
console.log('interceptors -> config', config)
|
||||
// config.headers['Accept'] = '*/*'
|
||||
return config
|
||||
})
|
||||
|
||||
APP.api.interceptors.response.use((response) => {
|
||||
console.log('interceptors -> response', response)
|
||||
return response
|
||||
}, errors.handleResponse)
|
||||
}
|
|
@ -2267,11 +2267,6 @@ boolbase@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
|
||||
integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==
|
||||
|
||||
bowser@^2.11.0:
|
||||
version "2.11.0"
|
||||
resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f"
|
||||
integrity sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||
|
@ -3864,11 +3859,6 @@ ieee754@^1.1.13, ieee754@^1.2.1:
|
|||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
||||
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
|
||||
|
||||
iframe-resizer@^4.3.9:
|
||||
version "4.4.5"
|
||||
resolved "https://registry.yarnpkg.com/iframe-resizer/-/iframe-resizer-4.4.5.tgz#f5048636e7f2fb5d9a09cc2ae78eb2da55ad555c"
|
||||
integrity sha512-U8bCywf/Gh07O69RXo6dXAzTtODQrxaHGHRI7Nt4ipXsuq6EMxVsOP/jjaP43YtXz/ibESS0uSVDN3sOGCzSmw==
|
||||
|
||||
ignore@^5.2.0, ignore@^5.2.4:
|
||||
version "5.3.1"
|
||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef"
|
||||
|
@ -6007,11 +5997,6 @@ vary@~1.1.2:
|
|||
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
||||
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
|
||||
|
||||
vh-check@^2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/vh-check/-/vh-check-2.0.5.tgz#1b70610461e9776176f23d172daae3c4761aed09"
|
||||
integrity sha512-vHtIYWt9uLl2P2tLlatVpMwv9+ezuJCtMNjUVIpzd5Pa/dJXN8AtqkKmVRcNSlmXyCjkCkbMQX/Vs9axmdlfgg==
|
||||
|
||||
vite-jsconfig-paths@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/vite-jsconfig-paths/-/vite-jsconfig-paths-2.0.1.tgz#d66e36d67596dd8a8e4a6ed6e6db20debc50b45e"
|
||||
|
|
Loading…
Reference in a new issue