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 f9a8a26 feature: add a new option, decide if we remove the "/" at the end of … (#1766) f9a8a26 is described below commit f9a8a26dd4ba6f114c382a0157ae6ba956ad26dd Author: YuanSheng Wang <membp...@gmail.com> AuthorDate: Wed Jul 29 19:25:30 2020 +0800 feature: add a new option, decide if we remove the "/" at the end of … (#1766) * feature: add a new option, decide if we remove the "/" at the end of the URI before route matching. fix #1765 --- apisix/init.lua | 19 +++++-- conf/config.yaml | 2 + t/lib/server.lua | 4 ++ t/router/radixtree-uri-keep-end-slash.t | 96 +++++++++++++++++++++++++++++++++ t/router/radixtree-uri-sanity.t | 55 +++++++++++++++++++ 5 files changed, 172 insertions(+), 4 deletions(-) diff --git a/apisix/init.lua b/apisix/init.lua index ad1131b..354290d 100644 --- a/apisix/init.lua +++ b/apisix/init.lua @@ -33,8 +33,10 @@ local ipairs = ipairs local tostring = tostring local type = type local ngx_now = ngx.now +local str_byte = string.byte +local str_sub = string.sub local load_balancer - +local local_conf local dns_resolver local lru_resolved_domain @@ -97,7 +99,7 @@ function _M.http_init_worker() require("apisix.debug").init_worker() require("apisix.upstream").init_worker() - local local_conf = core.config.local_conf() + local_conf = core.config.local_conf() local dns_resolver_valid = local_conf and local_conf.apisix and local_conf.apisix.dns_resolver_valid @@ -322,6 +324,15 @@ function _M.http_access_phase() api_ctx.global_rules = router.global_rules end + if local_conf.apisix and local_conf.apisix.delete_uri_tail_slash then + local uri = api_ctx.var.uri + if str_byte(uri, #uri) == str_byte("/") then + api_ctx.var.uri = str_sub(api_ctx.var.uri, 1, #uri - 1) + core.log.info("remove the end of uri '/', current uri: ", + api_ctx.var.uri) + end + end + router.router_http.match(api_ctx) core.log.info("matched route: ", @@ -585,7 +596,7 @@ end local function cors_admin() - local local_conf = core.config.local_conf() + local_conf = core.config.local_conf() if local_conf.apisix and not local_conf.apisix.enable_admin_cors then return end @@ -649,7 +660,7 @@ function _M.stream_init_worker() load_balancer = require("apisix.balancer").run - local local_conf = core.config.local_conf() + local_conf = core.config.local_conf() local dns_resolver_valid = local_conf and local_conf.apisix and local_conf.apisix.dns_resolver_valid diff --git a/conf/config.yaml b/conf/config.yaml index 58e1139..aea1e85 100644 --- a/conf/config.yaml +++ b/conf/config.yaml @@ -74,6 +74,8 @@ apisix: name: "viewer" key: 4054f7cf07e344346cd3f287985e76a2 role: viewer + + delete_uri_tail_slash: false # delete the '/' at the end of the URI router: http: 'radixtree_uri' # radixtree_uri: match route by uri(base on radixtree) # radixtree_host_uri: match route by host + uri(base on radixtree) diff --git a/t/lib/server.lua b/t/lib/server.lua index e34602c..dfbead6 100644 --- a/t/lib/server.lua +++ b/t/lib/server.lua @@ -28,6 +28,10 @@ function _M.hello1() ngx.say("hello1 world") end +function _M.hello_() + ngx.say("hello world") +end + function _M.server_port() ngx.print(ngx.var.server_port) end diff --git a/t/router/radixtree-uri-keep-end-slash.t b/t/router/radixtree-uri-keep-end-slash.t new file mode 100644 index 0000000..ec6e9ba --- /dev/null +++ b/t/router/radixtree-uri-keep-end-slash.t @@ -0,0 +1,96 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +use t::APISIX 'no_plan'; + +repeat_each(1); +log_level('info'); +worker_connections(256); +no_root_location(); +no_shuffle(); + +sub read_file($) { + my $infile = shift; + open my $in, $infile + or die "cannot open $infile for reading: $!"; + my $cert = do { local $/; <$in> }; + close $in; + $cert; +} + +our $yaml_config = read_file("conf/config.yaml"); +$yaml_config =~ s/node_listen: 9080/node_listen: 1984/; +$yaml_config =~ s/enable_heartbeat: true/enable_heartbeat: false/; +$yaml_config =~ s/admin_key:/disable_admin_key:/; +$yaml_config =~ s/delete_uri_tail_slash: false/delete_uri_tail_slash: true/; + +run_tests(); + +__DATA__ + +=== TEST 1: 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, + [[{ + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/hello" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- yaml_config eval: $::yaml_config +--- request +GET /t +--- response_body +passed +--- no_error_log +[error] + + + +=== TEST 2: hit route +--- request +GET /hello +--- yaml_config eval: $::yaml_config +--- response_body +hello world +--- no_error_log +[error] + + + +=== TEST 3: hit route +--- request +GET /hello/ +--- yaml_config eval: $::yaml_config +--- response_body +hello world +--- no_error_log +[error] diff --git a/t/router/radixtree-uri-sanity.t b/t/router/radixtree-uri-sanity.t index 7c365a1..0cd6101 100644 --- a/t/router/radixtree-uri-sanity.t +++ b/t/router/radixtree-uri-sanity.t @@ -268,3 +268,58 @@ GET /t passed --- no_error_log [error] + + + +=== TEST 13: set route(id: 1) +--- 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, + [[{ + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/hello" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- yaml_config eval: $::yaml_config +--- request +GET /t +--- response_body +passed +--- no_error_log +[error] + + + +=== TEST 14: hit route with /hello +--- request +GET /hello +--- yaml_config eval: $::yaml_config +--- response_body +hello world +--- no_error_log +[error] + + + +=== TEST 15: miss route +--- request +GET /hello/ +--- yaml_config eval: $::yaml_config +--- error_code: 404 +--- no_error_log +[error]