Skip to content

Commit 26bf209

Browse files
eugenepaniot0x501D
authored andcommitted
Add trailing_slash http route option
1 parent ae05f41 commit 26bf209

File tree

4 files changed

+92
-7
lines changed

4 files changed

+92
-7
lines changed

http/server.lua

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -981,10 +981,6 @@ local function httpd_stop(self)
981981
end
982982

983983
local function match_route(self, method, route)
984-
-- route must have '/' at the begin and end
985-
if string.match(route, '.$') ~= '/' then
986-
route = route .. '/'
987-
end
988984
if string.match(route, '^.') ~= '/' then
989985
route = '/' .. route
990986
end
@@ -995,8 +991,12 @@ local function match_route(self, method, route)
995991
local stash = {}
996992

997993
for _, r in pairs(self.routes) do
998-
if r.method == method or r.method == 'ANY' then
999-
local m = { string.match(route, r.match) }
994+
local sroute = route
995+
if r.method == method or r.method == 'ANY' then
996+
if r.trailing_slash and string.match(route, '.$') ~= '/' then
997+
sroute = route .. '/'
998+
end
999+
local m = { string.match(sroute, r.match) }
10001000
local nfit
10011001
if #m > 0 then
10021002
if #r.stash > 0 then
@@ -1145,6 +1145,7 @@ local function add_route(self, opts, sub)
11451145
end
11461146

11471147
opts = extend({method = 'ANY'}, opts, false)
1148+
opts = extend({trailing_slash = true}, opts, false)
11481149

11491150
local ctx
11501151
local action
@@ -1206,7 +1207,7 @@ local function add_route(self, opts, sub)
12061207
table.insert(stash, name)
12071208
end
12081209

1209-
if string.match(opts.match, '.$') ~= '/' then
1210+
if string.match(opts.match, '.$') ~= '/' and opts.trailing_slash then
12101211
opts.match = opts.match .. '/'
12111212
end
12121213
if string.match(opts.match, '^.') ~= '/' then

test/helpers.lua

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ helpers.cfgserv = function(opts)
3636
:route({path = '/test', file = 'test.html.el' },
3737
function(cx) return cx:render({ title = 'title: 123' }) end)
3838

39+
:route({path = '/trailing_slash_f/a/b/*c', trailing_slash = false},
40+
function(req) return req:render({text = req:stash("c")}) end)
41+
:route({path = '/trailing_slash_t/a/b/*c', trailing_slash = true},
42+
function(req) return req:render({text = req:stash("c")}) end)
3943
return httpd
4044
end
4145

