Skip to content

Commit 630f8fa

Browse files
committed
optimize: replaced ngx.re.gsub with 'str_replace_char()'.
1 parent 30a7266 commit 630f8fa

File tree

3 files changed

+163
-2
lines changed

3 files changed

+163
-2
lines changed

lib/resty/core/request.lua

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
local ffi = require 'ffi'
55
local base = require "resty.core.base"
6+
base.allows_subsystem("http")
7+
local utils = require "resty.core.utils"
68

79

810
local FFI_BAD_CONTEXT = base.FFI_BAD_CONTEXT
@@ -16,7 +18,6 @@ local ffi_str = ffi.string
1618
local get_string_buf = base.get_string_buf
1719
local get_size_ptr = base.get_size_ptr
1820
local setmetatable = setmetatable
19-
local re = ngx.re
2021
local lower = string.lower
2122
local rawget = rawget
2223
local ngx = ngx
@@ -25,6 +26,7 @@ local type = type
2526
local error = error
2627
local tostring = tostring
2728
local tonumber = tonumber
29+
local str_replace_char = utils.str_replace_char
2830

2931

3032
ffi.cdef[[
@@ -68,7 +70,7 @@ local truncated = ffi.new("int[1]")
6870

6971
local req_headers_mt = {
7072
__index = function (tb, key)
71-
return rawget(tb, (re.gsub(lower(key), '_', '-', "jo")))
73+
return rawget(tb, (str_replace_char(lower(key), '_', '-')))
7274
end
7375
}
7476

lib/resty/core/utils.lua

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
-- Copyright (C) Yichun Zhang (agentzh)
2+
3+
4+
local ffi = require "ffi"
5+
local base = require "resty.core.base"
6+
base.allows_subsystem("http")
7+
8+
9+
local C = ffi.C
10+
local ffi_str = ffi.string
11+
local ffi_copy = ffi.copy
12+
local byte = string.byte
13+
local str_find = string.find
14+
local get_string_buf = base.get_string_buf
15+
16+
17+
ffi.cdef[[
18+
void ngx_http_lua_ffi_str_replace_char(unsigned char *buf, size_t len,
19+
const unsigned char find, const unsigned char replace);
20+
]]
21+
22+
23+
local _M = {
24+
version = base.version
25+
}
26+
27+
28+
function _M.str_replace_char(str, find, replace)
29+
if not str_find(str, find, nil, true) then
30+
return str
31+
end
32+
33+
local len = #str
34+
local buf = get_string_buf(len)
35+
ffi_copy(buf, str)
36+
37+
C.ngx_http_lua_ffi_str_replace_char(buf, len, byte(find),
38+
byte(replace))
39+
40+
return ffi_str(buf, len)
41+
end
42+
43+
44+
return _M

t/utils.t

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# vim:set ft= ts=4 sw=4 et fdm=marker:
2+
use lib '.';
3+
use t::TestCore;
4+
5+
plan tests => repeat_each() * blocks() * 3;
6+
7+
add_block_preprocessor(sub {
8+
my $block = shift;
9+
10+
if (!defined $block->error_log) {
11+
$block->set_value("no_error_log", "[error]");
12+
}
13+
14+
if (!defined $block->request) {
15+
$block->set_value("request", "GET /t");
16+
}
17+
});
18+
19+
no_diff();
20+
no_long_string();
21+
run_tests();
22+
23+
__DATA__
24+
25+
=== TEST 1: utils.str_replace_char() sanity (replaces a single character)
26+
--- config
27+
location /t {
28+
content_by_lua_block {
29+
local utils = require "resty.core.utils"
30+
31+
local strings = {
32+
"Header_Name",
33+
"_Header_Name_",
34+
"Header__Name",
35+
"Header-Name",
36+
"Hello world",
37+
}
38+
39+
for i = 1, #strings do
40+
ngx.say(utils.str_replace_char(strings[i], "_", "-"))
41+
end
42+
}
43+
}
44+
--- response_body
45+
Header-Name
46+
-Header-Name-
47+
Header--Name
48+
Header-Name
49+
Hello world
50+
51+
52+
53+
=== TEST 2: utils.str_replace_char() JIT compiles when match
54+
--- config
55+
location /t {
56+
content_by_lua_block {
57+
local utils = require "resty.core.utils"
58+
59+
for i = 1, $TEST_NGINX_HOTLOOP * 10 do
60+
utils.str_replace_char("Header_Name", "_", "-")
61+
end
62+
}
63+
}
64+
--- ignore_response_body
65+
--- error_log eval
66+
qr/\[TRACE\s+\d+ content_by_lua\(nginx\.conf:\d+\):4 loop\]/,
67+
--- no_error_log
68+
[error]
69+
70+
71+
72+
=== TEST 3: utils.str_replace_char() JIT compiles when no match
73+
--- config
74+
location /t {
75+
content_by_lua_block {
76+
local utils = require "resty.core.utils"
77+
78+
for i = 1, $TEST_NGINX_HOTLOOP * 10 do
79+
utils.str_replace_char("Header_Name", "-", "_")
80+
end
81+
}
82+
}
83+
--- ignore_response_body
84+
--- error_log eval
85+
qr/\[TRACE\s+\d+ content_by_lua\(nginx\.conf:\d+\):4 loop\]/,
86+
--- no_error_log
87+
[error]
88+
89+
90+
91+
=== TEST 4: utils.str_replace_char() replacing more than one character is not supported
92+
--- config
93+
location /t {
94+
content_by_lua_block {
95+
local utils = require "resty.core.utils"
96+
97+
local strings = {
98+
"Header01Name",
99+
"01Header01Name01",
100+
"Header0Name",
101+
"Header1Name",
102+
"Hello world",
103+
}
104+
105+
for i = 1, #strings do
106+
ngx.say(utils.str_replace_char(strings[i], "02", "02"))
107+
end
108+
}
109+
}
110+
--- response_body
111+
Header01Name
112+
01Header01Name01
113+
Header0Name
114+
Header1Name
115+
Hello world

0 commit comments

Comments
 (0)