Comparison

plugins/mod_http.lua @ 9793:9993fd021d19

mod_http: Solve CORS problems once and for all This blindly allows any cross-site requests. Future work should add an API to allow each HTTP app some influence over this for each HTTP path
author Kim Alvefur <zash@zash.se>
date Thu, 04 Oct 2018 12:22:12 +0200
parent 9504:cfbea3064aa9
child 9796:adfb29f44412
comparison
equal deleted inserted replaced
9792:561b0e20e901 9793:9993fd021d19
19 19
20 server.set_default_host(module:get_option_string("http_default_host")); 20 server.set_default_host(module:get_option_string("http_default_host"));
21 21
22 server.set_option("body_size_limit", module:get_option_number("http_max_content_size")); 22 server.set_option("body_size_limit", module:get_option_number("http_max_content_size"));
23 server.set_option("buffer_size_limit", module:get_option_number("http_max_buffer_size")); 23 server.set_option("buffer_size_limit", module:get_option_number("http_max_buffer_size"));
24
25 -- CORS settigs
26 local opt_methods = module:get_option_set("access_control_allow_methods", { "GET", "POST", "PUT", "OPTIONS" });
27 local opt_headers = module:get_option_set("access_control_allow_headers", { "Content-Type" });
28 local opt_max_age = module:get_option_number("access_control_max_age", 2 * 60 * 60);
24 29
25 local function get_http_event(host, app_path, key) 30 local function get_http_event(host, app_path, key)
26 local method, path = key:match("^(%S+)%s+(.+)$"); 31 local method, path = key:match("^(%S+)%s+(.+)$");
27 if not method then -- No path specified, default to "" (base path) 32 if not method then -- No path specified, default to "" (base path)
28 method, path = key, ""; 33 method, path = key, "";
81 end 86 end
82 module:log("warn", "No http ports enabled, can't generate an external URL"); 87 module:log("warn", "No http ports enabled, can't generate an external URL");
83 return "http://disabled.invalid/"; 88 return "http://disabled.invalid/";
84 end 89 end
85 90
91 local function apply_cors_headers(response, methods, headers, max_age, origin)
92 response.headers.access_control_allow_methods = tostring(methods);
93 response.headers.access_control_allow_headers = tostring(headers);
94 response.headers.access_control_max_age = tostring(max_age)
95 response.headers.access_control_allow_origin = origin or "*";
96 end
97
86 function module.add_host(module) 98 function module.add_host(module)
87 local host = module.host; 99 local host = module.host;
88 if host ~= "*" then 100 if host ~= "*" then
89 host = module:get_option_string("http_host", host); 101 host = module:get_option_string("http_host", host);
90 end 102 end
99 module:log("error", "HTTP app has no 'name', add one or use module:provides('http', app)"); 111 module:log("error", "HTTP app has no 'name', add one or use module:provides('http', app)");
100 return; 112 return;
101 end 113 end
102 apps[app_name] = apps[app_name] or {}; 114 apps[app_name] = apps[app_name] or {};
103 local app_handlers = apps[app_name]; 115 local app_handlers = apps[app_name];
116
117 local function cors_handler(event_data)
118 local request, response = event_data.request, event_data.response;
119 apply_cors_headers(response, opt_methods, opt_headers, opt_max_age, request.headers.origin);
120 end
121
104 for key, handler in pairs(event.item.route or {}) do 122 for key, handler in pairs(event.item.route or {}) do
105 local event_name = get_http_event(host, app_path, key); 123 local event_name = get_http_event(host, app_path, key);
106 if event_name then 124 if event_name then
107 if type(handler) ~= "function" then 125 if type(handler) ~= "function" then
108 local data = handler; 126 local data = handler;
119 module:hook_object_event(server, event_name:sub(1, -2), redir_handler, -1); 137 module:hook_object_event(server, event_name:sub(1, -2), redir_handler, -1);
120 end 138 end
121 if not app_handlers[event_name] then 139 if not app_handlers[event_name] then
122 app_handlers[event_name] = handler; 140 app_handlers[event_name] = handler;
123 module:hook_object_event(server, event_name, handler); 141 module:hook_object_event(server, event_name, handler);
142 module:hook_object_event(server, event_name, cors_handler, 1);
124 else 143 else
125 module:log("warn", "App %s added handler twice for '%s', ignoring", app_name, event_name); 144 module:log("warn", "App %s added handler twice for '%s', ignoring", app_name, event_name);
126 end 145 end
127 else 146 else
128 module:log("error", "Invalid route in %s, %q. See https://prosody.im/doc/developers/http#routes", app_name, key); 147 module:log("error", "Invalid route in %s, %q. See https://prosody.im/doc/developers/http#routes", app_name, key);