test/integration/http_server_requests_test.lua

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,3 +417,69 @@ g.test_content_type_header_without_render = function()
417417
t.assert_equals(r.status, 200)
418418
t.assert_equals(r.headers['content-type'], 'text/plain; charset=utf-8', 'content-type header')
419419
end
420+
421+
g.test_trailing_slash_f_get = function()
422+
local r = http_client.get(helpers.base_uri .. '/trailing_slash_f/a/b/c')
423+
t.assert_equals(r.status, 200)
424+
t.assert_equals(r.body, 'c')
425+
end
426+
427+
g.test_trailing_slash_f_get_with_slash_at_begging = function()
428+
local r = http_client.get(helpers.base_uri .. '/trailing_slash_f/a/b//c')
429+
t.assert_equals(r.status, 200)
430+
t.assert_equals(r.body, '/c')
431+
end
432+
433+
g.test_trailing_slash_f_get_with_slash_at_begging_and_end = function()
434+
local r = http_client.get(helpers.base_uri .. '/trailing_slash_f/a/b//c/')
435+
t.assert_equals(r.status, 200)
436+
t.assert_equals(r.body, '/c/')
437+
end
438+
439+
g.test_trailing_slash_f_get_with_slash = function()
440+
local r = http_client.get(helpers.base_uri .. '/trailing_slash_f/a/b/c/')
441+
t.assert_equals(r.status, 200)
442+
t.assert_equals(r.body, 'c/')
443+
end
444+
445+
g.test_trailing_slash_f_get_with_encoded_slash_begging = function()
446+
local r = http_client.get(helpers.base_uri .. '/trailing_slash_f/a/b/%2Fc')
447+
t.assert_equals(r.status, 200)
448+
t.assert_equals(r.body, '/c')
449+
end
450+
451+
g.test_trailing_slash_f_get_with_encoded_slash_begging_and_end = function()
452+
local r = http_client.get(helpers.base_uri .. '/trailing_slash_f/a/b/%2Fc%2F')
453+
t.assert_equals(r.status, 200)
454+
t.assert_equals(r.body, '/c/')
455+
end
456+
457+
g.test_trailing_slash_f_get_html = function()
458+
local r = http_client.get(helpers.base_uri .. '/trailing_slash_f/a/b/c.htm')
459+
t.assert_equals(r.status, 200)
460+
t.assert_equals(r.body, 'c.htm')
461+
end
462+
463+
g.test_trailing_slash_f_get_long = function()
464+
local r = http_client.get(helpers.base_uri .. '/trailing_slash_f/a/b/c/d/e')
465+
t.assert_equals(r.status, 200)
466+
t.assert_equals(r.body, 'c/d/e')
467+
end
468+
469+
g.test_trailing_slash_f_get_long_with_slash_end = function()
470+
local r = http_client.get(helpers.base_uri .. '/trailing_slash_f/a/b/c/d/e/')
471+
t.assert_equals(r.status, 200)
472+
t.assert_equals(r.body, 'c/d/e/')
473+
end
474+
475+
g.test_trailing_slash_t_get_with_slash_at_begging_and_end = function()
476+
local r = http_client.get(helpers.base_uri .. '/trailing_slash_t/a/b//c/')
477+
t.assert_equals(r.status, 200)
478+
t.assert_equals(r.body, '/c')
479+
end
480+
481+
g.test_trailing_slash_t_get_with_encoded_slash_begging_and_end = function()
482+
local r = http_client.get(helpers.base_uri .. '/trailing_slash_t/a/b/%2Fc%2F')
483+
t.assert_equals(r.status, 200)
484+
t.assert_equals(r.body, '/c')
485+
end

test/integration/http_server_url_match_test.lua

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,18 @@ g.test_server_url_match = function()
4646
'-123-dea/1/2/3', '/abb-123-dea/1/2/3/cde')
4747
t.assert_equals(httpd:match('GET', '/banners/1wulc.z8kiy.6p5e3').stash.token,
4848
'1wulc.z8kiy.6p5e3', 'stash with dots')
49+
50+
t.assert_equals(httpd:match('GET', '/trailing_slash_t/a/b/c').endpoint.path, '/trailing_slash_t/a/b/*c')
51+
t.assert_equals(httpd:match('GET', '/trailing_slash_t/a/b/c').stash.c, 'c')
52+
t.assert_equals(httpd:match('GET', '/trailing_slash_t/a/b//c/').endpoint.path, '/trailing_slash_t/a/b/*c')
53+
t.assert_equals(httpd:match('GET', '/trailing_slash_t/a/b//c/').stash.c, '/c')
54+
55+
t.assert_equals(httpd:match('GET', '/trailing_slash_f/a/b/c').endpoint.path, '/trailing_slash_f/a/b/*c')
56+
t.assert_equals(httpd:match('GET', '/trailing_slash_f/a/b/c').stash.c, 'c')
57+
t.assert_equals(httpd:match('GET', '/trailing_slash_f/a/b//c').endpoint.path, '/trailing_slash_f/a/b/*c')
58+
t.assert_equals(httpd:match('GET', '/trailing_slash_f/a/b//c').stash.c, '/c')
59+
t.assert_equals(httpd:match('GET', '/trailing_slash_f/a/b//c/').endpoint.path, '/trailing_slash_f/a/b/*c')
60+
t.assert_equals(httpd:match('GET', '/trailing_slash_f/a/b//c/').stash.c, '/c/')
61+
t.assert_equals(httpd:match('GET', '/trailing_slash_f/a/b/c.htm').endpoint.path, '/trailing_slash_f/a/b/*c')
62+
t.assert_equals(httpd:match('GET', '/trailing_slash_f/a/b/c.htm').stash.c, 'c.htm')
4963
end

0 commit comments

Comments
 (0)