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
132 if c and type(c.target) == "function" then
134 stat, mod = pcall(require, c.module)
136 luci.util.updfenv(c.target, mod)
139 stat, err = pcall(c.target)
148 -- Generates the dispatching tree
149 function createindex()
151 local path = luci.sys.libpath() .. "/controller/"
154 --[[if pcall(require, "fastindex") then
155 createindex_fastindex(path, suff)
157 createindex_plain(path, suff)
160 createindex_plain(path, suff)
165 -- Uses fastindex to create the dispatching tree
166 function createindex_fastindex(path, suffix)
167 local fi = fastindex.new("index")
168 fi.add(path .. "*" .. suffix)
169 fi.add(path .. "*/*" .. suffix)
172 for k, v in pairs(fi.indexes) do
177 -- Calls the index function of all available controllers
178 function createindex_plain(path, suffix)
179 local cachetime = nil
181 local controllers = luci.util.combine(
182 luci.fs.glob(path .. "*" .. suffix) or {},
183 luci.fs.glob(path .. "*/*" .. suffix) or {}
187 cachetime = luci.fs.mtime(indexcache)
189 if not cachetime then
190 luci.fs.mkdir(indexcache)
191 luci.fs.chmod(indexcache, "a=,u=rwx")
195 if not cachetime then
196 for i,c in ipairs(controllers) do
197 c = "luci.controller." .. c:sub(#path+1, #c-#suffix):gsub("/", ".")
198 stat, mod = pcall(require, c)
200 if stat and mod and type(mod.index) == "function" then
204 luci.fs.writefile(indexcache .. "/" .. c, string.dump(mod.index))
209 for i,c in ipairs(luci.fs.dir(indexcache)) do
210 if c:sub(1) ~= "." then
211 index[c] = loadfile(indexcache .. "/" .. c)
217 -- Creates the dispatching tree from the index
218 function createtree()
219 if not built_index then
225 -- Load default translation
226 luci.i18n.loadc("default")
229 for k,v in pairs(_M) do
230 if type(v) == "function" then
235 for k, v in pairs(index) do
239 local stat, err = pcall(v)
249 -- Shortcut for creating a dispatching node
250 function entry(path, target, title, order, add)
257 c.module = getfenv(2)._NAME
259 for k,v in pairs(add) do
266 -- Fetch a dispatching node
270 if arg[1] and type(arg[1]) == "table" then
274 for k,v in ipairs(arg) do
275 if not c.nodes[v] then
276 c.nodes[v] = {nodes={}, module=getfenv(2)._NAME}
294 function rewrite(n, ...)
298 table.remove(request, 1)
301 for i,r in ipairs(req) do
302 table.insert(request, i, r)
310 return function() getfenv()[name]() end
313 function template(name)
314 require("luci.template")
315 return function() luci.template.render(name) end
320 require("luci.template")
323 local stat, res = pcall(luci.cbi.load, model)
329 local stat, err = pcall(res.parse, res)
335 luci.template.render("cbi/header")
337 luci.template.render("cbi/footer")