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)
31 -- Local dispatch database
32 local tree = {nodes={}}
37 -- Global request object
40 -- Active dispatched node
49 function build_url(...)
50 return luci.http.dispatcher() .. "/" .. table.concat(arg, "/")
53 -- Sends a 404 error code and renders the "error404" template if available
54 function error404(message)
55 luci.http.status(404, "Not Found")
56 message = message or "Not Found"
58 require("luci.template")
59 if not pcall(luci.template.render, "error404") then
60 luci.http.prepare_content("text/plain")
66 -- Sends a 500 error code and renders the "error500" template if available
67 function error500(message)
68 luci.http.status(500, "Internal Server Error")
70 require("luci.template")
71 if not pcall(luci.template.render, "error500", {message=message}) then
72 luci.http.prepare_content("text/plain")
78 -- Creates a request object for dispatching
79 function httpdispatch()
80 local pathinfo = luci.http.env.PATH_INFO or ""
83 for s in pathinfo:gmatch("([%w-]+)") do
84 table.insert(request, s)
90 -- Dispatches a request
92 if not built_tree then
99 for i, s in ipairs(request) do
101 if not c or c.leaf then
105 for k, v in pairs(c) do
112 require("luci.i18n").loadc(track.i18n)
115 if track.setgroup then
116 luci.sys.process.setgroup(track.setgroup)
119 if track.setuser then
120 luci.sys.process.setuser(track.setuser)
123 -- Init template engine
124 local tpl = require("luci.template")
125 tpl.viewns.translate = function(...) return require("luci.i18n").translate(...) end
126 tpl.viewns.controller = luci.http.dispatcher()
127 tpl.viewns.uploadctrl = luci.http.dispatcher_upload()
128 tpl.viewns.media = luci.config.main.mediaurlbase
129 tpl.viewns.resource = luci.config.main.resourcebase
131 -- Load default translation
132 require("luci.i18n").loadc("default")
135 if c and type(c.target) == "function" then
137 stat, mod = pcall(require, c.module)
139 luci.util.updfenv(c.target, mod)
142 stat, err = pcall(c.target)
151 -- Generates the dispatching tree
152 function createindex()
154 local path = luci.sys.libpath() .. "/controller/"
157 --[[if pcall(require, "fastindex") then
158 createindex_fastindex(path, suff)
160 createindex_plain(path, suff)
163 createindex_plain(path, suff)
168 -- Uses fastindex to create the dispatching tree
169 function createindex_fastindex(path, suffix)
170 local fi = fastindex.new("index")
171 fi.add(path .. "*" .. suffix)
172 fi.add(path .. "*/*" .. suffix)
175 for k, v in pairs(fi.indexes) do
180 -- Calls the index function of all available controllers
181 function createindex_plain(path, suffix)
182 local cachetime = nil
184 local controllers = luci.util.combine(
185 luci.fs.glob(path .. "*" .. suffix) or {},
186 luci.fs.glob(path .. "*/*" .. suffix) or {}
190 cachetime = luci.fs.mtime(indexcache)
192 if not cachetime then
193 luci.fs.mkdir(indexcache)
194 luci.fs.chmod(indexcache, "a=,u=rwx")
198 if not cachetime then
199 for i,c in ipairs(controllers) do
200 c = "luci.controller." .. c:sub(#path+1, #c-#suffix):gsub("/", ".")
201 stat, mod = pcall(require, c)
203 if stat and mod and type(mod.index) == "function" then
207 luci.fs.writefile(indexcache .. "/" .. c, string.dump(mod.index))
212 for i,c in ipairs(luci.fs.dir(indexcache)) do
213 if c:sub(1) ~= "." then
214 index[c] = loadfile(indexcache .. "/" .. c)
220 -- Creates the dispatching tree from the index
221 function createtree()
222 if not built_index then
228 for k, v in pairs(index) do
229 luci.util.updfenv(v, _M)
230 luci.util.extfenv(v, "_NAME", k)
232 local stat, err = pcall(v)
242 -- Shortcut for creating a dispatching node
243 function entry(path, target, title, order, add)
250 c.module = getfenv(2)._NAME
252 for k,v in pairs(add) do
259 -- Fetch a dispatching node
263 if arg[1] and type(arg[1]) == "table" then
267 for k,v in ipairs(arg) do
268 if not c.nodes[v] then
269 c.nodes[v] = {nodes={}, module=getfenv(2)._NAME}
287 function rewrite(n, ...)
291 table.remove(request, 1)
294 for i,r in ipairs(req) do
295 table.insert(request, i, r)
303 return function() getfenv()[name]() end
306 function template(name)
307 require("luci.template")
308 return function() luci.template.render(name) end
313 require("luci.template")
316 local stat, res = pcall(luci.cbi.load, model)
322 local stat, err = pcall(res.parse, res)
328 luci.template.render("cbi/header")
330 luci.template.render("cbi/footer")