# HG changeset patch # User Matthew Wild # Date 1335187019 -3600 # Node ID 7438b3c68576d61f034d7b6662ad2ad2ccc4a5bc # Parent 24524d70a50a73e957bec333e29dca47b232ffc6 mod_http: Revamp module for new API and config diff -r 24524d70a50a -r 7438b3c68576 plugins/mod_http.lua --- a/plugins/mod_http.lua Mon Apr 23 14:15:07 2012 +0100 +++ b/plugins/mod_http.lua Mon Apr 23 14:16:59 2012 +0100 @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2010 Matthew Wild --- Copyright (C) 2008-2010 Waqas Hussain +-- Copyright (C) 2008-2012 Matthew Wild +-- Copyright (C) 2008-2012 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -8,67 +8,68 @@ module:set_global(); ---local sessions = module:shared("sessions"); +local parse_url = require "socket.url".parse; +local server = require "net.http.server"; + +local function normalize_path(path) + if path:sub(1,1) ~= "/" then path = "/"..path; end + if path:sub(-1,-1) == "/" then path = path:sub(1, -2); end + return path; +end ---[[function listener.associate_session(conn, session) - sessions[conn] = session; -end]] - -local NULL = {}; -local handlers = {}; +local function get_http_event(http_module, app_name, key) + local method, path = key:match("^(%S+)%s+(.+)$"); + if not method and key:sub(1,1) == "/" then + method, path = "GET", key; + else + return nil; + end + path = normalize_path(path); + local app_path = normalize_path(http_module:get_option_string(app_name.."_http_path", "/"..app_name)); + return method:upper().." "..http_module.host..app_path..path; +end -function build_handlers(host) - if not hosts[host] then return; end - local h = {}; - handlers[host] = h; - - for mod_name, module in pairs(modulemanager.get_modules(host)) do - module = module.module; - if module.items then - for _, item in ipairs(module.items["http-handler"] or NULL) do - local previous = handlers[item.path]; - if not previous and item.path then - h[item.path] = item; +function module.add_host(module) + local apps = {}; + module.environment.apps = apps; + local function http_app_added(event) + local app_name = event.item.name; + if not app_name then + -- TODO: Link to docs + module:log("error", "HTTP app has no 'name', add one or use module:provides('http', app)"); + return; + end + apps[app_name] = apps[app_name] or {}; + local app_handlers = apps[app_name]; + for key, handler in pairs(event.item.route or {}) do + local event_name = get_http_event(module, app_name, key); + if event_name then + if not app_handlers[event_name] then + app_handlers[event_name] = handler; + server.add_handler(event_name, handler); + else + module:log("warn", "App %s added handler twice for '%s', ignoring", app_name, event_name); end + else + module:log("error", "Invalid route in %s: %q", app_name, key); end end end - - return h; -end -function clear_handlers(event) - handlers[event.source.host] = nil; -end -function get_handler(host, path) - local h = handlers[host] or build_handlers(host); - if h then - local item = h[path]; - return item and item.handler; + + local function http_app_removed(event) + local app_handlers = apps[event.item.name]; + apps[event.item.name] = nil; + for event, handler in pairs(app_handlers) do + server.remove_handler(event, handler); + end end + + module:handle_items("http-provider", http_app_added, http_app_removed); end -module:handle_items("http-handler", clear_handlers, clear_handlers, false); - -function http_handler(event) - local request, response = event.request, event.response; - - local handler = get_handler(request.headers.host:match("[^:]*"):lower(), request.path:match("[^?]*")); - if handler then - handler(request, response); - return true; - end -end - -local server = require "net.http.server"; -local listener = server.listener; -server.add_handler("*", http_handler); -function module.unload() - server.remove_handler("*", http_handler); -end ---require "net.http.server".listen_on(8080); module:add_item("net-provider", { name = "http"; - listener = listener; + listener = server.listener; default_port = 5280; multiplex = { pattern = "^[A-Z]"; @@ -77,7 +78,8 @@ module:add_item("net-provider", { name = "https"; - listener = listener; + listener = server.listener; + default_port = 5281; encryption = "ssl"; multiplex = { pattern = "^[A-Z]";