0
Fork 0
mirror of https://github.com/caddyserver/caddy.git synced 2024-12-30 22:34:15 -05:00

map: Apply default if mapped output is nil

This commit is contained in:
Matthew Holt 2020-10-02 15:23:52 -06:00
parent 25d2b4bf29
commit 0fc47e8357
No known key found for this signature in database
GPG key ID: 2A349DD577D586A5
3 changed files with 23 additions and 14 deletions

View file

@ -18,7 +18,7 @@ func TestMap(t *testing.T) {
localhost:9080 { localhost:9080 {
map {http.request.method} {dest-1} {dest-2} { map {http.request.method} {dest-1} {dest-2} {
default unknown default unknown1 unknown2
~G.T get-called ~G.T get-called
POST post-called foobar POST post-called foobar
} }
@ -30,7 +30,7 @@ func TestMap(t *testing.T) {
`, "caddyfile") `, "caddyfile")
// act and assert // act and assert
tester.AssertGetResponse("http://localhost:9080/version", 200, "hello from localhost get-called ") tester.AssertGetResponse("http://localhost:9080/version", 200, "hello from localhost get-called unknown2")
tester.AssertPostResponseBody("http://localhost:9080/version", []string{}, bytes.NewBuffer([]byte{}), 200, "hello from localhost post-called foobar") tester.AssertPostResponseBody("http://localhost:9080/version", []string{}, bytes.NewBuffer([]byte{}), 200, "hello from localhost post-called foobar")
} }

View file

@ -70,7 +70,10 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
// every other line maps one input to one or more outputs // every other line maps one input to one or more outputs
in := h.Val() in := h.Val()
outs := h.RemainingArgs() var outs []interface{}
for _, out := range h.RemainingArgs() {
outs = append(outs, out)
}
// cannot have more outputs than destinations // cannot have more outputs than destinations
if len(outs) > len(handler.Destinations) { if len(outs) > len(handler.Destinations) {
@ -78,9 +81,9 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
} }
// for convenience, can have fewer outputs than destinations, but the // for convenience, can have fewer outputs than destinations, but the
// underlying handler won't accept that, so we fill in empty values // underlying handler won't accept that, so we fill in nil values
for len(outs) < len(handler.Destinations) { for len(outs) < len(handler.Destinations) {
outs = append(outs, "") outs = append(outs, nil)
} }
// create the mapping // create the mapping

View file

@ -16,7 +16,6 @@ package maphandler
import ( import (
"fmt" "fmt"
"log"
"net/http" "net/http"
"regexp" "regexp"
"strings" "strings"
@ -40,14 +39,15 @@ type Handler struct {
// Source is the placeholder from which to get the input value. // Source is the placeholder from which to get the input value.
Source string `json:"source,omitempty"` Source string `json:"source,omitempty"`
// Destinations are the placeholders in which to store the outputs. // Destinations are the names of placeholders in which to store the outputs.
Destinations []string `json:"destinations,omitempty"` Destinations []string `json:"destinations,omitempty"`
// Mappings from source values (inputs) to destination values (outputs). // Mappings from source values (inputs) to destination values (outputs).
// The first matching mapping will be applied. // The first matching mapping will be applied.
Mappings []Mapping `json:"mappings,omitempty"` Mappings []Mapping `json:"mappings,omitempty"`
// If no mappings match, the default value will be applied (optional). // If no mappings match or if the mapped output is null/nil, the associated
// default output will be applied (optional).
Defaults []string Defaults []string
} }
@ -125,20 +125,26 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhtt
// find the first mapping matching the input and return // find the first mapping matching the input and return
// the requested destination/output value // the requested destination/output value
for _, m := range h.Mappings { for _, m := range h.Mappings {
log.Printf("MAPPING: %+v", m)
if m.re != nil { if m.re != nil {
if m.re.MatchString(input) { if m.re.MatchString(input) {
return m.Outputs[destIdx], true if output := m.Outputs[destIdx]; output == nil {
break
} else {
return output, true
}
} }
continue continue
} }
if input == m.Input { if input == m.Input {
log.Printf("RETURNING: %s", m.Outputs[destIdx]) if output := m.Outputs[destIdx]; output == nil {
return m.Outputs[destIdx], true break
} else {
return output, true
}
} }
} }
// fall back to default if no match // fall back to default if no match or if matched nil value
if len(h.Defaults) > destIdx { if len(h.Defaults) > destIdx {
return h.Defaults[destIdx], true return h.Defaults[destIdx], true
} }
@ -171,7 +177,7 @@ type Mapping struct {
// Upon a match with the input, each output is positionally correlated // Upon a match with the input, each output is positionally correlated
// with each destination of the parent handler. // with each destination of the parent handler.
Outputs []string `json:"outputs,omitempty"` Outputs []interface{} `json:"outputs,omitempty"`
re *regexp.Regexp re *regexp.Regexp
} }