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

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


The following commit(s) were added to refs/heads/master by this push:
     new ccd70dff2 feat(proxy-rewrite): create use_real_request_uri_unsafe 
option (#7401)
ccd70dff2 is described below

commit ccd70dff214f68a223d07e3a80148dbe92e9fa51
Author: İlteriş Yağıztegin Eroğlu 
<[email protected]>
AuthorDate: Tue Jul 19 08:55:20 2022 +0300

    feat(proxy-rewrite): create use_real_request_uri_unsafe option (#7401)
---
 apisix/plugins/proxy-rewrite.lua        | 37 ++++++++------
 docs/en/latest/plugins/proxy-rewrite.md | 17 ++++---
 t/admin/global-rules.t                  |  6 +--
 t/admin/global-rules2.t                 |  2 +-
 t/lib/server.lua                        |  4 ++
 t/plugin/proxy-rewrite.t                |  2 +-
 t/plugin/proxy-rewrite3.t               | 88 +++++++++++++++++++++++++++++++++
 7 files changed, 129 insertions(+), 27 deletions(-)

diff --git a/apisix/plugins/proxy-rewrite.lua b/apisix/plugins/proxy-rewrite.lua
index c1d7ec4f5..f53918003 100644
--- a/apisix/plugins/proxy-rewrite.lua
+++ b/apisix/plugins/proxy-rewrite.lua
@@ -78,6 +78,11 @@ local schema = {
             type = "object",
             minProperties = 1,
         },
+        use_real_request_uri_unsafe = {
+            description = "use real_request_uri instead, THIS IS VERY UNSAFE.",
+            type        = "boolean",
+            default     = false,
+        },
     },
     minProperties = 1,
 }
@@ -161,7 +166,9 @@ function _M.rewrite(conf, ctx)
     end
 
     local upstream_uri = ctx.var.uri
