reverseproxy: Move status replacement intercept to replace_status (#4300)

This commit is contained in:
Francis Lavoie 2022-03-01 16:12:43 -05:00 committed by GitHub
parent acbee94708
commit 87a1f228b4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 56 additions and 45 deletions

View file

@ -1,6 +1,9 @@
:8884 :8884
reverse_proxy 127.0.0.1:65535 { reverse_proxy 127.0.0.1:65535 {
@changeStatus status 500
replace_status @changeStatus 400
@accel header X-Accel-Redirect * @accel header X-Accel-Redirect *
handle_response @accel { handle_response @accel {
respond "Header X-Accel-Redirect!" respond "Header X-Accel-Redirect!"
@ -38,9 +41,6 @@ reverse_proxy 127.0.0.1:65535 {
handle_response @multi { handle_response @multi {
respond "Headers Foo, Bar AND statuses 401, 403 and 404!" respond "Headers Foo, Bar AND statuses 401, 403 and 404!"
} }
@changeStatus status 500
handle_response @changeStatus 400
} }
---------- ----------
{ {
@ -56,6 +56,14 @@ reverse_proxy 127.0.0.1:65535 {
"handle": [ "handle": [
{ {
"handle_response": [ "handle_response": [
{
"match": {
"status_code": [
500
]
},
"status_code": 400
},
{ {
"match": { "match": {
"headers": { "headers": {
@ -155,14 +163,6 @@ reverse_proxy 127.0.0.1:65535 {
} }
] ]
}, },
{
"match": {
"status_code": [
500
]
},
"status_code": 400
},
{ {
"routes": [ "routes": [
{ {

View file

@ -91,12 +91,13 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
// ... // ...
// } // }
// //
// # handle responses // # intercepting responses
// @name { // @name {
// status <code...> // status <code...>
// header <field> [<value>] // header <field> [<value>]
// } // }
// handle_response [<matcher>] [status_code] { // replace_status <matcher> <status_code>
// handle_response [<matcher>] {
// <directives...> // <directives...>
// } // }
// } // }
@ -651,6 +652,39 @@ func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
// See h.FinalizeUnmarshalCaddyfile // See h.FinalizeUnmarshalCaddyfile
h.handleResponseSegments = append(h.handleResponseSegments, d.NewFromNextSegment()) h.handleResponseSegments = append(h.handleResponseSegments, d.NewFromNextSegment())
case "replace_status":
args := d.RemainingArgs()
if len(args) != 2 {
return d.Errf("must have two arguments: a response matcher and a status code")
}
if !strings.HasPrefix(args[0], matcherPrefix) {
return d.Errf("must use a named response matcher, starting with '@'")
}
foundMatcher, ok := h.responseMatchers[args[0]]
if !ok {
return d.Errf("no named response matcher defined with name '%s'", args[0][1:])
}
_, err := strconv.Atoi(args[1])
if err != nil {
return d.Errf("bad integer value '%s': %v", args[1], err)
}
// make sure there's no block, cause it doesn't make sense
if d.NextBlock(1) {
return d.Errf("cannot define routes for 'replace_status', use 'handle_response' instead.")
}
h.HandleResponse = append(
h.HandleResponse,
caddyhttp.ResponseHandler{
Match: &foundMatcher,
StatusCode: caddyhttp.WeakString(args[1]),
},
)
default: default:
return d.Errf("unrecognized subdirective %s", d.Val()) return d.Errf("unrecognized subdirective %s", d.Val())
} }
@ -699,20 +733,20 @@ func (h *Handler) FinalizeUnmarshalCaddyfile(helper httpcaddyfile.Helper) error
for _, d := range h.handleResponseSegments { for _, d := range h.handleResponseSegments {
// consume the "handle_response" token // consume the "handle_response" token
d.Next() d.Next()
var matcher *caddyhttp.ResponseMatcher
args := d.RemainingArgs() args := d.RemainingArgs()
// the first arg should be a matcher (optional) // TODO: Remove this check at some point in the future
// the second arg should be a status code (optional) if len(args) == 2 {
// any more than that isn't currently supported return d.Errf("configuring 'handle_response' for status code replacement is no longer supported. Use 'replace_status' instead.")
if len(args) > 2 { }
if len(args) > 1 {
return d.Errf("too many arguments for 'handle_response': %s", args) return d.Errf("too many arguments for 'handle_response': %s", args)
} }
// the first arg should always be a matcher. var matcher *caddyhttp.ResponseMatcher
// it doesn't really make sense to support status code without a matcher. if len(args) == 1 {
if len(args) > 0 { // the first arg should always be a matcher.
if !strings.HasPrefix(args[0], matcherPrefix) { if !strings.HasPrefix(args[0], matcherPrefix) {
return d.Errf("must use a named response matcher, starting with '@'") return d.Errf("must use a named response matcher, starting with '@'")
} }
@ -724,29 +758,6 @@ func (h *Handler) FinalizeUnmarshalCaddyfile(helper httpcaddyfile.Helper) error
matcher = &foundMatcher matcher = &foundMatcher
} }
// a second arg should be a status code, in which case
// we skip parsing the block for routes
if len(args) == 2 {
_, err := strconv.Atoi(args[1])
if err != nil {
return d.Errf("bad integer value '%s': %v", args[1], err)
}
// make sure there's no block, cause it doesn't make sense
if d.NextBlock(1) {
return d.Errf("cannot define routes for 'handle_response' when changing the status code")
}
h.HandleResponse = append(
h.HandleResponse,
caddyhttp.ResponseHandler{
Match: matcher,
StatusCode: caddyhttp.WeakString(args[1]),
},
)
continue
}
// parse the block as routes // parse the block as routes
handler, err := httpcaddyfile.ParseSegmentAsSubroute(helper.WithDispenser(d.NewFromNextSegment())) handler, err := httpcaddyfile.ParseSegmentAsSubroute(helper.WithDispenser(d.NewFromNextSegment()))
if err != nil { if err != nil {