mirror of
https://github.com/containous/traefik.git
synced 2024-12-22 13:34:03 +03:00
Merge tag 'v1.4.4' into master
This commit is contained in:
commit
66591cf216
@ -36,6 +36,7 @@ deploy:
|
||||
on:
|
||||
repo: containous/traefik
|
||||
tags: true
|
||||
condition: ${TRAVIS_TAG} =~ ^v[0-9]+\.[0-9]+\.[0-9]+$
|
||||
- provider: releases
|
||||
api_key: ${GITHUB_TOKEN}
|
||||
file: dist/traefik*
|
||||
|
15
CHANGELOG.md
15
CHANGELOG.md
@ -1,5 +1,20 @@
|
||||
# Change Log
|
||||
|
||||
## [v1.4.4](https://github.com/containous/traefik/tree/v1.4.4) (2017-11-21)
|
||||
[All Commits](https://github.com/containous/traefik/compare/v1.4.3...v1.4.4)
|
||||
|
||||
**Enhancements:**
|
||||
- **[middleware]** Remove GzipHandler Fork ([#2436](https://github.com/containous/traefik/pull/2436) by [ldez](https://github.com/ldez))
|
||||
|
||||
**Bug fixes:**
|
||||
- **[docker]** Fix problems about duplicated and missing Docker backends/frontends. ([#2434](https://github.com/containous/traefik/pull/2434) by [nmengin](https://github.com/nmengin))
|
||||
- **[middleware]** Fix raw path handling in strip prefix ([#2382](https://github.com/containous/traefik/pull/2382) by [marco-jantke](https://github.com/marco-jantke))
|
||||
- **[rancher]** Fix issue with label traefik.backend.loadbalancer.stickiness.cookieName ([#2423](https://github.com/containous/traefik/pull/2423) by [rawmind0](https://github.com/rawmind0))
|
||||
- http.Server log goes to Debug level. ([#2420](https://github.com/containous/traefik/pull/2420) by [ldez](https://github.com/ldez))
|
||||
|
||||
**Documentation:**
|
||||
- Documentation archive ([#2405](https://github.com/containous/traefik/pull/2405) by [ldez](https://github.com/ldez))
|
||||
|
||||
## [v1.4.3](https://github.com/containous/traefik/tree/v1.4.3) (2017-11-14)
|
||||
[All Commits](https://github.com/containous/traefik/compare/v1.4.2...v1.4.3)
|
||||
|
||||
|
17
docs/archive.md
Normal file
17
docs/archive.md
Normal file
@ -0,0 +1,17 @@
|
||||
## Previous documentation
|
||||
|
||||
- [Latest stable](https://docs.traefik.io)
|
||||
|
||||
- [Experimental](https://master--traefik-docs.netlify.com/)
|
||||
|
||||
- [v1.4 aka Roquefort](http://v1-4.archive.docs.traefik.io/)
|
||||
|
||||
- [v1.3 aka Raclette](http://v1-3.archive.docs.traefik.io/)
|
||||
|
||||
- [v1.2 aka Morbier](http://v1-2.archive.docs.traefik.io/)
|
||||
|
||||
- [v1.1 aka Camembert](http://v1-1.archive.docs.traefik.io/)
|
||||
|
||||
## More
|
||||
|
||||
[Change log](https://github.com/containous/traefik/blob/master/CHANGELOG.md)
|
6
glide.lock
generated
6
glide.lock
generated
@ -1,4 +1,4 @@
|
||||
hash: fec4fec4363272870c49e10cea64cc51095ecd0987b9c020c9714d950cf38784
|
||||
hash: 6deb9adeca5f1724f9ef2b31b122f85a00cf47cf4308527d6d3ff68a6ac0e705
|
||||
updated: 2017-11-17T14:21:55.148450413+01:00
|
||||
imports:
|
||||
- name: cloud.google.com/go
|
||||
@ -420,9 +420,7 @@ imports:
|
||||
repo: https://github.com/ijc25/Gotty.git
|
||||
vcs: git
|
||||
- name: github.com/NYTimes/gziphandler
|
||||
version: 26a3f68265200656f31940bc15b191f7d10b5bbd
|
||||
repo: https://github.com/containous/gziphandler.git
|
||||
vcs: git
|
||||
version: d6f46609c7629af3a02d791a4666866eed3cbd3e
|
||||
- name: github.com/ogier/pflag
|
||||
version: 45c278ab3607870051a2ea9040bb85fcb8557481
|
||||
- name: github.com/opencontainers/go-digest
|
||||
|
@ -84,9 +84,6 @@ import:
|
||||
vcs: git
|
||||
- package: github.com/abbot/go-http-auth
|
||||
- package: github.com/NYTimes/gziphandler
|
||||
version: fork-containous
|
||||
repo: https://github.com/containous/gziphandler.git
|
||||
vcs: git
|
||||
- package: github.com/docker/leadership
|
||||
repo: https://github.com/containous/leadership.git
|
||||
vcs: git
|
||||
|
@ -16,8 +16,11 @@ type StripPrefix struct {
|
||||
|
||||
func (s *StripPrefix) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
for _, prefix := range s.Prefixes {
|
||||
if p := strings.TrimPrefix(r.URL.Path, prefix); len(p) < len(r.URL.Path) {
|
||||
r.URL.Path = "/" + strings.TrimPrefix(p, "/")
|
||||
if strings.HasPrefix(r.URL.Path, prefix) {
|
||||
r.URL.Path = stripPrefix(r.URL.Path, prefix)
|
||||
if r.URL.RawPath != "" {
|
||||
r.URL.RawPath = stripPrefix(r.URL.RawPath, prefix)
|
||||
}
|
||||
s.serveRequest(w, r, strings.TrimSpace(prefix))
|
||||
return
|
||||
}
|
||||
@ -35,3 +38,11 @@ func (s *StripPrefix) serveRequest(w http.ResponseWriter, r *http.Request, prefi
|
||||
func (s *StripPrefix) SetHandler(Handler http.Handler) {
|
||||
s.Handler = Handler
|
||||
}
|
||||
|
||||
func stripPrefix(s, prefix string) string {
|
||||
return ensureLeadingSlash(strings.TrimPrefix(s, prefix))
|
||||
}
|
||||
|
||||
func ensureLeadingSlash(str string) string {
|
||||
return "/" + strings.TrimPrefix(str, "/")
|
||||
}
|
||||
|
@ -40,6 +40,9 @@ func (s *StripPrefixRegex) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
r.URL.Path = r.URL.Path[len(prefix.Path):]
|
||||
if r.URL.RawPath != "" {
|
||||
r.URL.RawPath = r.URL.RawPath[len(prefix.Path):]
|
||||
}
|
||||
r.Header.Add(ForwardedPrefixHeader, prefix.Path)
|
||||
r.RequestURI = r.URL.RequestURI()
|
||||
s.Handler.ServeHTTP(w, r)
|
||||
|
@ -10,13 +10,13 @@ import (
|
||||
)
|
||||
|
||||
func TestStripPrefixRegex(t *testing.T) {
|
||||
|
||||
testPrefixRegex := []string{"/a/api/", "/b/{regex}/", "/c/{category}/{id:[0-9]+}/"}
|
||||
|
||||
tests := []struct {
|
||||
path string
|
||||
expectedStatusCode int
|
||||
expectedPath string
|
||||
expectedRawPath string
|
||||
expectedHeader string
|
||||
}{
|
||||
{
|
||||
@ -61,6 +61,13 @@ func TestStripPrefixRegex(t *testing.T) {
|
||||
path: "/c/api/abc/test4",
|
||||
expectedStatusCode: http.StatusNotFound,
|
||||
},
|
||||
{
|
||||
path: "/a/api/a%2Fb",
|
||||
expectedStatusCode: http.StatusOK,
|
||||
expectedPath: "a/b",
|
||||
expectedRawPath: "a%2Fb",
|
||||
expectedHeader: "/a/api/",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
@ -68,9 +75,10 @@ func TestStripPrefixRegex(t *testing.T) {
|
||||
t.Run(test.path, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var actualPath, actualHeader string
|
||||
var actualPath, actualRawPath, actualHeader string
|
||||
handlerPath := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
actualPath = r.URL.Path
|
||||
actualRawPath = r.URL.RawPath
|
||||
actualHeader = r.Header.Get(ForwardedPrefixHeader)
|
||||
})
|
||||
handler := NewStripPrefixRegex(handlerPath, testPrefixRegex)
|
||||
@ -82,6 +90,7 @@ func TestStripPrefixRegex(t *testing.T) {
|
||||
|
||||
assert.Equal(t, test.expectedStatusCode, resp.Code, "Unexpected status code.")
|
||||
assert.Equal(t, test.expectedPath, actualPath, "Unexpected path.")
|
||||
assert.Equal(t, test.expectedRawPath, actualRawPath, "Unexpected raw path.")
|
||||
assert.Equal(t, test.expectedHeader, actualHeader, "Unexpected '%s' header.", ForwardedPrefixHeader)
|
||||
})
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ func TestStripPrefix(t *testing.T) {
|
||||
path string
|
||||
expectedStatusCode int
|
||||
expectedPath string
|
||||
expectedRawPath string
|
||||
expectedHeader string
|
||||
}{
|
||||
{
|
||||
@ -94,6 +95,15 @@ func TestStripPrefix(t *testing.T) {
|
||||
expectedPath: "/us",
|
||||
expectedHeader: "/stat",
|
||||
},
|
||||
{
|
||||
desc: "raw path is also stripped",
|
||||
prefixes: []string{"/stat"},
|
||||
path: "/stat/a%2Fb",
|
||||
expectedStatusCode: http.StatusOK,
|
||||
expectedPath: "/a/b",
|
||||
expectedRawPath: "/a%2Fb",
|
||||
expectedHeader: "/stat",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
@ -101,11 +111,12 @@ func TestStripPrefix(t *testing.T) {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var actualPath, actualHeader, requestURI string
|
||||
var actualPath, actualRawPath, actualHeader, requestURI string
|
||||
handler := &StripPrefix{
|
||||
Prefixes: test.prefixes,
|
||||
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
actualPath = r.URL.Path
|
||||
actualRawPath = r.URL.RawPath
|
||||
actualHeader = r.Header.Get(ForwardedPrefixHeader)
|
||||
requestURI = r.RequestURI
|
||||
}),
|
||||
@ -118,8 +129,15 @@ func TestStripPrefix(t *testing.T) {
|
||||
|
||||
assert.Equal(t, test.expectedStatusCode, resp.Code, "Unexpected status code.")
|
||||
assert.Equal(t, test.expectedPath, actualPath, "Unexpected path.")
|
||||
assert.Equal(t, test.expectedRawPath, actualRawPath, "Unexpected raw path.")
|
||||
assert.Equal(t, test.expectedHeader, actualHeader, "Unexpected '%s' header.", ForwardedPrefixHeader)
|
||||
assert.Equal(t, test.expectedPath, requestURI, "Unexpected request URI.")
|
||||
|
||||
expectedURI := test.expectedPath
|
||||
if test.expectedRawPath != "" {
|
||||
// go HTTP uses the raw path when existent in the RequestURI
|
||||
expectedURI = test.expectedRawPath
|
||||
}
|
||||
assert.Equal(t, expectedURI, requestURI, "Unexpected request URI.")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -100,3 +100,4 @@ pages:
|
||||
- 'Clustering/HA': 'user-guide/cluster.md'
|
||||
- 'gRPC Example': 'user-guide/grpc.md'
|
||||
- Benchmarks: benchmarks.md
|
||||
- 'Archive': 'archive.md'
|
||||
|
@ -345,9 +345,15 @@ func (p *Provider) loadDockerConfig(containersInspected []dockerData) *types.Con
|
||||
frontends := map[string][]dockerData{}
|
||||
backends := map[string]dockerData{}
|
||||
servers := map[string][]dockerData{}
|
||||
serviceNames := make(map[string]struct{})
|
||||
for idx, container := range filteredContainers {
|
||||
frontendName := p.getFrontendName(container, idx)
|
||||
frontends[frontendName] = append(frontends[frontendName], container)
|
||||
if _, exists := serviceNames[container.ServiceName]; !exists {
|
||||
frontendName := p.getFrontendName(container, idx)
|
||||
frontends[frontendName] = append(frontends[frontendName], container)
|
||||
if len(container.ServiceName) > 0 {
|
||||
serviceNames[container.ServiceName] = struct{}{}
|
||||
}
|
||||
}
|
||||
backendName := p.getBackend(container)
|
||||
backends[backendName] = container
|
||||
servers[backendName] = append(servers[backendName], container)
|
||||
@ -471,9 +477,9 @@ func (p *Provider) getServicePriority(container dockerData, serviceName string)
|
||||
// Extract backend from labels for a given service and a given docker container
|
||||
func (p *Provider) getServiceBackend(container dockerData, serviceName string) string {
|
||||
if value, ok := getContainerServiceLabel(container, serviceName, "frontend.backend"); ok {
|
||||
return value
|
||||
return container.ServiceName + "-" + value
|
||||
}
|
||||
return p.getBackend(container) + "-" + provider.Normalize(serviceName)
|
||||
return strings.TrimPrefix(container.ServiceName, "/") + "-" + p.getBackend(container) + "-" + provider.Normalize(serviceName)
|
||||
}
|
||||
|
||||
// Extract rule from labels for a given service and a given docker container
|
||||
|
@ -171,19 +171,19 @@ func TestDockerGetServiceBackend(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
container: containerJSON(name("foo")),
|
||||
expected: "foo-myservice",
|
||||
expected: "foo-foo-myservice",
|
||||
},
|
||||
{
|
||||
container: containerJSON(labels(map[string]string{
|
||||
types.LabelBackend: "another-backend",
|
||||
})),
|
||||
expected: "another-backend-myservice",
|
||||
expected: "fake-another-backend-myservice",
|
||||
},
|
||||
{
|
||||
container: containerJSON(labels(map[string]string{
|
||||
"traefik.myservice.frontend.backend": "custom-backend",
|
||||
})),
|
||||
expected: "custom-backend",
|
||||
expected: "fake-custom-backend",
|
||||
},
|
||||
}
|
||||
|
||||
@ -342,8 +342,8 @@ func TestDockerLoadDockerServiceConfig(t *testing.T) {
|
||||
),
|
||||
},
|
||||
expectedFrontends: map[string]*types.Frontend{
|
||||
"frontend-foo-service": {
|
||||
Backend: "backend-foo-service",
|
||||
"frontend-foo-foo-service": {
|
||||
Backend: "backend-foo-foo-service",
|
||||
PassHostHeader: true,
|
||||
EntryPoints: []string{"http", "https"},
|
||||
BasicAuth: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"},
|
||||
@ -356,7 +356,7 @@ func TestDockerLoadDockerServiceConfig(t *testing.T) {
|
||||
},
|
||||
},
|
||||
expectedBackends: map[string]*types.Backend{
|
||||
"backend-foo-service": {
|
||||
"backend-foo-foo-service": {
|
||||
Servers: map[string]types.Server{
|
||||
"service-0": {
|
||||
URL: "http://127.0.0.1:2503",
|
||||
@ -402,8 +402,8 @@ func TestDockerLoadDockerServiceConfig(t *testing.T) {
|
||||
),
|
||||
},
|
||||
expectedFrontends: map[string]*types.Frontend{
|
||||
"frontend-foobar": {
|
||||
Backend: "backend-foobar",
|
||||
"frontend-test1-foobar": {
|
||||
Backend: "backend-test1-foobar",
|
||||
PassHostHeader: false,
|
||||
Priority: 5000,
|
||||
EntryPoints: []string{"http", "https", "ws"},
|
||||
@ -415,8 +415,8 @@ func TestDockerLoadDockerServiceConfig(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
"frontend-test2-anotherservice": {
|
||||
Backend: "backend-test2-anotherservice",
|
||||
"frontend-test2-test2-anotherservice": {
|
||||
Backend: "backend-test2-test2-anotherservice",
|
||||
PassHostHeader: true,
|
||||
EntryPoints: []string{},
|
||||
BasicAuth: []string{},
|
||||
@ -429,7 +429,7 @@ func TestDockerLoadDockerServiceConfig(t *testing.T) {
|
||||
},
|
||||
},
|
||||
expectedBackends: map[string]*types.Backend{
|
||||
"backend-foobar": {
|
||||
"backend-test1-foobar": {
|
||||
Servers: map[string]types.Server{
|
||||
"service-0": {
|
||||
URL: "https://127.0.0.1:2503",
|
||||
@ -438,7 +438,7 @@ func TestDockerLoadDockerServiceConfig(t *testing.T) {
|
||||
},
|
||||
CircuitBreaker: nil,
|
||||
},
|
||||
"backend-test2-anotherservice": {
|
||||
"backend-test2-test2-anotherservice": {
|
||||
Servers: map[string]types.Server{
|
||||
"service-0": {
|
||||
URL: "http://127.0.0.1:8079",
|
||||
|
@ -133,7 +133,7 @@ func (p *Provider) hasStickinessLabel(service rancherData) bool {
|
||||
return errStickiness == nil && len(labelStickiness) > 0 && strings.EqualFold(strings.TrimSpace(labelStickiness), "true")
|
||||
}
|
||||
|
||||
func (p *Provider) getStickinessCookieName(service rancherData, backendName string) string {
|
||||
func (p *Provider) getStickinessCookieName(service rancherData) string {
|
||||
if label, err := getServiceLabel(service, types.LabelBackendLoadbalancerStickinessCookieName); err == nil {
|
||||
return label
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
stdlog "log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@ -20,6 +21,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/armon/go-proxyproto"
|
||||
"github.com/containous/mux"
|
||||
"github.com/containous/traefik/cluster"
|
||||
@ -47,6 +49,10 @@ import (
|
||||
"golang.org/x/net/http2"
|
||||
)
|
||||
|
||||
var (
|
||||
httpServerLogger = stdlog.New(log.WriterLevel(logrus.DebugLevel), "", 0)
|
||||
)
|
||||
|
||||
// Server is the reverse-proxy/load-balancer engine
|
||||
type Server struct {
|
||||
serverEntryPoints serverEntryPoints
|
||||
@ -794,6 +800,7 @@ func (server *Server) prepareServer(entryPointName string, entryPoint *configura
|
||||
ReadTimeout: readTimeout,
|
||||
WriteTimeout: writeTimeout,
|
||||
IdleTimeout: idleTimeout,
|
||||
ErrorLog: httpServerLogger,
|
||||
},
|
||||
listener,
|
||||
nil
|
||||
|
Loading…
Reference in New Issue
Block a user