mod_http_index/mod_http_index.lua
changeset 1829 1b5c817cb642
parent 1573 0d8cc6971cdb
child 1830 ae2235d6c3f8
equal deleted inserted replaced
1828:8435e1766054 1829:1b5c817cb642
     1 local st = require "util.stanza";
       
     2 local url = require"socket.url";
     1 local url = require"socket.url";
       
     2 local render = require"util.interpolation".new("%b{}", require"util.stanza".xml_escape);
     3 
     3 
     4 module:depends"http";
     4 module:depends"http";
     5 
     5 
     6 -- local dump = require"util.serialization".new"dump".serialize;
       
     7 
       
     8 local function template(data)
       
     9 	--[[ DOC
       
    10 	Like util.template, but deals with plain text
       
    11 	Returns a closure that is called with a table of values
       
    12 	{name} is substituted for values["name"] and is XML escaped
       
    13 	{name!} is substituted without XML escaping
       
    14 	{name?} is optional and is replaced with an empty string if no value exists
       
    15 	]]
       
    16 	return function(values)
       
    17 		return (data:gsub("{([^}]-)(%p?)}", function (name, opt)
       
    18 			local value = values[name];
       
    19 			if value then
       
    20 				if opt ~= "!" then
       
    21 					return st.xml_escape(value);
       
    22 				end
       
    23 				return value;
       
    24 			elseif opt == "?" then
       
    25 				return "";
       
    26 			end
       
    27 		end));
       
    28 	end
       
    29 end
       
    30 
       
    31 -- TODO Move templates into files
     6 -- TODO Move templates into files
    32 local base = template(template[[
     7 local base_template = [[
    33 <!DOCTYPE html>
     8 <!DOCTYPE html>
    34 <html>
     9 <html>
    35 <head>
    10 <head>
    36 <meta charset="utf-8">
    11 <meta charset="utf-8">
    37 <meta name="viewport" content="width=device-width, initial-scale=1">
    12 <meta name="viewport" content="width=device-width, initial-scale=1">
    69 </style>
    44 </style>
    70 </head>
    45 </head>
    71 <body>
    46 <body>
    72 <header>
    47 <header>
    73 <h1>{title}</h1>
    48 <h1>{title}</h1>
    74 {header!}
       
    75 </header>
    49 </header>
    76 <hr>
    50 <hr>
    77 <div class="content">
    51 <div class="content">
    78 {body!}
    52 <nav>
       
    53 <ul>{items#
       
    54 <li><a href="{item.url}" title="{item.module}">{item.name}</a></li>}
       
    55 </ul>
       
    56 </nav>
    79 </div>
    57 </div>
    80 <hr>
    58 <hr>
    81 <footer>
    59 <footer>
    82 {footer!}
       
    83 <br>
    60 <br>
    84 <div class="powered-by">Prosody {prosody_version?}</div>
    61 <div class="powered-by">Prosody {prosody_version?}</div>
    85 </footer>
    62 </footer>
    86 </body>
    63 </body>
    87 </html>
    64 </html>
    88 ]] { prosody_version = prosody.version, mod_name = module.name });
    65 ]];
    89 
    66 
    90 local canonical = module:http_url(nil, "/");
    67 local canonical = module:http_url(nil, "/");
    91 local page_template = template(base{
       
    92 	canonical = canonical;
       
    93 	title = "HTTP stuff";
       
    94 	header = "";
       
    95 	body = [[
       
    96 <nav>
       
    97 <ul>
       
    98 {lines!}
       
    99 </ul>
       
   100 </nav>
       
   101 ]];
       
   102 	footer = "";
       
   103 });
       
   104 local line_template = template[[
       
   105 <li><a href="{url}" title="{module}">{name}</a></li>
       
   106 ]];
       
   107 
    68 
   108 local function relative(base, link)
    69 local function relative(base, link)
   109 	base = url.parse(base);
    70 	base = url.parse(base);
   110 	link = url.parse(link);
    71 	link = url.parse(link);
   111 	for k,v in pairs(base) do
    72 	for k,v in pairs(base) do
   115 	end
    76 	end
   116 	return url.build(link);
    77 	return url.build(link);
   117 end
    78 end
   118 
    79 
   119 local function handler(event)
    80 local function handler(event)
   120 	local items = module:get_host_items("http-provider");
    81 	local host_items = module:get_host_items("http-provider");
   121 	local item;
    82 	local http_apps = {}
   122 	for i = 1, #items do
    83 	for _, item in ipairs(host_items) do
   123 		item = items[i];
       
   124 		if module.name ~= item._provided_by then
    84 		if module.name ~= item._provided_by then
   125 			items[i] = line_template{
    85 			table.insert(http_apps, {
   126 				name = item.name;
    86 				name = item.name;
   127 				module = "mod_" .. item._provided_by;
    87 				module = "mod_" .. item._provided_by;
   128 				url = relative(canonical, module:http_url(item.name, item.default_path));
    88 				url = relative(canonical, module:http_url(item.name, item.default_path));
   129 			};
    89 			});
   130 		else
       
   131 			items[i] = "";
       
   132 		end
    90 		end
   133 	end
    91 	end
   134 	event.response.headers.content_type = "text/html";
    92 	event.response.headers.content_type = "text/html";
   135 	return page_template{
    93 	return render(base_template, {
   136 		lines = table.concat(items);
    94 		title = "HTTP Apps";
   137 	};
    95 		items = http_apps;
       
    96 		prosody_version = prosody.version;
       
    97 		mod_name = module.name;
       
    98 		canonical = canonical;
       
    99 	});
   138 end
   100 end
   139 
   101 
   140 module:provides("http", {
   102 module:provides("http", {
   141 	route = {
   103 	route = {
   142 		["GET /"] = handler;
   104 		["GET /"] = handler;