-    if conf.uri ~= nil then
+    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)
     elseif conf.regex_uri ~= nil then
         local uri, _, err = re_sub(ctx.var.uri, conf.regex_uri[1],
@@ -177,22 +184,24 @@ function _M.rewrite(conf, ctx)
         end
     end
 
-    local index = str_find(upstream_uri, "?")
-    if index then
-        upstream_uri = core.utils.uri_safe_encode(sub_str(upstream_uri, 1, 
index-1)) ..
-                       sub_str(upstream_uri, index)
-    else
-        upstream_uri = core.utils.uri_safe_encode(upstream_uri)
-    end
-
-    if ctx.var.is_args == "?" then
+    if not conf.use_real_request_uri_unsafe then
+        local index = str_find(upstream_uri, "?")
         if index then
-            ctx.var.upstream_uri = upstream_uri .. "&" .. (ctx.var.args or "")
+            upstream_uri = core.utils.uri_safe_encode(sub_str(upstream_uri, 1, 
index-1)) ..
+                           sub_str(upstream_uri, index)
+        else
+            upstream_uri = core.utils.uri_safe_encode(upstream_uri)
+        end
+
+        if ctx.var.is_args == "?" then
+            if index then
+                ctx.var.upstream_uri = upstream_uri .. "&" .. (ctx.var.args or 
"")
+            else
+                ctx.var.upstream_uri = upstream_uri .. "?" .. (ctx.var.args or 
"")
+            end
         else
-            ctx.var.upstream_uri = upstream_uri .. "?" .. (ctx.var.args or "")
+            ctx.var.upstream_uri = upstream_uri
         end
-    else
-        ctx.var.upstream_uri = upstream_uri
     end
 
     if conf.headers then
diff --git a/docs/en/latest/plugins/proxy-rewrite.md 
b/docs/en/latest/plugins/proxy-rewrite.md
index 1d1a87a17..6e2e71d62 100644
--- a/docs/en/latest/plugins/proxy-rewrite.md
+++ b/docs/en/latest/plugins/proxy-rewrite.md
@@ -33,14 +33,15 @@ The `proxy-rewrite` Plugin rewrites Upstream proxy 
information such as `scheme`,
 
 ## Attributes
 
-| Name      | Type          | Required | Default | Valid values                
                                                                                
                           | Description                                        
                                                                                
                                                                                
                                                                                
              [...]
-|-----------|---------------|----------|---------|----------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 [...]
-| scheme    | string        | False    | "http"  | ["http", "https"]           
                                                                                
                           | New upstream protocol scheme. This option is 
deprecated. Instead, it is recommended to set the `scheme` field in the 
Upstream.                                                                       
                                                                                
                            [...]
-| uri       | string        | False    |         |                             
                                                                                
                           | New Upstream forwarding address. Value supports 
[Nginx variables](https://nginx.org/en/docs/http/ngx_http_core_module.html). 
For example, `$arg_name`.                                                       
                                                                                
                    [...]
-| method    | string        | False    |         | ["GET", "POST", "PUT", 
"HEAD", "DELETE", "OPTIONS","MKCOL", "COPY", "MOVE", "PROPFIND", 
"PROPFIND","LOCK", "UNLOCK", "PATCH", "TRACE"] | Rewrites the HTTP method.      
                                                                                
                                                                                
                                                                                
                                  [...]
-| regex_uri | array[string] | False    |         |                             
                                                                                
                           | New upstream forwarding address. Regular 
expressions can be used to match the URL from client. If it matches, the URL 
template is forwarded to the Upstream otherwise, the URL from the client is 
forwarded. When both `uri` and `regex_uri` are configured, `uri` is used first. 
For example, `[" ^/iresty/(.*) [...]
-| host      | string        | False    |         |                             
                                                                                
                           | New Upstream host address.                         
                                                                                
                                                                                
                                                                                
              [...]
-| headers   | object        | False    |         |                             
                                                                                
                           | New Upstream headers. Headers are overwritten if 
they are already present otherwise, they are added to the present headers. To 
remove a header, set the header value to an empty string. The values in the 
header can contain Nginx variables like `$remote_addr` and `$client_addr`.      
                      [...]
+| Name                        | Type          | Required | Default | Valid 
values                                                                          
                                                 | Description                  
                                                                                
                                                                                
                                                                                
                  [...]
+|-----------------------------|---------------|----------|---------|----------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 [...]
+| scheme                      | string        | False    | "http"  | ["http", 
"https"]                                                                        
                                              | New upstream protocol scheme. 
This option is deprecated. Instead, it is recommended to set the `scheme` field 
in the Upstream.                                                                
                                                                                
                 [...]
+| uri                         | string        | False    |         |           
                                                                                
                                             | New Upstream forwarding address. 
Value supports [Nginx 
variables](https://nginx.org/en/docs/http/ngx_http_core_module.html). For 
example, `$arg_name`.                                                           
                                                                              
[...]
+| method                      | string        | False    |         | ["GET", 
"POST", "PUT", "HEAD", "DELETE", "OPTIONS","MKCOL", "COPY", "MOVE", "PROPFIND", 
"PROPFIND","LOCK", "UNLOCK", "PATCH", "TRACE"] | Rewrites the HTTP method.      
                                                                                
                                                                                
                                                                                
                [...]
+| regex_uri                   | array[string] | False    |         |           
                                                                                
                                             | New upstream forwarding address. 
Regular expressions can be used to match the URL from client. If it matches, 
the URL template is forwarded to the Upstream otherwise, the URL from the 
client is forwarded. When both `uri` and `regex_uri` are configured, `uri` is 
used first. For example, [...]
+| host                        | string        | False    |         |           
                                                                                
                                             | New Upstream host address.       
                                                                                
                                                                                
                                                                                
              [...]
+| headers                     | object        | False    |         |           
                                                                                
                                             | New Upstream headers. Headers 
are overwritten if they are already present otherwise, they are added to the 
present headers. To remove a header, set the header value to an empty string. 
The values in the header can contain Nginx variables like `$remote_addr` and 
`$client_addr`.          [...]
+| use_real_request_uri_unsafe | boolean       | False    | false   |           
                                                                                
                                             | Use real_request_uri (original 
$request_uri in nginx) to bypass URI normalization. **Enabling this is 
considered unsafe as it bypasses all URI normalization steps**.                 
                                                                                
                         [...]
 
 ## Enabling the Plugin
 
diff --git a/t/admin/global-rules.t b/t/admin/global-rules.t
index 422652a46..b153aeee1 100644
--- a/t/admin/global-rules.t
+++ b/t/admin/global-rules.t
@@ -447,7 +447,7 @@ passed
         }
     }
 --- response_body
-{"action":"set","node":{"key":"/apisix/global_rules/1","value":{"id":"1","plugins":{"proxy-rewrite":{"uri":"/"}}}}}
+{"action":"set","node":{"key":"/apisix/global_rules/1","value":{"id":"1","plugins":{"proxy-rewrite":{"uri":"/","use_real_request_uri_unsafe":false}}}}}
 --- request
 GET /t
 --- no_error_log
@@ -485,7 +485,7 @@ GET /t
         }
     }
 --- response_body
-{"action":"compareAndSwap","node":{"key":"/apisix/global_rules/1","value":{"id":"1","plugins":{"proxy-rewrite":{"uri":"/"}}}}}
+{"action":"compareAndSwap","node":{"key":"/apisix/global_rules/1","value":{"id":"1","plugins":{"proxy-rewrite":{"uri":"/","use_real_request_uri_unsafe":false}}}}}
 --- request
 GET /t
 --- no_error_log
@@ -521,7 +521,7 @@ GET /t
         }
     }
 --- response_body
-{"action":"get","node":{"key":"/apisix/global_rules/1","value":{"id":"1","plugins":{"proxy-rewrite":{"uri":"/"}}}}}
+{"action":"get","node":{"key":"/apisix/global_rules/1","value":{"id":"1","plugins":{"proxy-rewrite":{"uri":"/","use_real_request_uri_unsafe":false}}}}}
 --- request
 GET /t
 --- no_error_log
diff --git a/t/admin/global-rules2.t b/t/admin/global-rules2.t
index 6ff033b52..b84a80123 100644
--- a/t/admin/global-rules2.t
+++ b/t/admin/global-rules2.t
@@ -94,7 +94,7 @@ __DATA__
         }
     }
 --- response_body
-{"action":"set","node":{"key":"/apisix/global_rules/1","value":{"id":"1","plugins":{"proxy-rewrite":{"uri":"/"}}}}}
+{"action":"set","node":{"key":"/apisix/global_rules/1","value":{"id":"1","plugins":{"proxy-rewrite":{"uri":"/","use_real_request_uri_unsafe":false}}}}}
 
 
 
diff --git a/t/lib/server.lua b/t/lib/server.lua
index 029f463e5..a08ad227d 100644
--- a/t/lib/server.lua
+++ b/t/lib/server.lua
@@ -377,6 +377,10 @@ for i = 1, 100 do
     _M["print_uri_" .. i] = print_uri
 end
 
+function _M.print_uri_detailed()
+    ngx.say("ngx.var.uri: ", ngx.var.uri)
+    ngx.say("ngx.var.request_uri: ", ngx.var.request_uri)
+end
 
 function _M.headers()
     local args = ngx.req.get_uri_args()
diff --git a/t/plugin/proxy-rewrite.t b/t/plugin/proxy-rewrite.t
index fbca1b621..3070e631d 100644
--- a/t/plugin/proxy-rewrite.t
+++ b/t/plugin/proxy-rewrite.t
@@ -1097,7 +1097,7 @@ q: apisix)
 --- request
 GET /t
 --- response_body
-{"proxy-rewrite":{"headers":{"X-Api":"v2"},"uri":"/uri/plugin_proxy_rewrite"}}
+{"proxy-rewrite":{"headers":{"X-Api":"v2"},"uri":"/uri/plugin_proxy_rewrite","use_real_request_uri_unsafe":false}}
 --- no_error_log
 [error]
 
diff --git a/t/plugin/proxy-rewrite3.t b/t/plugin/proxy-rewrite3.t
index f98de527f..b67ef379e 100644
--- a/t/plugin/proxy-rewrite3.t
+++ b/t/plugin/proxy-rewrite3.t
@@ -200,3 +200,91 @@ passed
 GET /hello
 --- error_log
 plugin_proxy_rewrite get method: POST
+
+
+
+=== TEST 8: set route(unsafe uri not normalized at request)
+--- 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,
+                 [[{
+                        "methods": ["GET"],
+                        "plugins": {
+                            "proxy-rewrite": {
+                                "use_real_request_uri_unsafe": true
+                            }
+                        },
+                        "upstream": {
+                            "nodes": {
+                                "127.0.0.1:1980": 1
+                            },
+                            "type": "roundrobin"
+                        },
+                        "uri": "/print_uri_detailed"
+                }]]
+                )
+
+            if code >= 300 then
+                ngx.status = code
+            end
+            ngx.say(body)
+        }
+    }
+--- response_body
+passed
+
+
+
+=== TEST 9: unsafe uri not normalized at request
+--- request
+GET /print%5Furi%5Fdetailed HTTP/1.1
+--- response_body
+ngx.var.uri: /print_uri_detailed
+ngx.var.request_uri: /print%5Furi%5Fdetailed
+
+
+
+=== TEST 10: set route(safe uri not normalized at request)
+--- 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,
+                 [[{
+                        "methods": ["GET"],
+                        "plugins": {
+                            "proxy-rewrite": {
+                                "use_real_request_uri_unsafe": true
+                            }
+                        },
+                        "upstream": {
+                            "nodes": {
+                                "127.0.0.1:1980": 1
+                            },
+                            "type": "roundrobin"
+                        },
+                        "uri": "/print_uri_detailed"
+                }]]
+                )
+
+            if code >= 300 then
+                ngx.status = code
+            end
+            ngx.say(body)
+        }
+    }
+--- response_body
+passed
+
+
+
+=== TEST 11: safe uri not normalized at request
+--- request
+GET /print_uri_detailed HTTP/1.1
+--- response_body
+ngx.var.uri: /print_uri_detailed
+ngx.var.request_uri: /print_uri_detailed

Reply via email to