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 c7f9fdf  feature: support to specify TTL for route。 (#807)
c7f9fdf is described below

commit c7f9fdf9d756e93ad609bb4161d98717cf46958c
Author: YuanSheng Wang <membp...@gmail.com>
AuthorDate: Fri Dec 6 11:13:24 2019 +0800

    feature: support to specify TTL for route。 (#807)
    
    Fix #443.
---
 doc/admin-api-cn.md         |  28 ++++++++-
 lua/apisix/admin/init.lua   |  14 ++++-
 lua/apisix/admin/routes.lua |  12 ++--
 lua/apisix/core/etcd.lua    |   8 +--
 t/admin/routes.t            | 144 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 192 insertions(+), 14 deletions(-)

diff --git a/doc/admin-api-cn.md b/doc/admin-api-cn.md
index 2af0580..feb211f 100644
--- a/doc/admin-api-cn.md
+++ b/doc/admin-api-cn.md
@@ -25,7 +25,7 @@
 
 ## Route
 
-*地址*:/apisix/admin/routes/{id}
+*地址*:/apisix/admin/routes/{id}?ttl=0
 
 *说明*:Route 字面意思就是路由,通过定义一些规则来匹配客户端的请求,然后根据匹配结果加载并执行相应的
 插件,并把请求转发给到指定 Upstream。
@@ -40,7 +40,13 @@
 |DELETE   |/apisix/admin/routes/{id}|无|删除资源|
 |PATCH    |/apisix/admin/routes/{id}/{path}|{...}|修改已有 Route 
的部分内容,其他不涉及部分会原样保留。|
 
-> 请求参数:
+> uri 请求参数:
+
+|名字      |可选项   |类型 |说明        |示例|
+|---------|---------|----|-----------|----|
+|ttl     |可选 |辅助   |超过这个时间会被自动删除,单位:秒|ttl=1|
+
+> body 请求参数:
 
 |名字      |可选项   |类型 |说明        |示例|
 |---------|---------|----|-----------|----|
@@ -64,6 +70,7 @@
 示例:
 
 ```shell
+# 创建一个路由
 $ curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -i -d '
 {
     "uri": "/index.html",
@@ -81,6 +88,23 @@ $ curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -i 
-d '
 HTTP/1.1 201 Created
 Date: Sat, 31 Aug 2019 01:17:15 GMT
 ...
+
+# 创建一个有效期为 60 秒的路由,过期后自动删除
+$ curl http://127.0.0.1:9080/apisix/admin/routes/2?ttl=60 -X PUT -i -d '
+{
+    "uri": "/aa/index.html",
+    "upstream": {
+        "type": "roundrobin",
+        "nodes": {
+            "39.97.63.215:80": 1
+        }
+    }
+}'
+
+HTTP/1.1 201 Created
+Date: Sat, 31 Aug 2019 01:17:15 GMT
+...
+
 ```
 
 > 应答参数
diff --git a/lua/apisix/admin/init.lua b/lua/apisix/admin/init.lua
index 128340f..ee4ebea 100644
--- a/lua/apisix/admin/init.lua
+++ b/lua/apisix/admin/init.lua
@@ -17,10 +17,11 @@
 local core = require("apisix.core")
 local route = require("resty.radixtree")
 local plugin = require("apisix.plugin")
+local ngx = ngx
 local get_method = ngx.req.get_method
+local tonumber = tonumber
 local str_lower = string.lower
 local require = require
-local ngx = ngx
 local reload_event = "/apisix/admin/plugins/reload"
 local events
 
@@ -80,7 +81,16 @@ local function run()
         req_body = data
     end
 
-    local code, data = resource[method](seg_id, req_body, seg_sub_path)
+    local uri_args = ngx.req.get_uri_args() or {}
+    if uri_args.ttl then
+        if not tonumber(uri_args.ttl) then
+            core.response.exit(400, {error_msg = "invalid argument ttl: "
+                                                 .. "should be a number"})
+        end
+    end
+
+    local code, data = resource[method](seg_id, req_body, seg_sub_path,
+                                        uri_args)
     if code then
         core.response.exit(code, data)
     end
diff --git a/lua/apisix/admin/routes.lua b/lua/apisix/admin/routes.lua
index e27e33a..34ab758 100644
--- a/lua/apisix/admin/routes.lua
+++ b/lua/apisix/admin/routes.lua
@@ -117,14 +117,14 @@ local function check_conf(id, conf, need_id)
 end
 
 
-function _M.put(id, conf)
+function _M.put(id, conf, sub_path, args)
     local id, err = check_conf(id, conf, true)
     if not id then
         return 400, err
     end
 
     local key = "/routes/" .. id
-    local res, err = core.etcd.set(key, conf)
+    local res, err = core.etcd.set(key, conf, args.ttl)
     if not res then
         core.log.error("failed to put route[", key, "]: ", err)
         return 500, {error_msg = err}
@@ -150,7 +150,7 @@ function _M.get(id)
 end
 
 
-function _M.post(id, conf)
+function _M.post(id, conf, sub_path, args)
     local id, err = check_conf(id, conf, false)
     if not id then
         return 400, err
@@ -158,7 +158,7 @@ function _M.post(id, conf)
 
     local key = "/routes"
     -- core.log.info("key: ", key)
-    local res, err = core.etcd.push("/routes", conf)
+    local res, err = core.etcd.push("/routes", conf, args.ttl)
     if not res then
         core.log.error("failed to post route[", key, "]: ", err)
         return 500, {error_msg = err}
@@ -185,7 +185,7 @@ function _M.delete(id)
 end
 
 
-function _M.patch(id, conf, sub_path)
+function _M.patch(id, conf, sub_path, args)
     if not id then
         return 400, {error_msg = "missing route id"}
     end
@@ -250,7 +250,7 @@ function _M.patch(id, conf, sub_path)
     end
 
     -- TODO: this is not safe, we need to use compare-set
-    local res, err = core.etcd.set(key, node_value)
+    local res, err = core.etcd.set(key, node_value, args.ttl)
     if not res then
         core.log.error("failed to set new route[", key, "]: ", err)
         return 500, {error_msg = err}
diff --git a/lua/apisix/core/etcd.lua b/lua/apisix/core/etcd.lua
index 311ceb5..3e34144 100644
--- a/lua/apisix/core/etcd.lua
+++ b/lua/apisix/core/etcd.lua
@@ -52,23 +52,23 @@ function _M.get(key)
 end
 
 
-function _M.set(key, value)
+function _M.set(key, value, ttl)
     local etcd_cli, prefix, err = new()
     if not etcd_cli then
         return nil, err
     end
 
-    return etcd_cli:set(prefix .. key, value)
+    return etcd_cli:set(prefix .. key, value, ttl)
 end
 
 
-function _M.push(key, value)
+function _M.push(key, value, ttl)
     local etcd_cli, prefix, err = new()
     if not etcd_cli then
         return nil, err
     end
 
-    return etcd_cli:push(prefix .. key, value)
+    return etcd_cli:push(prefix .. key, value, ttl)
 end
 
 
diff --git a/t/admin/routes.t b/t/admin/routes.t
index 1b8d8ac..e6354d3 100644
--- a/t/admin/routes.t
+++ b/t/admin/routes.t
@@ -1361,3 +1361,147 @@ GET /t
 passed
 --- no_error_log
 [error]
+
+
+
+=== TEST 38: set route with ttl
+--- config
+location /t {
+    content_by_lua_block {
+        local t = require("lib.test_admin").test
+        -- set
+        local code, body, res = t('/apisix/admin/routes/1?ttl=1',
+            ngx.HTTP_PUT,
+            [[{
+                "upstream": {
+                    "nodes": {
+                        "127.0.0.1:8080": 1
+                    },
+                    "type": "roundrobin"
+                },
+                "uri": "/index.html"
+            }]]
+            )
+
+        if code >= 300 then ngx.print("code: ", code, " ") end
+        ngx.say(body)
+
+        -- get
+        code, body = t('/apisix/admin/routes/1?ttl=1',
+            ngx.HTTP_GET,
+            nil,
+            [[{
+                "node": {
+                    "value": {
+                        "uri": "/index.html"
+                    },
+                    "key": "/apisix/routes/1"
+                }
+            }]]
+        )
+
+        if code >= 300 then ngx.print("code: ", code, " ") end
+        ngx.say(body)
+
+        ngx.sleep(2)
+
+        -- get again
+        code, body, res = t('/apisix/admin/routes/1', ngx.HTTP_GET)
+
+        if code >= 300 then ngx.print("code: ", code, " ") end
+        ngx.print(body)
+    }
+}
+--- request
+GET /t
+--- response_body_like eval
+qr$passed
+passed
+code: 404 
{"cause":"\\/apisix\\/routes\\/1","index":\d+,"errorCode":100,"message":"Key 
not found"}$
+--- no_error_log
+[error]
+--- timeout: 5
+
+
+
+=== TEST 39: post route with ttl
+--- config
+location /t {
+    content_by_lua_block {
+        local t = require("lib.test_admin").test
+        local code, body, res = t('/apisix/admin/routes?ttl=1',
+            ngx.HTTP_POST,
+            [[{
+                "methods": ["GET"],
+                "upstream": {
+                    "nodes": {
+                        "127.0.0.1:8080": 1
+                    },
+                    "type": "roundrobin"
+                },
+                "uri": "/index.html"
+            }]],
+            [[{"action": "create"}]]
+            )
+
+        if code >= 300 then
+            ngx.status = code
+            ngx.say(body)
+            return
+        end
+
+        ngx.say("[push] succ: ", body)
+        ngx.sleep(2)
+
+        local id = string.sub(res.node.key, #"/apisix/routes/" + 1)
+        code, body = t('/apisix/admin/routes/' .. id, ngx.HTTP_GET)
+
+        if code >= 300 then ngx.print("code: ", code, " ") end
+        ngx.print(body)
+    }
+}
+--- request
+GET /t
+--- response_body_like eval
+qr$succ: passed
+code: 404 
{"cause":"\\/apisix\\/routes\\/\d+","index":\d+,"errorCode":100,"message":"Key 
not found"}$
+--- no_error_log
+[error]
+--- timeout: 5
+
+
+
+=== TEST 40: invalid argument: ttl
+--- config
+location /t {
+    content_by_lua_block {
+        local t = require("lib.test_admin").test
+        local code, body, res = t('/apisix/admin/routes?ttl=xxx',
+            ngx.HTTP_PUT,
+            [[{
+                "upstream": {
+                    "nodes": {
+                        "127.0.0.1:8080": 1
+                    },
+                    "type": "roundrobin"
+                },
+                "uri": "/index.html"
+            }]]
+            )
+
+        if code >= 300 then
+            ngx.status = code
+            ngx.print(body)
+            return
+        end
+
+        ngx.say("[push] succ: ", body)
+    }
+}
+--- request
+GET /t
+--- error_code: 400
+--- response_body
+{"error_msg":"invalid argument ttl: should be a number"}
+--- no_error_log
+[error]

Reply via email to