httpcaddyfile: Prevent error handler from overriding sub-handler matchers (#6999)
Fixes: #6957pull/6772/head^2
parent
7099892958
commit
092913a7a5
|
@ -15,6 +15,7 @@
|
||||||
package httpcaddyfile
|
package httpcaddyfile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html"
|
"html"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -843,13 +844,18 @@ func parseHandleErrors(h Helper) ([]ConfigValue, error) {
|
||||||
return nil, h.Errf("segment was not parsed as a subroute")
|
return nil, h.Errf("segment was not parsed as a subroute")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// wrap the subroutes
|
||||||
|
wrappingRoute := caddyhttp.Route{
|
||||||
|
HandlersRaw: []json.RawMessage{caddyconfig.JSONModuleObject(subroute, "handler", "subroute", nil)},
|
||||||
|
}
|
||||||
|
subroute = &caddyhttp.Subroute{
|
||||||
|
Routes: []caddyhttp.Route{wrappingRoute},
|
||||||
|
}
|
||||||
if expression != "" {
|
if expression != "" {
|
||||||
statusMatcher := caddy.ModuleMap{
|
statusMatcher := caddy.ModuleMap{
|
||||||
"expression": h.JSON(caddyhttp.MatchExpression{Expr: expression}),
|
"expression": h.JSON(caddyhttp.MatchExpression{Expr: expression}),
|
||||||
}
|
}
|
||||||
for i := range subroute.Routes {
|
subroute.Routes[0].MatcherSetsRaw = []caddy.ModuleMap{statusMatcher}
|
||||||
subroute.Routes[i].MatcherSetsRaw = []caddy.ModuleMap{statusMatcher}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return []ConfigValue{
|
return []ConfigValue{
|
||||||
{
|
{
|
||||||
|
|
|
@ -106,20 +106,29 @@ example.com {
|
||||||
"handler": "subroute",
|
"handler": "subroute",
|
||||||
"routes": [
|
"routes": [
|
||||||
{
|
{
|
||||||
"group": "group0",
|
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"handler": "rewrite",
|
"handler": "subroute",
|
||||||
"uri": "/{http.error.status_code}.html"
|
"routes": [
|
||||||
}
|
{
|
||||||
]
|
"group": "group0",
|
||||||
},
|
"handle": [
|
||||||
{
|
{
|
||||||
"handle": [
|
"handler": "rewrite",
|
||||||
{
|
"uri": "/{http.error.status_code}.html"
|
||||||
"handler": "file_server",
|
}
|
||||||
"hide": [
|
]
|
||||||
"./Caddyfile"
|
},
|
||||||
|
{
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"handler": "file_server",
|
||||||
|
"hide": [
|
||||||
|
"./Caddyfile"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -165,8 +165,17 @@ bar.localhost {
|
||||||
{
|
{
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"body": "404 or 410 error",
|
"handler": "subroute",
|
||||||
"handler": "static_response"
|
"routes": [
|
||||||
|
{
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"body": "404 or 410 error",
|
||||||
|
"handler": "static_response"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"match": [
|
"match": [
|
||||||
|
@ -178,8 +187,17 @@ bar.localhost {
|
||||||
{
|
{
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"body": "Error In range [500 .. 599]",
|
"handler": "subroute",
|
||||||
"handler": "static_response"
|
"routes": [
|
||||||
|
{
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"body": "Error In range [500 .. 599]",
|
||||||
|
"handler": "static_response"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"match": [
|
"match": [
|
||||||
|
@ -208,8 +226,17 @@ bar.localhost {
|
||||||
{
|
{
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"body": "404 or 410 error from second site",
|
"handler": "subroute",
|
||||||
"handler": "static_response"
|
"routes": [
|
||||||
|
{
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"body": "404 or 410 error from second site",
|
||||||
|
"handler": "static_response"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"match": [
|
"match": [
|
||||||
|
@ -221,8 +248,17 @@ bar.localhost {
|
||||||
{
|
{
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"body": "Error In range [500 .. 599] from second site",
|
"handler": "subroute",
|
||||||
"handler": "static_response"
|
"routes": [
|
||||||
|
{
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"body": "Error In range [500 .. 599] from second site",
|
||||||
|
"handler": "static_response"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"match": [
|
"match": [
|
||||||
|
|
|
@ -96,8 +96,17 @@ localhost:3010 {
|
||||||
{
|
{
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"body": "Error in the [400 .. 499] range",
|
"handler": "subroute",
|
||||||
"handler": "static_response"
|
"routes": [
|
||||||
|
{
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"body": "Error in the [400 .. 499] range",
|
||||||
|
"handler": "static_response"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"match": [
|
"match": [
|
||||||
|
|
|
@ -116,8 +116,17 @@ localhost:2099 {
|
||||||
{
|
{
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"body": "Error in the [400 .. 499] range",
|
"handler": "subroute",
|
||||||
"handler": "static_response"
|
"routes": [
|
||||||
|
{
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"body": "Error in the [400 .. 499] range",
|
||||||
|
"handler": "static_response"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"match": [
|
"match": [
|
||||||
|
@ -129,8 +138,17 @@ localhost:2099 {
|
||||||
{
|
{
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"body": "Error code is equal to 500 or in the [300..399] range",
|
"handler": "subroute",
|
||||||
"handler": "static_response"
|
"routes": [
|
||||||
|
{
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"body": "Error code is equal to 500 or in the [300..399] range",
|
||||||
|
"handler": "static_response"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"match": [
|
"match": [
|
||||||
|
|
|
@ -96,8 +96,17 @@ localhost:3010 {
|
||||||
{
|
{
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"body": "404 or 410 error",
|
"handler": "subroute",
|
||||||
"handler": "static_response"
|
"routes": [
|
||||||
|
{
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"body": "404 or 410 error",
|
||||||
|
"handler": "static_response"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"match": [
|
"match": [
|
||||||
|
|
|
@ -116,8 +116,17 @@ localhost:2099 {
|
||||||
{
|
{
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"body": "Error in the [400 .. 499] range",
|
"handler": "subroute",
|
||||||
"handler": "static_response"
|
"routes": [
|
||||||
|
{
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"body": "Error in the [400 .. 499] range",
|
||||||
|
"handler": "static_response"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"match": [
|
"match": [
|
||||||
|
@ -129,8 +138,17 @@ localhost:2099 {
|
||||||
{
|
{
|
||||||
"handle": [
|
"handle": [
|
||||||
{
|
{
|
||||||
"body": "Fallback route: code outside the [400..499] range",
|
"handler": "subroute",
|
||||||
"handler": "static_response"
|
"routes": [
|
||||||
|
{
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"body": "Fallback route: code outside the [400..499] range",
|
||||||
|
"handler": "static_response"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,260 @@
|
||||||
|
{
|
||||||
|
http_port 2099
|
||||||
|
}
|
||||||
|
localhost:2099 {
|
||||||
|
root * /var/www/
|
||||||
|
file_server
|
||||||
|
|
||||||
|
handle_errors 404 {
|
||||||
|
handle /en/* {
|
||||||
|
respond "not found" 404
|
||||||
|
}
|
||||||
|
handle /es/* {
|
||||||
|
respond "no encontrado"
|
||||||
|
}
|
||||||
|
handle {
|
||||||
|
respond "default not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handle_errors {
|
||||||
|
handle /en/* {
|
||||||
|
respond "English error"
|
||||||
|
}
|
||||||
|
handle /es/* {
|
||||||
|
respond "Spanish error"
|
||||||
|
}
|
||||||
|
handle {
|
||||||
|
respond "Default error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
----------
|
||||||
|
{
|
||||||
|
"apps": {
|
||||||
|
"http": {
|
||||||
|
"http_port": 2099,
|
||||||
|
"servers": {
|
||||||
|
"srv0": {
|
||||||
|
"listen": [
|
||||||
|
":2099"
|
||||||
|
],
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"match": [
|
||||||
|
{
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"handler": "subroute",
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"handler": "vars",
|
||||||
|
"root": "/var/www/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"handler": "file_server",
|
||||||
|
"hide": [
|
||||||
|
"./Caddyfile"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"terminal": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"errors": {
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"match": [
|
||||||
|
{
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"handler": "subroute",
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"handler": "subroute",
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"group": "group3",
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"handler": "subroute",
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"body": "not found",
|
||||||
|
"handler": "static_response",
|
||||||
|
"status_code": 404
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"match": [
|
||||||
|
{
|
||||||
|
"path": [
|
||||||
|
"/en/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "group3",
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"handler": "subroute",
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"body": "no encontrado",
|
||||||
|
"handler": "static_response"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"match": [
|
||||||
|
{
|
||||||
|
"path": [
|
||||||
|
"/es/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "group3",
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"handler": "subroute",
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"body": "default not found",
|
||||||
|
"handler": "static_response"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"match": [
|
||||||
|
{
|
||||||
|
"expression": "{http.error.status_code} in [404]"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"handler": "subroute",
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"group": "group8",
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"handler": "subroute",
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"body": "English error",
|
||||||
|
"handler": "static_response"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"match": [
|
||||||
|
{
|
||||||
|
"path": [
|
||||||
|
"/en/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "group8",
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"handler": "subroute",
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"body": "Spanish error",
|
||||||
|
"handler": "static_response"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"match": [
|
||||||
|
{
|
||||||
|
"path": [
|
||||||
|
"/es/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "group8",
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"handler": "subroute",
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"handle": [
|
||||||
|
{
|
||||||
|
"body": "Default error",
|
||||||
|
"handler": "static_response"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"terminal": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -782,6 +782,46 @@ func TestHandleErrorRangeAndCodes(t *testing.T) {
|
||||||
tester.AssertGetResponse("http://localhost:9080/private", 410, "Error in the [400 .. 499] range")
|
tester.AssertGetResponse("http://localhost:9080/private", 410, "Error in the [400 .. 499] range")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHandleErrorSubHandlers(t *testing.T) {
|
||||||
|
tester := caddytest.NewTester(t)
|
||||||
|
tester.InitServer(`{
|
||||||
|
admin localhost:2999
|
||||||
|
http_port 9080
|
||||||
|
}
|
||||||
|
localhost:9080 {
|
||||||
|
root * /srv
|
||||||
|
file_server
|
||||||
|
error /*/internalerr* "Internal Server Error" 500
|
||||||
|
|
||||||
|
handle_errors 404 {
|
||||||
|
handle /en/* {
|
||||||
|
respond "not found" 404
|
||||||
|
}
|
||||||
|
handle /es/* {
|
||||||
|
respond "no encontrado" 404
|
||||||
|
}
|
||||||
|
handle {
|
||||||
|
respond "default not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handle_errors {
|
||||||
|
handle {
|
||||||
|
respond "Default error"
|
||||||
|
}
|
||||||
|
handle /en/* {
|
||||||
|
respond "English error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`, "caddyfile")
|
||||||
|
// act and assert
|
||||||
|
tester.AssertGetResponse("http://localhost:9080/en/notfound", 404, "not found")
|
||||||
|
tester.AssertGetResponse("http://localhost:9080/es/notfound", 404, "no encontrado")
|
||||||
|
tester.AssertGetResponse("http://localhost:9080/notfound", 404, "default not found")
|
||||||
|
tester.AssertGetResponse("http://localhost:9080/es/internalerr", 500, "Default error")
|
||||||
|
tester.AssertGetResponse("http://localhost:9080/en/internalerr", 500, "English error")
|
||||||
|
}
|
||||||
|
|
||||||
func TestInvalidSiteAddressesAsDirectives(t *testing.T) {
|
func TestInvalidSiteAddressesAsDirectives(t *testing.T) {
|
||||||
type testCase struct {
|
type testCase struct {
|
||||||
config, expectedError string
|
config, expectedError string
|
||||||
|
|
Loading…
Reference in New Issue