This is an automated email from the ASF dual-hosted git repository.

membphis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-apisix.git


The following commit(s) were added to refs/heads/master by this push:
     new ecd684b  feat(admin api): enhance `PATCH` method, allow to update 
partial data. (#1609)
ecd684b is described below

commit ecd684b3a0b40b885aed4ced8339027eb189b38f
Author: nic-chen <33000667+nic-c...@users.noreply.github.com>
AuthorDate: Tue Jun 2 11:28:45 2020 +0800

    feat(admin api): enhance `PATCH` method, allow to update partial data. 
(#1609)
---
 apisix/admin/global_rules.lua | 35 ++++++-----------------------------
 apisix/admin/routes.lua       | 36 +++++++-----------------------------
 apisix/admin/services.lua     | 35 ++++++-----------------------------
 apisix/admin/upstreams.lua    | 35 ++++++-----------------------------
 apisix/core/table.lua         | 19 +++++++++++++++++++
 doc/admin-api-cn.md           |  6 +++---
 doc/admin-api.md              |  6 +++---
 t/admin/global-rules.t        |  5 +++--
 t/admin/routes.t              | 29 ++++++++++++++++-------------
 t/admin/services.t            | 23 ++++++++++++++---------
 t/admin/upstream.t            | 32 +++++++++++++++++++-------------
 11 files changed, 102 insertions(+), 159 deletions(-)

diff --git a/apisix/admin/global_rules.lua b/apisix/admin/global_rules.lua
index c74d773..a29d953 100644
--- a/apisix/admin/global_rules.lua
+++ b/apisix/admin/global_rules.lua
@@ -104,19 +104,19 @@ function _M.delete(id)
 end
 
 
-function _M.patch(id, conf, sub_path)
+function _M.patch(id, conf)
     if not id then
         return 400, {error_msg = "missing global rule id"}
     end
 
-    if not sub_path then
-        return 400, {error_msg = "missing sub-path"}
-    end
-
     if not conf then
         return 400, {error_msg = "missing new configuration"}
     end
 
+    if type(conf) ~= "table"  then
+        return 400, {error_msg = "invalid configuration"}
+    end
+
     local key = "/global_rules/" .. id
     local res_old, err = core.etcd.get(key)
     if not res_old then
@@ -131,32 +131,9 @@ function _M.patch(id, conf, sub_path)
                   core.json.delay_encode(res_old, true))
 
     local node_value = res_old.body.node.value
-    local sub_value = node_value
-    local sub_paths = core.utils.split_uri(sub_path)
-    for i = 1, #sub_paths - 1 do
-        local sub_name = sub_paths[i]
-        if sub_value[sub_name] == nil then
-            sub_value[sub_name] = {}
-        end
 
-        sub_value = sub_value[sub_name]
+    node_value = core.table.merge(node_value, conf);
 
-        if type(sub_value) ~= "table" then
-            return 400, "invalid sub-path: /"
-                        .. core.table.concat(sub_paths, 1, i)
-        end
-    end
-
-    if type(sub_value) ~= "table" then
-        return 400, "invalid sub-path: /" .. sub_path
-    end
-
-    local sub_name = sub_paths[#sub_paths]
-    if sub_name and sub_name ~= "" then
-        sub_value[sub_name] = conf
-    else
-        node_value = conf
-    end
     core.log.info("new conf: ", core.json.delay_encode(node_value, true))
 
     local ok, err = check_conf(id, node_value, true)
diff --git a/apisix/admin/routes.lua b/apisix/admin/routes.lua
index bb7092f..6a14ce4 100644
--- a/apisix/admin/routes.lua
+++ b/apisix/admin/routes.lua
@@ -194,19 +194,19 @@ function _M.delete(id)
 end
 
 
-function _M.patch(id, conf, sub_path, args)
+function _M.patch(id, conf, args)
     if not id then
         return 400, {error_msg = "missing route id"}
     end
 
-    if not sub_path then
-        return 400, {error_msg = "missing sub-path"}
-    end
-
     if not conf then
         return 400, {error_msg = "missing new configuration"}
     end
 
+    if type(conf) ~= "table"  then
+        return 400, {error_msg = "invalid configuration"}
+    end
+
     local key = "/routes"
     if id then
         key = key .. "/" .. id
@@ -224,33 +224,11 @@ function _M.patch(id, conf, sub_path, args)
     core.log.info("key: ", key, " old value: ",
                   core.json.delay_encode(res_old, true))
 
-    local node_value = res_old.body.node.value
-    local sub_value = node_value
-    local sub_paths = core.utils.split_uri(sub_path)
-    for i = 1, #sub_paths - 1 do
-        local sub_name = sub_paths[i]
-        if sub_value[sub_name] == nil then
-            sub_value[sub_name] = {}
-        end
-
-        sub_value = sub_value[sub_name]
 
-        if type(sub_value) ~= "table" then
-            return 400, "invalid sub-path: /"
-                        .. core.table.concat(sub_paths, 1, i)
-        end
-    end
+    local node_value = res_old.body.node.value
 
-    if type(sub_value) ~= "table" then
-        return 400, "invalid sub-path: /" .. sub_path
-    end
+    node_value = core.table.merge(node_value, conf);
 
-    local sub_name = sub_paths[#sub_paths]
-    if sub_name and sub_name ~= "" then
-        sub_value[sub_name] = conf
-    else
-        node_value = conf
-    end
     core.log.info("new conf: ", core.json.delay_encode(node_value, true))
 
     local id, err = check_conf(id, node_value, true)
diff --git a/apisix/admin/services.lua b/apisix/admin/services.lua
index e26ea41..7bebd3b 100644
--- a/apisix/admin/services.lua
+++ b/apisix/admin/services.lua
@@ -177,19 +177,19 @@ function _M.delete(id)
 end
 
 
-function _M.patch(id, conf, sub_path)
+function _M.patch(id, conf)
     if not id then
         return 400, {error_msg = "missing service id"}
     end
 
-    if not sub_path then
-        return 400, {error_msg = "missing sub-path"}
-    end
-
     if not conf then
         return 400, {error_msg = "missing new configuration"}
     end
 
+    if type(conf) ~= "table"  then
+        return 400, {error_msg = "invalid configuration"}
+    end
+
     local key = "/services" .. "/" .. id
     local res_old, err = core.etcd.get(key)
     if not res_old then
@@ -204,32 +204,9 @@ function _M.patch(id, conf, sub_path)
                   core.json.delay_encode(res_old, true))
 
     local new_value = res_old.body.node.value
-    local sub_value = new_value
-    local sub_paths = core.utils.split_uri(sub_path)
-    for i = 1, #sub_paths - 1 do
-        local sub_name = sub_paths[i]
-        if sub_value[sub_name] == nil then
-            sub_value[sub_name] = {}
-        end
 
-        sub_value = sub_value[sub_name]
+    new_value = core.table.merge(new_value, conf);
 
-        if type(sub_value) ~= "table" then
-            return 400, "invalid sub-path: /"
-                        .. core.table.concat(sub_paths, 1, i)
-        end
-    end
-
-    if type(sub_value) ~= "table" then
-        return 400, "invalid sub-path: /" .. sub_path
-    end
-
-    local sub_name = sub_paths[#sub_paths]
-    if sub_name and sub_name ~= "" then
-        sub_value[sub_name] = conf
-    else
-        new_value = conf
-    end
     core.log.info("new value ", core.json.delay_encode(new_value, true))
 
     local id, err = check_conf(id, new_value, true)
diff --git a/apisix/admin/upstreams.lua b/apisix/admin/upstreams.lua
index e989cd5..b7d2a04 100644
--- a/apisix/admin/upstreams.lua
+++ b/apisix/admin/upstreams.lua
@@ -213,19 +213,19 @@ function _M.delete(id)
 end
 
 
-function _M.patch(id, conf, sub_path)
+function _M.patch(id, conf)
     if not id then
         return 400, {error_msg = "missing upstream id"}
     end
 
-    if not sub_path then
-        return 400, {error_msg = "missing sub-path"}
-    end
-
     if not conf then
         return 400, {error_msg = "missing new configuration"}
     end
 
+    if type(conf) ~= "table"  then
+        return 400, {error_msg = "invalid configuration"}
+    end
+
     local key = "/upstreams" .. "/" .. id
     local res_old, err = core.etcd.get(key)
     if not res_old then
@@ -240,32 +240,9 @@ function _M.patch(id, conf, sub_path)
                   core.json.delay_encode(res_old, true))
 
     local new_value = res_old.body.node.value
-    local sub_value = new_value
-    local sub_paths = core.utils.split_uri(sub_path)
-    for i = 1, #sub_paths - 1 do
-        local sub_name = sub_paths[i]
-        if sub_value[sub_name] == nil then
-            sub_value[sub_name] = {}
-        end
 
-        sub_value = sub_value[sub_name]
+    new_value = core.table.merge(new_value, conf);
 
-        if type(sub_value) ~= "table" then
-            return 400, "invalid sub-path: /"
-                        .. core.table.concat(sub_paths, 1, i)
-        end
-    end
-
-    if type(sub_value) ~= "table" then
-        return 400, "invalid sub-path: /" .. sub_path
-    end
-
-    local sub_name = sub_paths[#sub_paths]
-    if sub_name and sub_name ~= "" then
-        sub_value[sub_name] = conf
-    else
-        new_value = conf
-    end
     core.log.info("new value ", core.json.delay_encode(new_value, true))
 
     local id, err = check_conf(id, new_value, true)
diff --git a/apisix/core/table.lua b/apisix/core/table.lua
index 14e0165..e666e16 100644
--- a/apisix/core/table.lua
+++ b/apisix/core/table.lua
@@ -85,5 +85,24 @@ local function deepcopy(orig)
 end
 _M.deepcopy = deepcopy
 
+local ngx_null = ngx.null
+local function merge(origin, extend)
+    for k,v in pairs(extend) do
+        if type(v) == "table" then
+            if type(origin[k] or false) == "table" then
+                merge(origin[k] or {}, extend[k] or {})
+            else
+                origin[k] = v
+            end
+        elseif v == ngx_null then
+            origin[k] = nil
+        else
+            origin[k] = v
+        end
+    end
+
+    return origin
+end
+_M.merge = merge
 
 return _M
diff --git a/doc/admin-api-cn.md b/doc/admin-api-cn.md
index 7a7d355..40303f4 100644
--- a/doc/admin-api-cn.md
+++ b/doc/admin-api-cn.md
@@ -40,7 +40,7 @@
 |PUT      |/apisix/admin/routes/{id}|{...}|根据 id 创建资源|
 |POST     |/apisix/admin/routes     |{...}|创建资源,id 由后台服务自动生成|
 |DELETE   |/apisix/admin/routes/{id}|无|删除资源|
-|PATCH    |/apisix/admin/routes/{id}/{path}|{...}|修改已有 Route 
的部分内容,其他不涉及部分会原样保留。|
+|PATCH    |/apisix/admin/routes/{id}|{...}|修改已有 Route 
的部分内容,其他不涉及部分会原样保留;如果你要删除某个属性,将该属性的值设置为null 即可删除|
 
 > uri 请求参数:
 
@@ -187,7 +187,7 @@ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 
'X-API-KEY: edd1c9f034335f13
 |PUT      |/apisix/admin/services/{id}|{...}|根据 id 创建资源|
 |POST     |/apisix/admin/services     |{...}|创建资源,id 由后台服务自动生成|
 |DELETE   |/apisix/admin/services/{id}|无|删除资源|
-|PATCH    |/apisix/admin/services/{id}/{path}|{...}|修改已有 Service 
的部分内容,其他不涉及部分会原样保留。|
+|PATCH    |/apisix/admin/services/{id}|{...}|修改已有 Service 
的部分内容,其他不涉及部分会原样保留;如果你要删除某个属性,将该属性的值设置为null 即可删除|
 
 > body 请求参数:
 
@@ -336,7 +336,7 @@ Date: Thu, 26 Dec 2019 08:17:49 GMT
 |PUT      |/apisix/admin/upstreams/{id}|{...}|根据 id 创建资源|
 |POST     |/apisix/admin/upstreams     |{...}|创建资源,id 由后台服务自动生成|
 |DELETE   |/apisix/admin/upstreams/{id}|无|删除资源|
-|PATCH    |/apisix/admin/upstreams/{id}/{path}|{...}|修改已有 Route 
的部分内容,其他不涉及部分会原样保留。|
+|PATCH    |/apisix/admin/upstreams/{id}|{...}|修改已有 Route 
的部分内容,其他不涉及部分会原样保留;如果你要删除某个属性,将该属性的值设置为null 即可删除|
 
 > body 请求参数:
 
diff --git a/doc/admin-api.md b/doc/admin-api.md
index f60ccb6..4d1cc9b 100644
--- a/doc/admin-api.md
+++ b/doc/admin-api.md
@@ -41,7 +41,7 @@
 |PUT      |/apisix/admin/routes/{id}|{...}|Create resource by ID|
 |POST     |/apisix/admin/routes     |{...}|Create resource, and ID is 
generated by server|
 |DELETE   |/apisix/admin/routes/{id}|NULL|Remove resource|
-|PATCH    |/apisix/admin/routes/{id}/{path}|{...}|Update targeted content|
+|PATCH    |/apisix/admin/routes/{id}|{...}|Update targeted content, if you 
want to remove an attribute, set the attribute value to null to remove|
 
 > URI Request Parameters:
 
@@ -183,7 +183,7 @@ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 
'X-API-KEY: edd1c9f034335f13
 |PUT      |/apisix/admin/services/{id}|{...}|Create resource by ID|
 |POST     |/apisix/admin/services     |{...}|Create resource, and ID is 
generated by server|
 |DELETE   |/apisix/admin/services/{id}|NULL|Remove resource|
-|PATCH    |/apisix/admin/routes/{id}/{path}|{...}|Update targeted content|
+|PATCH    |/apisix/admin/routes/{id}|{...}|Update targeted content, if you 
want to remove an attribute, set the attribute value to null to remove|
 
 > Request Body Parameters:
 
@@ -328,7 +328,7 @@ Return response from etcd currently.
 |PUT      |/apisix/admin/upstreams/{id}|{...}|Create resource by ID|
 |POST     |/apisix/admin/upstreams     |{...}|Create resource, and ID is 
generated by server|
 |DELETE   |/apisix/admin/upstreams/{id}|NULL|Remove resource|
-|PATCH    |/apisix/admin/upstreams/{id}/{path}|{...}|Update targeted content|
+|PATCH    |/apisix/admin/upstreams/{id}|{...}|Update targeted content, if you 
want to remove an attribute, set the attribute value to null to remove|
 
 > Request Body Parameters:
 
diff --git a/t/admin/global-rules.t b/t/admin/global-rules.t
index aa7a0c6..ee1f10c 100644
--- a/t/admin/global-rules.t
+++ b/t/admin/global-rules.t
@@ -164,16 +164,17 @@ passed
     location /t {
         content_by_lua_block {
             local t = require("lib.test_admin").test
-            local code, body = t('/apisix/admin/global_rules/1/plugins',
+            local code, body = t('/apisix/admin/global_rules/1',
                 ngx.HTTP_PATCH,
                 [[{
+                    "plugins": {
                     "limit-count": {
                         "count": 3,
                         "time_window": 60,
                         "rejected_code": 503,
                         "key": "remote_addr"
                     }
-                }]],
+                }}]],
                 [[{
                     "node": {
                         "value": {
diff --git a/t/admin/routes.t b/t/admin/routes.t
index 78ab5c6..ac8078b 100644
--- a/t/admin/routes.t
+++ b/t/admin/routes.t
@@ -993,9 +993,11 @@ passed
     location /t {
         content_by_lua_block {
             local t = require("lib.test_admin").test
-            local code, body = t('/apisix/admin/routes/1/methods',
+            local code, body = t('/apisix/admin/routes/1',
                 ngx.HTTP_PATCH,
-                '["GET"]',
+                [[{
+                    "methods": ["GET", null, null, null, null, null, null, 
null, null]
+                }]],
                 [[{
                     "node": {
                         "value": {
@@ -1027,9 +1029,11 @@ passed
     location /t {
         content_by_lua_block {
             local t = require("lib.test_admin").test
-            local code, body = t('/apisix/admin/routes/1/uri',
+            local code, body = t('/apisix/admin/routes/1',
                 ngx.HTTP_PATCH,
-                '"/patch_test"',
+                [[{
+                    "uri": "/patch_test"
+                }]],
                 [[{
                     "node": {
                         "value": {
@@ -1054,23 +1058,22 @@ passed
 
 
 
-=== TEST 30: patch route(whole)
+=== TEST 30: patch route(multi)
 --- config
     location /t {
         content_by_lua_block {
             local t = require("lib.test_admin").test
-            local code, body = t('/apisix/admin/routes/1/',
+            local code, body = t('/apisix/admin/routes/1',
                 ngx.HTTP_PATCH,
                 [[{
                     "methods": ["GET"],
                     "upstream": {
                         "nodes": {
-                            "127.0.0.1:8080": 1
-                        },
-                        "type": "roundrobin"
+                            "127.0.0.1:8080": null,
+                            "127.0.0.2:8080": 1
+                        }
                     },
-                    "desc": "new route",
-                    "uri": "/index.html"
+                    "desc": "new route"
                 }]],
                 [[{
                     "node": {
@@ -1078,11 +1081,11 @@ passed
                             "methods": [
                                 "GET"
                             ],
-                            "uri": "/index.html",
+                            "uri": "/patch_test",
                             "desc": "new route",
                             "upstream": {
                                 "nodes": {
-                                    "127.0.0.1:8080": 1
+                                    "127.0.0.2:8080": 1
                                 },
                                 "type": "roundrobin"
                             }
diff --git a/t/admin/services.t b/t/admin/services.t
index 6c6f503..a3aaa59 100644
--- a/t/admin/services.t
+++ b/t/admin/services.t
@@ -633,7 +633,7 @@ GET /t
     location /t {
         content_by_lua_block {
             local t = require("lib.test_admin").test
-            local code, body = t('/apisix/admin/services/1/',
+            local code, body = t('/apisix/admin/services/1',
                 ngx.HTTP_PATCH,
                 [[{
                     "upstream": {
@@ -679,9 +679,11 @@ passed
     location /t {
         content_by_lua_block {
             local t = require("lib.test_admin").test
-            local code, body = t('/apisix/admin/services/1/desc',
+            local code, body = t('/apisix/admin/services/1',
                 ngx.HTTP_PATCH,
-                '"new 19 service"',
+                [[{
+                    "desc": "new 19 service"
+                }]],
                 [[{
                     "node": {
                         "value": {
@@ -717,20 +719,23 @@ passed
     location /t {
         content_by_lua_block {
             local t = require("lib.test_admin").test
-            local code, body = t('/apisix/admin/services/1/upstream',
+            local code, body = t('/apisix/admin/services/1',
                 ngx.HTTP_PATCH,
                 [[{
-                    "nodes": {
-                        "127.0.0.1:8081": 3,
-                        "127.0.0.1:8082": 4
-                    },
-                    "type": "roundrobin"
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:8081": 3,
+                            "127.0.0.1:8082": 4
+                        },
+                        "type": "roundrobin"
+                    }
                 }]],
                 [[{
                     "node": {
                         "value": {
                             "upstream": {
                                 "nodes": {
+                                    "127.0.0.1:8080": 1,
                                     "127.0.0.1:8081": 3,
                                     "127.0.0.1:8082": 4
                                 },
diff --git a/t/admin/upstream.t b/t/admin/upstream.t
index 6ec7b22..661186d 100644
--- a/t/admin/upstream.t
+++ b/t/admin/upstream.t
@@ -652,7 +652,7 @@ GET /t
     location /t {
         content_by_lua_block {
             local t = require("lib.test_admin").test
-            local code, body = t('/apisix/admin/upstreams/1/',
+            local code, body = t('/apisix/admin/upstreams/1',
                 ngx.HTTP_PATCH,
                 [[{
                     "nodes": {
@@ -694,9 +694,11 @@ passed
     location /t {
         content_by_lua_block {
             local t = require("lib.test_admin").test
-            local code, body = t('/apisix/admin/upstreams/1/desc',
+            local code, body = t('/apisix/admin/upstreams/1',
                 ngx.HTTP_PATCH,
-                '"new 21 upstream"',
+                [[{
+                    "desc": "new 21 upstream"
+                }]],
                 [[{
                     "node": {
                         "value": {
@@ -730,16 +732,19 @@ passed
     location /t {
         content_by_lua_block {
             local t = require("lib.test_admin").test
-            local code, body = t('/apisix/admin/upstreams/1/nodes',
+            local code, body = t('/apisix/admin/upstreams/1',
                 ngx.HTTP_PATCH,
                 [[{
-                    "127.0.0.1:8081": 3,
-                    "127.0.0.1:8082": 4
+                    "nodes": {
+                        "127.0.0.1:8081": 3,
+                        "127.0.0.1:8082": 4
+                    }
                 }]],
                 [[{
                     "node": {
                         "value": {
                             "nodes": {
+                                "127.0.0.1:8080": 1,
                                 "127.0.0.1:8081": 3,
                                 "127.0.0.1:8082": 4
                             },
@@ -768,18 +773,20 @@ passed
     location /t {
         content_by_lua_block {
             local t = require("lib.test_admin").test
-            local code, body = t('/apisix/admin/upstreams/1/nodes',
+            local code, body = t('/apisix/admin/upstreams/1',
                 ngx.HTTP_PATCH,
                 [[{
-                    "127.0.0.1:8081": 0,
-                    "127.0.0.1:8082": 4
-                }]],
+                    "nodes": {
+                        "127.0.0.1:8081": 3,
+                        "127.0.0.1:8082": 0
+                    }
+                }]],                
                 [[{
                     "node": {
                         "value": {
                             "nodes": {
-                                "127.0.0.1:8081": 0,
-                                "127.0.0.1:8082": 4
+                                "127.0.0.1:8081": 3,
+                                "127.0.0.1:8082": 0
                             },
                             "type": "roundrobin",
                             "desc": "new 21 upstream"
@@ -800,7 +807,6 @@ passed
 [error]
 
 
-
 === TEST 24: set upstream(type: chash)
 --- config
     location /t {

Reply via email to