@marcel91200 / caddy Mirror · read-only / commits / 6455efa5
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 14, 05:15 UTC

admin: POST /... expands and appends all array elements

Makes it easy to append many items to an array in one command

Matthew Holt committed Dec 17, 2019 at 10:11 UTC 6455efa5d327377b41e708a063d1b7a71a131165
2 files changed +39 -6
admin.go
+33 -6
@@ -636,6 +636,19 @@ func unsyncedConfigAccess(method, path string, body []byte, out io.Writer) error
636 return fmt.Errorf("path missing")
637 }
638
639 + // A path that ends with "..." implies:
640 + // 1) the part before it is an array
641 + // 2) the payload is an array
642 + // and means that the user wants to expand the elements
643 + // in the payload array and append each one into the
644 + // destination array, like so:
645 + // array = append(array, elems...)
646 + // This special case is handled below.
647 + ellipses := parts[len(parts)-1] == "..."
648 + if ellipses {
649 + parts = parts[:len(parts)-1]
650 + }
651 +
652 var ptr interface{} = rawCfg
653
654 traverseLoop:
@@ -666,7 +679,15 @@ traverseLoop:
679 return fmt.Errorf("encoding config: %v", err)
680 }
681 case http.MethodPost:
669 - v[part] = append(arr, val)
682 + if ellipses {
683 + valArray, ok := val.([]interface{})
684 + if !ok {
685 + return fmt.Errorf("final element is not an array")
686 + }
687 + v[part] = append(arr, valArray...)
688 + } else {
689 + v[part] = append(arr, val)
690 + }
691 case http.MethodPut:
692 // avoid creation of new slice and a second copy (see
693 // https://github.com/golang/go/wiki/SliceTricks#insert)
@@ -692,13 +713,19 @@ traverseLoop:
713 return fmt.Errorf("encoding config: %v", err)
714 }
715 case http.MethodPost:
716 + // if the part is an existing list, POST appends to
717 + // it, otherwise it just sets or creates the value
718 if arr, ok := v[part].([]interface{}); ok {
696 - // if the part is an existing list, POST appends to it
697 - // TODO: Do we ever reach this point, since we handle arrays
698 - // separately above?
699 - v[part] = append(arr, val)
719 + if ellipses {
720 + valArray, ok := val.([]interface{})
721 + if !ok {
722 + return fmt.Errorf("final element is not an array")
723 + }
724 + v[part] = append(arr, valArray...)
725 + } else {
726 + v[part] = append(arr, val)
727 + }
728 } else {
701 - // otherwise, it simply sets the value
729 v[part] = val
730 }
731 case http.MethodPut:
admin_test.go
+6
@@ -77,6 +77,12 @@ func TestUnsyncedConfigAccess(t *testing.T) {
77 payload: `"d"`,
78 expect: `{"foo": "jet", "bar": {"aa": "bb"}, "list": ["a", "b", "c", "d"]}`,
79 },
80 + {
81 + method: "POST",
82 + path: "/list/...",
83 + payload: `["e", "f", "g"]`,
84 + expect: `{"foo": "jet", "bar": {"aa": "bb"}, "list": ["a", "b", "c", "d", "e", "f", "g"]}`,
85 + },
86 } {
87 err := unsyncedConfigAccess(tc.method, rawConfigKey+tc.path, []byte(tc.payload), nil)
88