5 The request dispatcher and module dispatcher generators
11 Copyright 2008 Steven Barth <steven@midlink.org>
13 Licensed under the Apache License, Version 2.0 (the "License");
14 you may not use this file except in compliance with the License.
15 You may obtain a copy of the License at
17 http://www.apache.org/licenses/LICENSE-2.0
19 Unless required by applicable law or agreed to in writing, software
20 distributed under the License is distributed on an "AS IS" BASIS,
21 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 See the License for the specific language governing permissions and
23 limitations under the License.
26 module("luci.dispatcher", package.seeall)
30 require("luci.fastindex")
33 if (os.time() < luci.fs.mtime(luci.sys.libpath() .. "/dispatcher.lua")) then
34 os.execute('date -s '..os.date('%m%d%H%M%Y', luci.fs.mtime(luci.sys.libpath() .. "/dispatcher.lua"))..' > /dev/null 2>&1')
37 -- Local dispatch database
38 local tree = {nodes={}}
43 -- Global request object
46 -- Active dispatched node
57 function build_url(...)
58 return luci.http.dispatcher() .. "/" .. table.concat(arg, "/")
61 -- Sends a 404 error code and renders the "error404" template if available
62 function error404(message)
63 luci.http.status(404, "Not Found")
64 message = message or "Not Found"
66 require("luci.template")
67 if not pcall(luci.template.render, "error404") then
68 luci.http.prepare_content("text/plain")
74 -- Sends a 500 error code and renders the "error500" template if available
75 function error500(message)
76 luci.http.status(500, "Internal Server Error")
78 require("luci.template")
79 if not pcall(luci.template.render, "error500", {message=message}) then
80 luci.http.prepare_content("text/plain")
86 -- Creates a request object for dispatching
87 function httpdispatch()
88 local pathinfo = luci.http.env.PATH_INFO or ""
91 for s in pathinfo:gmatch("([%w-]+)") do
92 table.insert(request, s)
98 -- Dispatches a request
100 if not built_tree then
107 for i, s in ipairs(request) do
109 if not c or c.leaf then
113 for k, v in pairs(c) do
120 require("luci.i18n").loadc(track.i18n)
123 if track.setgroup then
124 luci.sys.process.setgroup(track.setgroup)
127 if track.setuser then
128 luci.sys.process.setuser(track.setuser)
131 -- Init template engine
132 local tpl = require("luci.template")
133 tpl.viewns.translate = function(...) return require("luci.i18n").translate(...) end
134 tpl.viewns.controller = luci.http.dispatcher()
135 tpl.viewns.uploadctrl = luci.http.dispatcher_upload()
136 tpl.viewns.media = luci.config.main.mediaurlbase
137 tpl.viewns.resource = luci.config.main.resourcebase
138 tpl.viewns.REQUEST_URI = luci.http.env.SCRIPT_NAME .. luci.http.env.PATH_INFO
141 if c and type(c.target) == "function" then
143 stat, mod = pcall(require, c.module)
145 luci.util.updfenv(c.target, mod)
148 stat, err = pcall(c.target)
157 -- Generates the dispatching tree
158 function createindex()
160 local path = luci.sys.libpath() .. "/controller/"
161 local suffix = ".lua"
164 fi = luci.fastindex.new("index")
165 fi.add(path .. "*" .. suffix)
166 fi.add(path .. "*/*" .. suffix)
170 for k, v in pairs(fi.indexes) do
177 -- Creates the dispatching tree from the index
178 function createtree()
179 if not built_index then
185 -- Load default translation
186 luci.i18n.loadc("default")
188 local scope = luci.util.clone(_G)
189 for k,v in pairs(_M) do
190 if type(v) == "function" then
195 for k, v in pairs(index) do
199 local stat, err = pcall(v)
209 -- Shortcut for creating a dispatching node
210 function entry(path, target, title, order, add)
217 c.module = getfenv(2)._NAME
219 for k,v in pairs(add) do
226 -- Fetch a dispatching node
230 if arg[1] and type(arg[1]) == "table" then
234 for k,v in ipairs(arg) do
235 if not c.nodes[v] then
236 c.nodes[v] = {nodes={}, module=getfenv(2)._NAME}
254 function rewrite(n, ...)
258 table.remove(request, 1)
261 for i,r in ipairs(req) do
262 table.insert(request, i, r)
270 return function() getfenv()[name]() end
273 function template(name)
274 require("luci.template")
275 return function() luci.template.render(name) end
280 require("luci.template")
283 local stat, res = pcall(luci.cbi.load, model)
289 local stat, err = pcall(res.parse, res)
295 luci.template.render("cbi/header")
297 luci.template.render("cbi/footer")