diff options
author | Matthew Holt <mholt@users.noreply.github.com> | 2019-12-17 10:11:45 -0700 |
---|---|---|
committer | Matthew Holt <mholt@users.noreply.github.com> | 2019-12-17 10:11:45 -0700 |
commit | 6455efa5d327377b41e708a063d1b7a71a131165 (patch) | |
tree | 4532f26949b89a2fa1224dc566af3daa49c55368 | |
parent | 5ab17a3a371c1f84ef5a649d9310971eb7959271 (diff) |
admin: POST /... expands and appends all array elements
Makes it easy to append many items to an array in one command
-rw-r--r-- | admin.go | 39 | ||||
-rw-r--r-- | admin_test.go | 6 |
2 files changed, 39 insertions, 6 deletions
@@ -636,6 +636,19 @@ func unsyncedConfigAccess(method, path string, body []byte, out io.Writer) error 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 traverseLoop: @@ -666,7 +679,15 @@ traverseLoop: return fmt.Errorf("encoding config: %v", err) } 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: // avoid creation of new slice and a second copy (see // https://github.com/golang/go/wiki/SliceTricks#insert) @@ -692,13 +713,19 @@ traverseLoop: return fmt.Errorf("encoding config: %v", err) } 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 the part is an existing list, POST appends to it - // TODO: Do we ever reach this point, since we handle arrays - // separately above? - 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) + } } else { - // otherwise, it simply sets the value v[part] = val } case http.MethodPut: diff --git a/admin_test.go b/admin_test.go index e8563b7..cfb4ab7 100644 --- a/admin_test.go +++ b/admin_test.go @@ -77,6 +77,12 @@ func TestUnsyncedConfigAccess(t *testing.T) { payload: `"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) |