Skip to content

Commit

Permalink
feat: add 'radmon_id' algorithm for 'request-id' plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
jiangfucheng committed Jan 2, 2023
1 parent 403e4c5 commit f52f53c
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 7 deletions.
37 changes: 32 additions & 5 deletions apisix/plugins/request-id.lua
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ local tostring = tostring
local math_pow = math.pow
local math_ceil = math.ceil
local math_floor = math.floor
local math_random = math.random
local str_sub = string.sub
local str_len = string.len

local plugin_name = "request-id"

Expand All @@ -40,7 +43,17 @@ local schema = {
properties = {
header_name = {type = "string", default = "X-Request-Id"},
include_in_response = {type = "boolean", default = true},
algorithm = {type = "string", enum = {"uuid", "snowflake", "nanoid"}, default = "uuid"}
algorithm = {
type = "string",
enum = {"uuid", "snowflake", "nanoid", "specified_character_id"},
default = "uuid"
},
specified_character_id_length = { type = "integer", minimum = 6, default = 16 },
specified_character_id_strs = {
type = "string",
minLength = 6,
default = "abcdefghijklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ0123456789"
}
}
}

Expand Down Expand Up @@ -202,14 +215,28 @@ local function next_id()
return snowflake:next_id()
end

-- generate random id
local function get_random_id(strs, length)
local res = ""
for i = 1,length do
local idx = math_random(str_len(strs))
res = res .. str_sub(strs, idx, idx)
end
return res
end

local function get_request_id(algorithm)
if algorithm == "uuid" then
local function get_request_id(conf)
if conf.algorithm == "uuid" then
return uuid()
end
if algorithm == "nanoid" then
if conf.algorithm == "nanoid" then
return nanoid.safe_simple()
end

if conf.algorithm == "specified_character_id" then
return get_random_id(conf.specified_character_id_strs, conf.specified_character_id_length)
end

return next_id()
end

Expand All @@ -218,7 +245,7 @@ function _M.rewrite(conf, ctx)
local headers = ngx.req.get_headers()
local uuid_val
if not headers[conf.header_name] then
uuid_val = get_request_id(conf.algorithm)
uuid_val = get_request_id(conf)
core.request.set_header(ctx, conf.header_name, uuid_val)
else
uuid_val = headers[conf.header_name]
Expand Down
4 changes: 3 additions & 1 deletion docs/en/latest/plugins/request-id.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ The Plugin will not add a unique ID if the request already has a header with the
| ------------------- | ------- | -------- | -------------- | ------------------------------- | ---------------------------------------------------------------------- |
| header_name | string | False | "X-Request-Id" | | Header name for the unique request ID. |
| include_in_response | boolean | False | true | | When set to `true`, adds the unique request ID in the response header. |
| algorithm | string | False | "uuid" | ["uuid", "snowflake", "nanoid"] | Algorithm to use for generating the unique request ID. |
| algorithm | string | False | "uuid" | ["uuid", "snowflake", "nanoid", "specified_character_id"] | Algorithm to use for generating the unique request ID. |
| specified_character_id_strs | string || "abcdefghijklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ0123456789| The minimum string length is 6 | Character set for specified_character_id |
| specified_character_id_length | integer || 16 | Minimum 6 | Id length for specified_character_id algorithm |

### Using snowflake algorithm to generate unique ID

Expand Down
4 changes: 3 additions & 1 deletion docs/zh/latest/plugins/request-id.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ description: 本文介绍了 Apache APISIX request-id 插件的相关操作,
| ------------------- | ------- | -------- | -------------- | ------ | ------------------------------ |
| header_name | string || "X-Request-Id" | | unique ID 的请求头的名称。 |
| include_in_response | boolean || true | | 当设置为 `true` 时,将 unique ID 加入返回头。 |
| algorithm | string || "uuid" | ["uuid", "snowflake", "nanoid"] | 指定的 unique ID 生成算法。 |
| algorithm | string || "uuid" | ["uuid", "snowflake", "nanoid", "specified_character_id"] | 指定的 unique ID 生成算法。 |
| specified_character_id_strs | string || "abcdefghijklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ0123456789| 字符串长度最小为 6 | specified_character_id 算法的字符集 |
| specified_character_id_length | integer || 16 | 最小值为 6 | specified_character_id 算法生成的 id 长度 |

### 使用 snowflake 算法生成 unique ID

Expand Down
141 changes: 141 additions & 0 deletions t/plugin/request-id.t
Original file line number Diff line number Diff line change
Expand Up @@ -710,3 +710,144 @@ X-Request-ID: 123
--- wait: 5
--- response_body
true
=== TEST 21: check config with algorithm specified_character_id
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[[{
"plugins": {
"request-id": {
"algorithm": "specified_character_id",
"specified_character_id_strs": "abcdefg",
"specified_character_id_length" : 20
}
},
"upstream": {
"nodes": {
"127.0.0.1:1982": 1
},
"type": "roundrobin"
},
"uri": "/opentracing"
}]]
)
if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- response_body
passed
=== TEST 22: add plugin with algorithm specified_character_id (default uuid)
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[[{
"plugins": {
"request-id": {
"algorithm": "specified_character_id"
}
},
"upstream": {
"nodes": {
"127.0.0.1:1982": 1
},
"type": "roundrobin"
},
"uri": "/opentracing"
}]]
)
if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- response_body
passed
=== TEST 23: add plugin with algorithm specified_character_id (default uuid)
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local http = require "resty.http"
local v = {}
local ids = {}
local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[[{
"plugins": {
"request-id": {
"algorithm": "specified_character_id"
}
},
"upstream": {
"nodes": {
"127.0.0.1:1982": 1
},
"type": "roundrobin"
},
"uri": "/opentracing"
}]]
)
if code >= 300 then
ngx.say("algorithm specified_character_id is error")
end
for i = 1, 180 do
local th = assert(ngx.thread.spawn(function()
local httpc = http.new()
local uri = "http://127.0.0.1:" .. ngx.var.server_port .. "/opentracing"
local res, err = httpc:request_uri(uri,
{
method = "GET",
headers = {
["Content-Type"] = "application/json",
}
}
)
if not res then
ngx.log(ngx.ERR, err)
return
end
local id = res.headers["X-Request-Id"]
if not id then
return -- ignore if the data is not synced yet.
end
if string.len(id) ~= 16 then
ngx.say(id)
ngx.say("incorrect length for id")
return
end
if ids[id] == true then
ngx.say("ids not unique")
return
end
ids[id] = true
end, i))
table.insert(v, th)
end
for i, th in ipairs(v) do
ngx.thread.wait(th)
end
ngx.say("true")
}
}
--- wait: 5
--- response_body
true

0 comments on commit f52f53c

Please sign in to comment.