Skip to content

Commit

Permalink
fix(proxy-rewrite): escape args part if it's not from user conf (apac…
Browse files Browse the repository at this point in the history
  • Loading branch information
spacewander committed Mar 1, 2023
1 parent a9ac45e commit 237ba55
Show file tree
Hide file tree
Showing 3 changed files with 193 additions and 10 deletions.
8 changes: 7 additions & 1 deletion apisix/core/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -293,17 +293,21 @@ do
local _ctx
local n_resolved
local pat = [[(?<!\\)\$\{?(\w+)\}?]]
local _escaper

local function resolve(m)
local v = _ctx[m[1]]
if v == nil then
return ""
end
n_resolved = n_resolved + 1
if _escaper then
return _escaper(tostring(v))
end
return tostring(v)
end

function resolve_var(tpl, ctx)
function resolve_var(tpl, ctx, escaper)
n_resolved = 0
if not tpl then
return tpl, nil, n_resolved
Expand All @@ -316,8 +320,10 @@ do

-- avoid creating temporary function
_ctx = ctx
_escaper = escaper
local res, _, err = re_gsub(tpl, pat, resolve, "jo")
_ctx = nil
_escaper = nil
if not res then
return nil, err
end
Expand Down
27 changes: 22 additions & 5 deletions apisix/plugins/proxy-rewrite.lua
Original file line number Diff line number Diff line change
Expand Up @@ -165,13 +165,24 @@ function _M.rewrite(conf, ctx)
ctx.upstream_scheme = conf["scheme"]
end


local function escape_separator(s)
return re_sub(s, [[\?]], "%3F", "jo")
end

local upstream_uri = ctx.var.uri
local separator_escaped = false
if conf.use_real_request_uri_unsafe then
upstream_uri = ctx.var.real_request_uri
elseif conf.uri ~= nil then
upstream_uri = core.utils.resolve_var(conf.uri, ctx.var)
separator_escaped = true
upstream_uri = core.utils.resolve_var(conf.uri, ctx.var, escape_separator)
elseif conf.regex_uri ~= nil then
local uri, _, err = re_sub(ctx.var.uri, conf.regex_uri[1],
if not str_find(upstream_uri, "?") then
separator_escaped = true
end

local uri, _, err = re_sub(upstream_uri, conf.regex_uri[1],
conf.regex_uri[2], "jo")
if uri then
upstream_uri = uri
Expand All @@ -185,11 +196,17 @@ function _M.rewrite(conf, ctx)
end

if not conf.use_real_request_uri_unsafe then
local index = str_find(upstream_uri, "?")
local index
if separator_escaped then
index = str_find(upstream_uri, "?")
end

if index then
upstream_uri = core.utils.uri_safe_encode(sub_str(upstream_uri, 1, index-1)) ..
sub_str(upstream_uri, index)
upstream_uri = core.utils.uri_safe_encode(sub_str(upstream_uri, 1, index - 1)) ..
sub_str(upstream_uri, index)
else
-- The '?' may come from client request '%3f' when we use ngx.var.uri directly or
-- via regex_uri
upstream_uri = core.utils.uri_safe_encode(upstream_uri)
end

Expand Down
168 changes: 164 additions & 4 deletions t/plugin/proxy-rewrite3.t
Original file line number Diff line number Diff line change
Expand Up @@ -327,8 +327,6 @@ ngx.var.request_uri: /print_uri_detailed
GET /t
--- response_body
passed
--- no_error_log
[error]
Expand All @@ -339,5 +337,167 @@ GET /echo HTTP/1.1
X-Forwarded-Host: apisix.ai
--- response_headers
X-Forwarded-Host: test.com
--- no_error_log
[error]
=== TEST 14: set route
--- 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": {
"proxy-rewrite": {
"host": "test.xxxx.com"
}
},
"upstream": {
"nodes": {
"127.0.0.1:8125": 1
},
"type": "roundrobin"
},
"uri": "/hello*"
}]]
)
if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- request
GET /t
--- response_body
passed
=== TEST 15: hit with CRLF
--- request
GET /hello%3f0z=700%26a=c%20HTTP/1.1%0D%0AHost:google.com%0d%0a%0d%0a
--- http_config
server {
listen 8125;
location / {
content_by_lua_block {
ngx.say(ngx.var.host)
ngx.say(ngx.var.request_uri)
}
}
}
--- response_body
test.xxxx.com
/hello%3F0z=700&a=c%20HTTP/1.1%0D%0AHost:google.com%0D%0A%0D%0A
=== TEST 16: set route with uri
--- 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": {
"proxy-rewrite": {
"uri": "/$uri/remain",
"host": "test.xxxx.com"
}
},
"upstream": {
"nodes": {
"127.0.0.1:8125": 1
},
"type": "roundrobin"
},
"uri": "/hello*"
}]]
)
if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- request
GET /t
--- response_body
passed
=== TEST 17: hit with CRLF
--- request
GET /hello%3f0z=700%26a=c%20HTTP/1.1%0D%0AHost:google.com%0d%0a%0d%0a
--- http_config
server {
listen 8125;
location / {
content_by_lua_block {
ngx.say(ngx.var.host)
ngx.say(ngx.var.request_uri)
}
}
}
--- response_body
test.xxxx.com
//hello%253F0z=700&a=c%20HTTP/1.1%0D%0AHost:google.com%0D%0A%0D%0A/remain
=== TEST 18: regex_uri with args
--- 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": {
"proxy-rewrite": {
"regex_uri": ["^/test/(.*)/(.*)/(.*)", "/$1_$2_$3?a=c"]
}
},
"upstream": {
"nodes": {
"127.0.0.1:8125": 1
},
"type": "roundrobin"
},
"uri": "/test/*"
}]]
)
if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- request
GET /t
--- response_body
passed
=== TEST 19: hit
--- request
GET /test/plugin/proxy/rewrite HTTP/1.1
--- http_config
server {
listen 8125;
location / {
content_by_lua_block {
ngx.say(ngx.var.request_uri)
}
}
}
--- response_body
/plugin_proxy_rewrite?a=c

0 comments on commit 237ba55

Please sign in to comment.