mod_bosh: Support for cross-domain access control using CORS

Thu, 21 Jan 2010 15:07:52 +0000

author
Matthew Wild <mwild1@gmail.com>
date
Thu, 21 Jan 2010 15:07:52 +0000
changeset 2484
cf924f587410
parent 2483
2f235c57d713
child 2485
ace62f19076d

mod_bosh: Support for cross-domain access control using CORS

plugins/mod_bosh.lua file | annotate | diff | comparison | revisions
--- a/plugins/mod_bosh.lua	Thu Jan 21 14:53:01 2010 +0000
+++ b/plugins/mod_bosh.lua	Thu Jan 21 15:07:52 2010 +0000
@@ -34,6 +34,23 @@
 local default_headers = { ["Content-Type"] = "text/xml; charset=utf-8" };
 local session_close_reply = { headers = default_headers, body = st.stanza("body", { xmlns = xmlns_bosh, type = "terminate" }), attr = {} };
 
+local http_options, http_denied_options = { headers = {} }, { headers = {} };
+local cross_domain = module:get_option("cross_domain_bosh");
+if cross_domain ~= false then
+	http_options.headers["Access-Control-Allow-Methods"] = "GET, POST, OPTIONS";
+	http_options.headers["Access-Control-Allow-Headers"] = "Content-Type";
+	http_options.headers["Access-Control-Max-Age"] = "86400";
+
+	if cross_domain == true then
+		http_options.headers["Access-Control-Allow-Origin"] = "*";
+	elseif type(cross_domain) == "table" then
+		cross_domain = table.concat(cross_domain, ", ");
+	end
+	if type(cross_domain) == "string" then
+		http_options.headers["Access-Control-Allow-Origin"] = cross_domain;
+	end
+end
+
 local t_insert, t_remove, t_concat = table.insert, table.remove, table.concat;
 local os_time = os.time;
 
@@ -59,9 +76,25 @@
 	end
 end
 
+local function send_options_headers(request)
+	if cross_domain == nil then
+		local host = request.headers.host and request.headers.host:match("^[^:]+");
+		if hosts[host] then
+			http_options.headers["Access-Control-Allow-Origin"] = "http://"..host;
+		else
+			return http_denied_options; -- We don't want to reveal the hosts we serve
+		end
+	end
+	return http_options;
+end
+
 function handle_request(method, body, request)
 	if (not body) or request.method ~= "POST" then
-		return "<html><body>You really don't look like a BOSH client to me... what do you want?</body></html>";
+		if request.method == "OPTIONS" then
+			return send_options_headers(request);
+		else
+			return "<html><body>You really don't look like a BOSH client to me... what do you want?</body></html>";
+		end
 	end
 	if not method then
 		log("debug", "Request %s suffered error %s", tostring(request.id), body);

mercurial