-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
204 additions
and
158 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
local utils = require "router-tree.utils" | ||
local Parser = require "router-tree.parser" | ||
local bit = utils.is_luajit and require "bit" | ||
|
||
local ipairs = ipairs | ||
local is_luajit = utils.is_luajit | ||
local starts_with = utils.starts_with | ||
|
||
local EMPTY = {} | ||
|
||
local METHODS = {} | ||
for i, name in ipairs({"GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS", "CONNECT", "TRACE", "PURGE"}) do | ||
METHODS[name] = bit.lshift(1, i - 1) | ||
-- ngx.log(ngx.WARN, "name: ", name, " val: ", METHODS[name]) | ||
end | ||
|
||
|
||
|
||
local Route = {} | ||
local mt = { __index = Route } | ||
|
||
local function extract_params(path) | ||
local params = {} | ||
local parser = Parser.parse(path, "default") | ||
local token = parser:next() | ||
while (token) do | ||
local c = string.sub(token, 1, 1) | ||
if c == ":" then | ||
table.insert(params, string.sub(token, 2)) | ||
elseif c == "*" then | ||
if #token > 1 then | ||
table.insert(params, string.sub(token, 2)) | ||
else | ||
table.insert(params, ":ext") | ||
end | ||
end | ||
token = parser:next() | ||
end | ||
return params | ||
end | ||
|
||
function Route.new(route) | ||
|
||
local self = { | ||
priority = route.priority, | ||
handler = route.handler or route.metadata, | ||
params = {}, | ||
} | ||
|
||
for _, path in ipairs(route.paths) do | ||
self.params[path] = extract_params(path) | ||
end | ||
|
||
if is_luajit then | ||
local methods_bit = 0 | ||
for _, method in ipairs(route.methods or EMPTY) do | ||
methods_bit = bit.bor(methods_bit, METHODS[method]) | ||
end | ||
self.method = methods_bit | ||
else | ||
local methods = {} | ||
for _, method in ipairs(route.methods or EMPTY) do | ||
methods[method] = true | ||
end | ||
self.method = methods | ||
end | ||
|
||
-- hosts | ||
local hosts = route.hosts | ||
if type(hosts) == "table" and #hosts > 0 then | ||
self.hosts = {} | ||
for _, h in ipairs(hosts) do | ||
local is_wildcard = false | ||
if h and h:sub(1, 1) == '*' then | ||
is_wildcard = true | ||
h = h:sub(2) | ||
end | ||
|
||
h = string.lower(h) | ||
table.insert(self.hosts, is_wildcard) | ||
table.insert(self.hosts, h) | ||
end | ||
|
||
elseif type(hosts) == "string" then | ||
local is_wildcard = false | ||
local host = string.lower(hosts) | ||
if host:sub(1, 1) == '*' then | ||
is_wildcard = true | ||
host = host:sub(2) | ||
end | ||
|
||
self.hosts = { is_wildcard, host} | ||
end | ||
|
||
return setmetatable(self, mt) | ||
end | ||
|
||
local function match_host(route_host_is_wildcard, route_host, request_host) | ||
if not route_host_is_wildcard then | ||
return route_host == request_host | ||
end | ||
|
||
return starts_with(request_host, route_host) | ||
end | ||
|
||
|
||
function Route:is_match(ctx) | ||
local route = self | ||
|
||
if route.method ~= 0 then | ||
local method = ctx.method | ||
-- 或者直接使用 map 就好 | ||
if not method or METHODS[method] == nil or bit.band(route.method, METHODS[method]) == 0 then | ||
return false | ||
end | ||
end | ||
|
||
-- log_info("route.hosts: ", type(route.hosts)) | ||
if route.hosts then | ||
local matched = false | ||
|
||
local hosts = route.hosts | ||
local host = ctx.host | ||
if host then | ||
local len = #hosts | ||
for i = 1, len, 2 do | ||
if match_host(hosts[i], hosts[i + 1], host) then | ||
if ctx and ctx.matched then | ||
if hosts[i] then | ||
ctx.matched._host = "*" .. hosts[i + 1] | ||
else | ||
ctx.matched._host = ctx.host | ||
end | ||
end | ||
matched = true | ||
break | ||
end | ||
end | ||
end | ||
|
||
if not matched then | ||
return false | ||
end | ||
end | ||
|
||
return true | ||
end | ||
|
||
|
||
return Route |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.