mirror of
https://github.com/caddyserver/caddy.git
synced 2025-01-27 12:25:55 +03:00
admin: POST /... expands and appends all array elements
Makes it easy to append many items to an array in one command
This commit is contained in:
parent
5ab17a3a37
commit
6455efa5d3
2 changed files with 39 additions and 6 deletions
39
admin.go
39
admin.go
|
@ -636,6 +636,19 @@ func unsyncedConfigAccess(method, path string, body []byte, out io.Writer) error
|
||||||
return fmt.Errorf("path missing")
|
return fmt.Errorf("path missing")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A path that ends with "..." implies:
|
||||||
|
// 1) the part before it is an array
|
||||||
|
// 2) the payload is an array
|
||||||
|
// and means that the user wants to expand the elements
|
||||||
|
// in the payload array and append each one into the
|
||||||
|
// destination array, like so:
|
||||||
|
// array = append(array, elems...)
|
||||||
|
// This special case is handled below.
|
||||||
|
ellipses := parts[len(parts)-1] == "..."
|
||||||
|
if ellipses {
|
||||||
|
parts = parts[:len(parts)-1]
|
||||||
|
}
|
||||||
|
|
||||||
var ptr interface{} = rawCfg
|
var ptr interface{} = rawCfg
|
||||||
|
|
||||||
traverseLoop:
|
traverseLoop:
|
||||||
|
@ -666,7 +679,15 @@ traverseLoop:
|
||||||
return fmt.Errorf("encoding config: %v", err)
|
return fmt.Errorf("encoding config: %v", err)
|
||||||
}
|
}
|
||||||
case http.MethodPost:
|
case http.MethodPost:
|
||||||
v[part] = append(arr, val)
|
if ellipses {
|
||||||
|
valArray, ok := val.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("final element is not an array")
|
||||||
|
}
|
||||||
|
v[part] = append(arr, valArray...)
|
||||||
|
} else {
|
||||||
|
v[part] = append(arr, val)
|
||||||
|
}
|
||||||
case http.MethodPut:
|
case http.MethodPut:
|
||||||
// avoid creation of new slice and a second copy (see
|
// avoid creation of new slice and a second copy (see
|
||||||
// https://github.com/golang/go/wiki/SliceTricks#insert)
|
// https://github.com/golang/go/wiki/SliceTricks#insert)
|
||||||
|
@ -692,13 +713,19 @@ traverseLoop:
|
||||||
return fmt.Errorf("encoding config: %v", err)
|
return fmt.Errorf("encoding config: %v", err)
|
||||||
}
|
}
|
||||||
case http.MethodPost:
|
case http.MethodPost:
|
||||||
|
// if the part is an existing list, POST appends to
|
||||||
|
// it, otherwise it just sets or creates the value
|
||||||
if arr, ok := v[part].([]interface{}); ok {
|
if arr, ok := v[part].([]interface{}); ok {
|
||||||
// if the part is an existing list, POST appends to it
|
if ellipses {
|
||||||
// TODO: Do we ever reach this point, since we handle arrays
|
valArray, ok := val.([]interface{})
|
||||||
// separately above?
|
if !ok {
|
||||||
v[part] = append(arr, val)
|
return fmt.Errorf("final element is not an array")
|
||||||
|
}
|
||||||
|
v[part] = append(arr, valArray...)
|
||||||
|
} else {
|
||||||
|
v[part] = append(arr, val)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// otherwise, it simply sets the value
|
|
||||||
v[part] = val
|
v[part] = val
|
||||||
}
|
}
|
||||||
case http.MethodPut:
|
case http.MethodPut:
|
||||||
|
|
|
@ -77,6 +77,12 @@ func TestUnsyncedConfigAccess(t *testing.T) {
|
||||||
payload: `"d"`,
|
payload: `"d"`,
|
||||||
expect: `{"foo": "jet", "bar": {"aa": "bb"}, "list": ["a", "b", "c", "d"]}`,
|
expect: `{"foo": "jet", "bar": {"aa": "bb"}, "list": ["a", "b", "c", "d"]}`,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
path: "/list/...",
|
||||||
|
payload: `["e", "f", "g"]`,
|
||||||
|
expect: `{"foo": "jet", "bar": {"aa": "bb"}, "list": ["a", "b", "c", "d", "e", "f", "g"]}`,
|
||||||
|
},
|
||||||
} {
|
} {
|
||||||
err := unsyncedConfigAccess(tc.method, rawConfigKey+tc.path, []byte(tc.payload), nil)
|
err := unsyncedConfigAccess(tc.method, rawConfigKey+tc.path, []byte(tc.payload), nil)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue