Skip to content

Commit

Permalink
httpcaddyfile: Add optional status code argument to handle_errors d…
Browse files Browse the repository at this point in the history
…irective (#5965)

Co-authored-by: Aziz Rmadi <azizrmadi@Azizs-MacBook-Air.local>
  • Loading branch information
armadi1809 and Aziz Rmadi committed Jan 16, 2024
1 parent 5e2f1b5 commit 4181c79
Show file tree
Hide file tree
Showing 8 changed files with 942 additions and 2 deletions.
59 changes: 58 additions & 1 deletion caddyconfig/httpcaddyfile/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -844,10 +844,67 @@ func parseHandle(h Helper) (caddyhttp.MiddlewareHandler, error) {
}

func parseHandleErrors(h Helper) ([]ConfigValue, error) {
subroute, err := ParseSegmentAsSubroute(h)
h.Next()
args := h.RemainingArgs()
expression := ""
if len(args) > 0 {
expression = ""
codes := []string{}
for _, val := range args {
if len(val) != 3 {
return nil, h.Errf("bad status value '%s'", val)
}
if strings.HasSuffix(val, "xx") {
val = val[:1]
_, err := strconv.Atoi(val)
if err != nil {
return nil, h.Errf("bad status value '%s': %v", val, err)
}
if expression != "" {
expression += " || "
}
expression += fmt.Sprintf("{http.error.status_code} >= %s00 && {http.error.status_code} <= %s99", val, val)
continue
}
_, err := strconv.Atoi(val)
if err != nil {
return nil, h.Errf("bad status value '%s': %v", val, err)
}
codes = append(codes, val)
}
if len(codes) > 0 {
if expression != "" {
expression += " || "
}
expression += "{http.error.status_code} in [" + strings.Join(codes, ", ") + "]"
}
// 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
h.Prev()
}

handler, err := ParseSegmentAsSubroute(h)
if err != nil {
return nil, err
}
subroute, ok := handler.(*caddyhttp.Subroute)
if !ok {
return nil, h.Errf("segment was not parsed as a subroute")
}

if expression != "" {
statusMatcher := caddy.ModuleMap{
"expression": h.JSON(caddyhttp.MatchExpression{Expr: expression}),
}
for i := range subroute.Routes {
subroute.Routes[i].MatcherSetsRaw = []caddy.ModuleMap{statusMatcher}
}
}
return []ConfigValue{
{
Class: "error_route",
Expand Down
11 changes: 10 additions & 1 deletion caddyconfig/httpcaddyfile/httptype.go
Original file line number Diff line number Diff line change
Expand Up @@ -774,10 +774,19 @@ func (st *ServerType) serversFromPairings(
if srv.Errors == nil {
srv.Errors = new(caddyhttp.HTTPErrorConfig)
}
sort.SliceStable(errorSubrouteVals, func(i, j int) bool {
sri, srj := errorSubrouteVals[i].Value.(*caddyhttp.Subroute), errorSubrouteVals[j].Value.(*caddyhttp.Subroute)
if len(sri.Routes[0].MatcherSetsRaw) == 0 && len(srj.Routes[0].MatcherSetsRaw) != 0 {
return false
}
return true
})
errorsSubroute := &caddyhttp.Subroute{}
for _, val := range errorSubrouteVals {
sr := val.Value.(*caddyhttp.Subroute)
srv.Errors.Routes = appendSubrouteToRouteList(srv.Errors.Routes, sr, matcherSetsEnc, p, warnings)
errorsSubroute.Routes = append(errorsSubroute.Routes, sr.Routes...)
}
srv.Errors.Routes = appendSubrouteToRouteList(srv.Errors.Routes, errorsSubroute, matcherSetsEnc, p, warnings)
}

// add log associations
Expand Down
245 changes: 245 additions & 0 deletions caddytest/integration/caddyfile_adapt/error_multi_site_blocks.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
foo.localhost {
root * /srv
error /private* "Unauthorized" 410
error /fivehundred* "Internal Server Error" 500

handle_errors 5xx {
respond "Error In range [500 .. 599]"
}
handle_errors 410 {
respond "404 or 410 error"
}
}

bar.localhost {
root * /srv
error /private* "Unauthorized" 410
error /fivehundred* "Internal Server Error" 500

handle_errors 5xx {
respond "Error In range [500 .. 599] from second site"
}
handle_errors 410 {
respond "404 or 410 error from second site"
}
}
----------
{
"apps": {
"http": {
"servers": {
"srv0": {
"listen": [
":443"
],
"routes": [
{
"match": [
{
"host": [
"foo.localhost"
]
}
],
"handle": [
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"handler": "vars",
"root": "/srv"
}
]
},
{
"handle": [
{
"error": "Internal Server Error",
"handler": "error",
"status_code": 500
}
],
"match": [
{
"path": [
"/fivehundred*"
]
}
]
},
{
"handle": [
{
"error": "Unauthorized",
"handler": "error",
"status_code": 410
}
],
"match": [
{
"path": [
"/private*"
]
}
]
}
]
}
],
"terminal": true
},
{
"match": [
{
"host": [
"bar.localhost"
]
}
],
"handle": [
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"handler": "vars",
"root": "/srv"
}
]
},
{
"handle": [
{
"error": "Internal Server Error",
"handler": "error",
"status_code": 500
}
],
"match": [
{
"path": [
"/fivehundred*"
]
}
]
},
{
"handle": [
{
"error": "Unauthorized",
"handler": "error",
"status_code": 410
}
],
"match": [
{
"path": [
"/private*"
]
}
]
}
]
}
],
"terminal": true
}
],
"errors": {
"routes": [
{
"match": [
{
"host": [
"foo.localhost"
]
}
],
"handle": [
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"body": "404 or 410 error",
"handler": "static_response"
}
],
"match": [
{
"expression": "{http.error.status_code} in [410]"
}
]
},
{
"handle": [
{
"body": "Error In range [500 .. 599]",
"handler": "static_response"
}
],
"match": [
{
"expression": "{http.error.status_code} \u003e= 500 \u0026\u0026 {http.error.status_code} \u003c= 599"
}
]
}
]
}
],
"terminal": true
},
{
"match": [
{
"host": [
"bar.localhost"
]
}
],
"handle": [
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"body": "404 or 410 error from second site",
"handler": "static_response"
}
],
"match": [
{
"expression": "{http.error.status_code} in [410]"
}
]
},
{
"handle": [
{
"body": "Error In range [500 .. 599] from second site",
"handler": "static_response"
}
],
"match": [
{
"expression": "{http.error.status_code} \u003e= 500 \u0026\u0026 {http.error.status_code} \u003c= 599"
}
]
}
]
}
],
"terminal": true
}
]
}
}
}
}
}
}

0 comments on commit 4181c79

Please sign in to comment.