From 4f0b4eab94c93bb20779836b6a5fbc14a2d36f28 Mon Sep 17 00:00:00 2001 From: armadi1809 Date: Thu, 7 Dec 2023 22:43:44 -0600 Subject: [PATCH] Added tests to the handle_error directive --- caddyconfig/httpcaddyfile/builtins.go | 8 +- caddyconfig/httpcaddyfile/httptype.go | 3 + .../caddyfile_adapt/error_range_codes.txt | 113 +++++++++++++ .../error_range_simple_codes.txt | 156 +++++++++++++++++ .../caddyfile_adapt/error_simple_codes.txt | 113 +++++++++++++ .../caddyfile_adapt/error_sort.txt | 158 ++++++++++++++++++ caddytest/integration/caddyfile_test.go | 88 ++++++++++ 7 files changed, 634 insertions(+), 5 deletions(-) create mode 100644 caddytest/integration/caddyfile_adapt/error_range_codes.txt create mode 100644 caddytest/integration/caddyfile_adapt/error_range_simple_codes.txt create mode 100644 caddytest/integration/caddyfile_adapt/error_simple_codes.txt create mode 100644 caddytest/integration/caddyfile_adapt/error_sort.txt diff --git a/caddyconfig/httpcaddyfile/builtins.go b/caddyconfig/httpcaddyfile/builtins.go index 7d86c52cdd7..2f44862dcf9 100644 --- a/caddyconfig/httpcaddyfile/builtins.go +++ b/caddyconfig/httpcaddyfile/builtins.go @@ -844,7 +844,6 @@ func parseHandle(h Helper) (caddyhttp.MiddlewareHandler, error) { } func parseHandleErrors(h Helper) ([]ConfigValue, error) { - h.Next() args := h.RemainingArgs() expression := "" @@ -865,17 +864,16 @@ func parseHandleErrors(h Helper) ([]ConfigValue, error) { if len(codes) > 0 { if expression != "" { expression += " || " - } else { - expression += "{http.error.status_code} in [" + strings.Join(codes, ", ") + "]" } + expression += "{http.error.status_code} in [" + strings.Join(codes, ", ") + "]" } - //Reset cursor position to get ready for ParseSegmentAsSubroute + // Reset cursor position to get ready for ParseSegmentAsSubroute h.Reset() h.Next() h.RemainingArgs() h.Prev() } else { - //If no arguments present reset the cursor position to get ready for ParseSegmentAsSubroute + // If no arguments present reset the cursor position to get ready for ParseSegmentAsSubroute h.Prev() } diff --git a/caddyconfig/httpcaddyfile/httptype.go b/caddyconfig/httpcaddyfile/httptype.go index 447e28a9d8e..fe7df194c0b 100644 --- a/caddyconfig/httpcaddyfile/httptype.go +++ b/caddyconfig/httpcaddyfile/httptype.go @@ -785,6 +785,9 @@ func (st *ServerType) serversFromPairings( sr := val.Value.(*caddyhttp.Subroute) routeMatcherSet := sr.Routes[0].MatcherSetsRaw sr.Routes[0].MatcherSetsRaw = []caddy.ModuleMap{} + if routeMatcherSet == nil { + routeMatcherSet = matcherSetsEnc + } srv.Errors.Routes = appendSubrouteToRouteList(srv.Errors.Routes, sr, routeMatcherSet, p, warnings) } } diff --git a/caddytest/integration/caddyfile_adapt/error_range_codes.txt b/caddytest/integration/caddyfile_adapt/error_range_codes.txt new file mode 100644 index 00000000000..447824d0942 --- /dev/null +++ b/caddytest/integration/caddyfile_adapt/error_range_codes.txt @@ -0,0 +1,113 @@ +{ + http_port 3010 +} +localhost:3010 { + root * /srv + error /private* "Unauthorized" 410 + error /hidden* "Not found" 404 + + handle_errors 4xx { + respond "Error in the [400 .. 499] range" + } +} +---------- +{ + "apps": { + "http": { + "http_port": 3010, + "servers": { + "srv0": { + "listen": [ + ":3010" + ], + "routes": [ + { + "match": [ + { + "host": [ + "localhost" + ] + } + ], + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "handler": "vars", + "root": "/srv" + } + ] + }, + { + "handle": [ + { + "error": "Unauthorized", + "handler": "error", + "status_code": 410 + } + ], + "match": [ + { + "path": [ + "/private*" + ] + } + ] + }, + { + "handle": [ + { + "error": "Not found", + "handler": "error", + "status_code": 404 + } + ], + "match": [ + { + "path": [ + "/hidden*" + ] + } + ] + } + ] + } + ], + "terminal": true + } + ], + "errors": { + "routes": [ + { + "match": [ + { + "expression": "{http.error.status_code} \u003e= 400 \u0026\u0026 {http.error.status_code} \u003c= 499" + } + ], + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "body": "Error in the [400 .. 499] range", + "handler": "static_response" + } + ] + } + ] + } + ], + "terminal": true + } + ] + } + } + } + } + } +} diff --git a/caddytest/integration/caddyfile_adapt/error_range_simple_codes.txt b/caddytest/integration/caddyfile_adapt/error_range_simple_codes.txt new file mode 100644 index 00000000000..4649671a961 --- /dev/null +++ b/caddytest/integration/caddyfile_adapt/error_range_simple_codes.txt @@ -0,0 +1,156 @@ +{ + http_port 2099 +} +localhost:2099 { + root * /srv + error /private* "Unauthorized" 410 + error /threehundred* "Moved Permanently" 301 + error /internalerr* "Internal Server Error" 500 + + handle_errors 500 3xx { + respond "Error code is equal to 500 or in the [300..399] range" + } + handle_errors 4xx { + respond "Error in the [400 .. 499] range" + } +} +---------- +{ + "apps": { + "http": { + "http_port": 2099, + "servers": { + "srv0": { + "listen": [ + ":2099" + ], + "routes": [ + { + "match": [ + { + "host": [ + "localhost" + ] + } + ], + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "handler": "vars", + "root": "/srv" + } + ] + }, + { + "handle": [ + { + "error": "Moved Permanently", + "handler": "error", + "status_code": 301 + } + ], + "match": [ + { + "path": [ + "/threehundred*" + ] + } + ] + }, + { + "handle": [ + { + "error": "Internal Server Error", + "handler": "error", + "status_code": 500 + } + ], + "match": [ + { + "path": [ + "/internalerr*" + ] + } + ] + }, + { + "handle": [ + { + "error": "Unauthorized", + "handler": "error", + "status_code": 410 + } + ], + "match": [ + { + "path": [ + "/private*" + ] + } + ] + } + ] + } + ], + "terminal": true + } + ], + "errors": { + "routes": [ + { + "match": [ + { + "expression": "{http.error.status_code} \u003e= 400 \u0026\u0026 {http.error.status_code} \u003c= 499" + } + ], + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "body": "Error in the [400 .. 499] range", + "handler": "static_response" + } + ] + } + ] + } + ], + "terminal": true + }, + { + "match": [ + { + "expression": "{http.error.status_code} \u003e= 300 \u0026\u0026 {http.error.status_code} \u003c= 399 || {http.error.status_code} in [500]" + } + ], + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "body": "Error code is equal to 500 or in the [300..399] range", + "handler": "static_response" + } + ] + } + ] + } + ], + "terminal": true + } + ] + } + } + } + } + } +} diff --git a/caddytest/integration/caddyfile_adapt/error_simple_codes.txt b/caddytest/integration/caddyfile_adapt/error_simple_codes.txt new file mode 100644 index 00000000000..dccc35a602e --- /dev/null +++ b/caddytest/integration/caddyfile_adapt/error_simple_codes.txt @@ -0,0 +1,113 @@ +{ + http_port 3010 +} +localhost:3010 { + root * /srv + error /private* "Unauthorized" 410 + error /hidden* "Not found" 404 + + handle_errors 404 410 { + respond "404 or 410 error" + } +} +---------- +{ + "apps": { + "http": { + "http_port": 3010, + "servers": { + "srv0": { + "listen": [ + ":3010" + ], + "routes": [ + { + "match": [ + { + "host": [ + "localhost" + ] + } + ], + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "handler": "vars", + "root": "/srv" + } + ] + }, + { + "handle": [ + { + "error": "Unauthorized", + "handler": "error", + "status_code": 410 + } + ], + "match": [ + { + "path": [ + "/private*" + ] + } + ] + }, + { + "handle": [ + { + "error": "Not found", + "handler": "error", + "status_code": 404 + } + ], + "match": [ + { + "path": [ + "/hidden*" + ] + } + ] + } + ] + } + ], + "terminal": true + } + ], + "errors": { + "routes": [ + { + "match": [ + { + "expression": "{http.error.status_code} in [404, 410]" + } + ], + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "body": "404 or 410 error", + "handler": "static_response" + } + ] + } + ] + } + ], + "terminal": true + } + ] + } + } + } + } + } +} diff --git a/caddytest/integration/caddyfile_adapt/error_sort.txt b/caddytest/integration/caddyfile_adapt/error_sort.txt new file mode 100644 index 00000000000..578c8582802 --- /dev/null +++ b/caddytest/integration/caddyfile_adapt/error_sort.txt @@ -0,0 +1,158 @@ +{ + http_port 2099 +} +localhost:2099 { + root * /srv + error /private* "Unauthorized" 410 + error /hidden* "Not found" 404 + error /internalerr* "Internal Server Error" 500 + + handle_errors { + respond "Fallback route: code outside the [400..499] range" + } + handle_errors 4xx { + respond "Error in the [400 .. 499] range" + } +} +---------- +{ + "apps": { + "http": { + "http_port": 2099, + "servers": { + "srv0": { + "listen": [ + ":2099" + ], + "routes": [ + { + "match": [ + { + "host": [ + "localhost" + ] + } + ], + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "handler": "vars", + "root": "/srv" + } + ] + }, + { + "handle": [ + { + "error": "Internal Server Error", + "handler": "error", + "status_code": 500 + } + ], + "match": [ + { + "path": [ + "/internalerr*" + ] + } + ] + }, + { + "handle": [ + { + "error": "Unauthorized", + "handler": "error", + "status_code": 410 + } + ], + "match": [ + { + "path": [ + "/private*" + ] + } + ] + }, + { + "handle": [ + { + "error": "Not found", + "handler": "error", + "status_code": 404 + } + ], + "match": [ + { + "path": [ + "/hidden*" + ] + } + ] + } + ] + } + ], + "terminal": true + } + ], + "errors": { + "routes": [ + { + "match": [ + { + "expression": "{http.error.status_code} \u003e= 400 \u0026\u0026 {http.error.status_code} \u003c= 499" + } + ], + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "body": "Error in the [400 .. 499] range", + "handler": "static_response" + } + ] + } + ] + } + ], + "terminal": true + }, + { + "match": [ + { + "host": [ + "localhost" + ] + } + ], + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "body": "Fallback route: code outside the [400..499] range", + "handler": "static_response" + } + ] + } + ] + } + ], + "terminal": true + } + ] + } + } + } + } + } +} diff --git a/caddytest/integration/caddyfile_test.go b/caddytest/integration/caddyfile_test.go index 0db7e794787..f9a98fb3855 100644 --- a/caddytest/integration/caddyfile_test.go +++ b/caddytest/integration/caddyfile_test.go @@ -496,3 +496,91 @@ func TestUriReplace(t *testing.T) { tester.AssertGetResponse("http://localhost:9080/endpoint?test={%20content%20}", 200, "test=%7B%20content%20%7D") } +func TestHandleErrorSimpleCodes(t *testing.T) { + tester := caddytest.NewTester(t) + tester.InitServer(`{ + admin localhost:2999 + http_port 9080 + } + localhost:9080 { + root * /srv + error /private* "Unauthorized" 410 + error /hidden* "Not found" 404 + + handle_errors 404 410 { + respond "404 or 410 error" + } + }`, "caddyfile") + // act and assert + tester.AssertGetResponse("http://localhost:9080/private", 410, "404 or 410 error") + tester.AssertGetResponse("http://localhost:9080/hidden", 404, "404 or 410 error") +} + +func TestHandleErrorRange(t *testing.T) { + tester := caddytest.NewTester(t) + tester.InitServer(`{ + admin localhost:2999 + http_port 9080 + } + localhost:9080 { + root * /srv + error /private* "Unauthorized" 410 + error /hidden* "Not found" 404 + + handle_errors 4xx { + respond "Error in the [400 .. 499] range" + } + }`, "caddyfile") + // act and assert + tester.AssertGetResponse("http://localhost:9080/private", 410, "Error in the [400 .. 499] range") + tester.AssertGetResponse("http://localhost:9080/hidden", 404, "Error in the [400 .. 499] range") +} + +func TestHandleErrorSort(t *testing.T) { + tester := caddytest.NewTester(t) + tester.InitServer(`{ + admin localhost:2999 + http_port 9080 + } + localhost:9080 { + root * /srv + error /private* "Unauthorized" 410 + error /hidden* "Not found" 404 + error /internalerr* "Internal Server Error" 500 + + handle_errors { + respond "Fallback route: code outside the [400..499] range" + } + handle_errors 4xx { + respond "Error in the [400 .. 499] range" + } + }`, "caddyfile") + // act and assert + tester.AssertGetResponse("http://localhost:9080/internalerr", 500, "Fallback route: code outside the [400..499] range") + tester.AssertGetResponse("http://localhost:9080/hidden", 404, "Error in the [400 .. 499] range") +} + +func TestHandleErrorRangeAndCodes(t *testing.T) { + tester := caddytest.NewTester(t) + tester.InitServer(`{ + admin localhost:2999 + http_port 9080 + } + localhost:9080 { + root * /srv + error /private* "Unauthorized" 410 + error /threehundred* "Moved Permanently" 301 + error /internalerr* "Internal Server Error" 500 + + handle_errors 500 3xx { + respond "Error code is equal to 500 or in the [300..399] range" + } + handle_errors 4xx { + respond "Error in the [400 .. 499] range" + } + }`, "caddyfile") + // act and assert + tester.AssertGetResponse("http://localhost:9080/internalerr", 500, "Error code is equal to 500 or in the [300..399] range") + tester.AssertGetResponse("http://localhost:9080/threehundred", 301, "Error code is equal to 500 or in the [300..399] range") + tester.AssertGetResponse("http://localhost:9080/private", 410, "Error in the [400 .. 499] range") +}