- Implements Apache APISIX packaging for Cloudron platform. - Includes Dockerfile, CloudronManifest.json, and start.sh. - Configured to use Cloudron's etcd addon. 🤖 Generated with Gemini CLI Co-Authored-By: Gemini <noreply@google.com>
154 lines
5.1 KiB
Lua
154 lines
5.1 KiB
Lua
--
|
|
-- 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.
|
|
--
|
|
local require = require
|
|
local radixtree = require("resty.radixtree")
|
|
local router = require("apisix.utils.router")
|
|
local service_fetch = require("apisix.http.service").get
|
|
local core = require("apisix.core")
|
|
local expr = require("resty.expr.v1")
|
|
local plugin_checker = require("apisix.plugin").plugin_checker
|
|
local event = require("apisix.core.event")
|
|
local ipairs = ipairs
|
|
local type = type
|
|
local error = error
|
|
local loadstring = loadstring
|
|
|
|
|
|
local _M = {}
|
|
|
|
|
|
function _M.create_radixtree_uri_router(routes, uri_routes, with_parameter)
|
|
routes = routes or {}
|
|
|
|
core.table.clear(uri_routes)
|
|
|
|
for _, route in ipairs(routes) do
|
|
if type(route) == "table" then
|
|
local status = core.table.try_read_attr(route, "value", "status")
|
|
-- check the status
|
|
if status and status == 0 then
|
|
goto CONTINUE
|
|
end
|
|
|
|
local filter_fun, err
|
|
if route.value.filter_func then
|
|
filter_fun, err = loadstring(
|
|
"return " .. route.value.filter_func,
|
|
"router#" .. route.value.id)
|
|
if not filter_fun then
|
|
core.log.error("failed to load filter function: ", err,
|
|
" route id: ", route.value.id)
|
|
goto CONTINUE
|
|
end
|
|
|
|
filter_fun = filter_fun()
|
|
end
|
|
|
|
local hosts = route.value.hosts or route.value.host
|
|
if not hosts and route.value.service_id then
|
|
local service = service_fetch(route.value.service_id)
|
|
if not service then
|
|
core.log.error("failed to fetch service configuration by ",
|
|
"id: ", route.value.service_id)
|
|
-- we keep the behavior that missing service won't affect the route matching
|
|
else
|
|
hosts = service.value.hosts
|
|
end
|
|
end
|
|
|
|
core.log.info("insert uri route: ",
|
|
core.json.delay_encode(route.value, true))
|
|
core.table.insert(uri_routes, {
|
|
paths = route.value.uris or route.value.uri,
|
|
methods = route.value.methods,
|
|
priority = route.value.priority,
|
|
hosts = hosts,
|
|
remote_addrs = route.value.remote_addrs
|
|
or route.value.remote_addr,
|
|
vars = route.value.vars,
|
|
filter_fun = filter_fun,
|
|
handler = function (api_ctx, match_opts)
|
|
api_ctx.matched_params = nil
|
|
api_ctx.matched_route = route
|
|
api_ctx.curr_req_matched = match_opts.matched
|
|
end
|
|
})
|
|
|
|
::CONTINUE::
|
|
end
|
|
end
|
|
|
|
event.push(event.CONST.BUILD_ROUTER, routes)
|
|
core.log.info("route items: ", core.json.delay_encode(uri_routes, true))
|
|
|
|
if with_parameter then
|
|
return radixtree.new(uri_routes)
|
|
else
|
|
return router.new(uri_routes)
|
|
end
|
|
end
|
|
|
|
|
|
function _M.match_uri(uri_router, api_ctx)
|
|
local match_opts = core.tablepool.fetch("route_match_opts", 0, 4)
|
|
match_opts.method = api_ctx.var.request_method
|
|
match_opts.host = api_ctx.var.host
|
|
match_opts.remote_addr = api_ctx.var.remote_addr
|
|
match_opts.vars = api_ctx.var
|
|
match_opts.matched = core.tablepool.fetch("matched_route_record", 0, 4)
|
|
|
|
local ok = uri_router:dispatch(api_ctx.var.uri, match_opts, api_ctx, match_opts)
|
|
core.tablepool.release("route_match_opts", match_opts)
|
|
return ok
|
|
end
|
|
|
|
|
|
-- additional check for synced route configuration, run after schema check
|
|
local function check_route(route)
|
|
local ok, err = plugin_checker(route)
|
|
if not ok then
|
|
return nil, err
|
|
end
|
|
|
|
if route.vars then
|
|
ok, err = expr.new(route.vars)
|
|
if not ok then
|
|
return nil, "failed to validate the 'vars' expression: " .. err
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
|
|
function _M.init_worker(filter)
|
|
local user_routes, err = core.config.new("/routes", {
|
|
automatic = true,
|
|
item_schema = core.schema.route,
|
|
checker = check_route,
|
|
filter = filter,
|
|
})
|
|
if not user_routes then
|
|
error("failed to create etcd instance for fetching /routes : " .. err)
|
|
end
|
|
|
|
return user_routes
|
|
end
|
|
|
|
|
|
return _M
|