Support URL replacement in errors middleware
This commit is contained in:
parent
7d274e8088
commit
ae6e844143
3 changed files with 51 additions and 23 deletions
|
@ -1,16 +1,16 @@
|
||||||
---
|
---
|
||||||
title: "Traefik ErrorPage Documentation"
|
title: "Traefik Errors Documentation"
|
||||||
description: "In Traefik Proxy, the ErrorPage middleware returns custom pages according to configured ranges of HTTP Status codes. Read the technical documentation."
|
description: "In Traefik Proxy, the Errors middleware returns custom pages according to configured ranges of HTTP Status codes. Read the technical documentation."
|
||||||
---
|
---
|
||||||
|
|
||||||
# ErrorPage
|
# Errors
|
||||||
|
|
||||||
It Has Never Been Easier to Say That Something Went Wrong
|
It Has Never Been Easier to Say That Something Went Wrong
|
||||||
{: .subtitle }
|
{: .subtitle }
|
||||||
|
|
||||||
![ErrorPages](../../assets/img/middleware/errorpages.png)
|
![Errors](../../assets/img/middleware/errorpages.png)
|
||||||
|
|
||||||
The ErrorPage middleware returns a custom page in lieu of the default, according to configured ranges of HTTP Status codes.
|
The Errors middleware returns a custom page in lieu of the default, according to configured ranges of HTTP Status codes.
|
||||||
|
|
||||||
!!! important
|
!!! important
|
||||||
|
|
||||||
|
@ -21,16 +21,16 @@ The ErrorPage middleware returns a custom page in lieu of the default, according
|
||||||
```yaml tab="Docker"
|
```yaml tab="Docker"
|
||||||
# Dynamic Custom Error Page for 5XX Status Code
|
# Dynamic Custom Error Page for 5XX Status Code
|
||||||
labels:
|
labels:
|
||||||
- "traefik.http.middlewares.test-errorpage.errors.status=500-599"
|
- "traefik.http.middlewares.test-errors.errors.status=500-599"
|
||||||
- "traefik.http.middlewares.test-errorpage.errors.service=serviceError"
|
- "traefik.http.middlewares.test-errors.errors.service=serviceError"
|
||||||
- "traefik.http.middlewares.test-errorpage.errors.query=/{status}.html"
|
- "traefik.http.middlewares.test-errors.errors.query=/{status}.html"
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml tab="Kubernetes"
|
```yaml tab="Kubernetes"
|
||||||
apiVersion: traefik.containo.us/v1alpha1
|
apiVersion: traefik.containo.us/v1alpha1
|
||||||
kind: Middleware
|
kind: Middleware
|
||||||
metadata:
|
metadata:
|
||||||
name: test-errorpage
|
name: test-errors
|
||||||
spec:
|
spec:
|
||||||
errors:
|
errors:
|
||||||
status:
|
status:
|
||||||
|
@ -43,32 +43,32 @@ spec:
|
||||||
|
|
||||||
```yaml tab="Consul Catalog"
|
```yaml tab="Consul Catalog"
|
||||||
# Dynamic Custom Error Page for 5XX Status Code
|
# Dynamic Custom Error Page for 5XX Status Code
|
||||||
- "traefik.http.middlewares.test-errorpage.errors.status=500-599"
|
- "traefik.http.middlewares.test-errors.errors.status=500-599"
|
||||||
- "traefik.http.middlewares.test-errorpage.errors.service=serviceError"
|
- "traefik.http.middlewares.test-errors.errors.service=serviceError"
|
||||||
- "traefik.http.middlewares.test-errorpage.errors.query=/{status}.html"
|
- "traefik.http.middlewares.test-errors.errors.query=/{status}.html"
|
||||||
```
|
```
|
||||||
|
|
||||||
```json tab="Marathon"
|
```json tab="Marathon"
|
||||||
"labels": {
|
"labels": {
|
||||||
"traefik.http.middlewares.test-errorpage.errors.status": "500-599",
|
"traefik.http.middlewares.test-errors.errors.status": "500-599",
|
||||||
"traefik.http.middlewares.test-errorpage.errors.service": "serviceError",
|
"traefik.http.middlewares.test-errors.errors.service": "serviceError",
|
||||||
"traefik.http.middlewares.test-errorpage.errors.query": "/{status}.html"
|
"traefik.http.middlewares.test-errors.errors.query": "/{status}.html"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml tab="Rancher"
|
```yaml tab="Rancher"
|
||||||
# Dynamic Custom Error Page for 5XX Status Code
|
# Dynamic Custom Error Page for 5XX Status Code
|
||||||
labels:
|
labels:
|
||||||
- "traefik.http.middlewares.test-errorpage.errors.status=500-599"
|
- "traefik.http.middlewares.test-errors.errors.status=500-599"
|
||||||
- "traefik.http.middlewares.test-errorpage.errors.service=serviceError"
|
- "traefik.http.middlewares.test-errors.errors.service=serviceError"
|
||||||
- "traefik.http.middlewares.test-errorpage.errors.query=/{status}.html"
|
- "traefik.http.middlewares.test-errors.errors.query=/{status}.html"
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml tab="File (YAML)"
|
```yaml tab="File (YAML)"
|
||||||
# Custom Error Page for 5XX
|
# Custom Error Page for 5XX
|
||||||
http:
|
http:
|
||||||
middlewares:
|
middlewares:
|
||||||
test-errorpage:
|
test-errors:
|
||||||
errors:
|
errors:
|
||||||
status:
|
status:
|
||||||
- "500-599"
|
- "500-599"
|
||||||
|
@ -82,7 +82,7 @@ http:
|
||||||
```toml tab="File (TOML)"
|
```toml tab="File (TOML)"
|
||||||
# Custom Error Page for 5XX
|
# Custom Error Page for 5XX
|
||||||
[http.middlewares]
|
[http.middlewares]
|
||||||
[http.middlewares.test-errorpage.errors]
|
[http.middlewares.test-errors.errors]
|
||||||
status = ["500-599"]
|
status = ["500-599"]
|
||||||
service = "serviceError"
|
service = "serviceError"
|
||||||
query = "/{status}.html"
|
query = "/{status}.html"
|
||||||
|
@ -125,4 +125,13 @@ The service that will serve the new requested error page.
|
||||||
|
|
||||||
### `query`
|
### `query`
|
||||||
|
|
||||||
The URL for the error page (hosted by `service`). You can use the `{status}` variable in the `query` option in order to insert the status code in the URL.
|
The URL for the error page (hosted by [`service`](#service))).
|
||||||
|
|
||||||
|
There are multiple variables that can be placed in the `query` option to insert values in the URL.
|
||||||
|
|
||||||
|
The table below lists all the available variables and their associated values.
|
||||||
|
|
||||||
|
| Variable | Value |
|
||||||
|
|------------|--------------------------------------------------------------------|
|
||||||
|
| `{status}` | The response status code. |
|
||||||
|
| `{url}` | The [escaped](https://pkg.go.dev/net/url#QueryEscape) request URL. |
|
||||||
|
|
|
@ -93,6 +93,7 @@ func (c *customErrors) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
if len(c.backendQuery) > 0 {
|
if len(c.backendQuery) > 0 {
|
||||||
query = "/" + strings.TrimPrefix(c.backendQuery, "/")
|
query = "/" + strings.TrimPrefix(c.backendQuery, "/")
|
||||||
query = strings.ReplaceAll(query, "{status}", strconv.Itoa(code))
|
query = strings.ReplaceAll(query, "{status}", strconv.Itoa(code))
|
||||||
|
query = strings.ReplaceAll(query, "{url}", url.QueryEscape(req.URL.String()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pageReq, err := newRequest("http://" + req.Host + query)
|
pageReq, err := newRequest("http://" + req.Host + query)
|
||||||
|
|
|
@ -133,6 +133,24 @@ func TestHandler(t *testing.T) {
|
||||||
assert.Contains(t, recorder.Body.String(), "localhost")
|
assert.Contains(t, recorder.Body.String(), "localhost")
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "full query replacement",
|
||||||
|
errorPage: &dynamic.ErrorPage{Service: "error", Query: "/?status={status}&url={url}", Status: []string{"503"}},
|
||||||
|
backendCode: http.StatusServiceUnavailable,
|
||||||
|
backendErrorHandler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.RequestURI != "/?status=503&url=http%3A%2F%2Flocalhost%2Ftest%3Ffoo%3Dbar%26baz%3Dbuz" {
|
||||||
|
t.Log(r.RequestURI)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _ = fmt.Fprintln(w, "My 503 page.")
|
||||||
|
}),
|
||||||
|
validate: func(t *testing.T, recorder *httptest.ResponseRecorder) {
|
||||||
|
t.Helper()
|
||||||
|
assert.Equal(t, http.StatusServiceUnavailable, recorder.Code, "HTTP status")
|
||||||
|
assert.Contains(t, recorder.Body.String(), "My 503 page.")
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
|
@ -153,7 +171,7 @@ func TestHandler(t *testing.T) {
|
||||||
errorPageHandler, err := New(context.Background(), handler, *test.errorPage, serviceBuilderMock, "test")
|
errorPageHandler, err := New(context.Background(), handler, *test.errorPage, serviceBuilderMock, "test")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
req := testhelpers.MustNewRequest(http.MethodGet, "http://localhost/test", nil)
|
req := testhelpers.MustNewRequest(http.MethodGet, "http://localhost/test?foo=bar&baz=buz", nil)
|
||||||
|
|
||||||
recorder := httptest.NewRecorder()
|
recorder := httptest.NewRecorder()
|
||||||
errorPageHandler.ServeHTTP(recorder, req)
|
errorPageHandler.ServeHTTP(recorder, req)
|
||||||
|
|
Loading…
Reference in a new issue