Software /
code /
prosody
Comparison
plugins/mod_http.lua @ 12443:17d87fb2312a 0.12
mod_http: Reintroduce support for disabling or limiting CORS (fixes #1730)
This is far better than pre-0.12, because we now have a universal way to
configure and enable/disable CORS on a per-module basis.
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Mon, 28 Mar 2022 14:40:21 +0100 |
parent | 12269:a19d435dee90 |
child | 12444:b33558969b3e |
comparison
equal
deleted
inserted
replaced
12441:dc6263625069 | 12443:17d87fb2312a |
---|---|
29 | 29 |
30 server.set_option("body_size_limit", module:get_option_number("http_max_content_size")); | 30 server.set_option("body_size_limit", module:get_option_number("http_max_content_size")); |
31 server.set_option("buffer_size_limit", module:get_option_number("http_max_buffer_size")); | 31 server.set_option("buffer_size_limit", module:get_option_number("http_max_buffer_size")); |
32 | 32 |
33 -- CORS settings | 33 -- CORS settings |
34 local cors_overrides = module:get_option("http_cors_override", {}); | |
34 local opt_methods = module:get_option_set("access_control_allow_methods", { "GET", "OPTIONS" }); | 35 local opt_methods = module:get_option_set("access_control_allow_methods", { "GET", "OPTIONS" }); |
35 local opt_headers = module:get_option_set("access_control_allow_headers", { "Content-Type" }); | 36 local opt_headers = module:get_option_set("access_control_allow_headers", { "Content-Type" }); |
37 local opt_origins = module:get_option_set("access_control_allow_origins"); | |
36 local opt_credentials = module:get_option_boolean("access_control_allow_credentials", false); | 38 local opt_credentials = module:get_option_boolean("access_control_allow_credentials", false); |
37 local opt_max_age = module:get_option_number("access_control_max_age", 2 * 60 * 60); | 39 local opt_max_age = module:get_option_number("access_control_max_age", 2 * 60 * 60); |
38 | 40 |
39 local function get_http_event(host, app_path, key) | 41 local function get_http_event(host, app_path, key) |
40 local method, path = key:match("^(%S+)%s+(.+)$"); | 42 local method, path = key:match("^(%S+)%s+(.+)$"); |
107 module:log("warn", "No http ports enabled, can't generate an external URL"); | 109 module:log("warn", "No http ports enabled, can't generate an external URL"); |
108 end | 110 end |
109 return "http://disabled.invalid/"; | 111 return "http://disabled.invalid/"; |
110 end | 112 end |
111 | 113 |
112 local function apply_cors_headers(response, methods, headers, max_age, allow_credentials, origin) | 114 local function apply_cors_headers(response, methods, headers, max_age, allow_credentials, allowed_origins, origin) |
115 if allowed_origins and not allowed_origins[origin] then | |
116 return; | |
117 end | |
113 response.headers.access_control_allow_methods = tostring(methods); | 118 response.headers.access_control_allow_methods = tostring(methods); |
114 response.headers.access_control_allow_headers = tostring(headers); | 119 response.headers.access_control_allow_headers = tostring(headers); |
115 response.headers.access_control_max_age = tostring(max_age) | 120 response.headers.access_control_max_age = tostring(max_age) |
116 response.headers.access_control_allow_origin = origin or "*"; | 121 response.headers.access_control_allow_origin = origin or "*"; |
117 if allow_credentials then | 122 if allow_credentials then |
139 local app_handlers = apps[app_name]; | 144 local app_handlers = apps[app_name]; |
140 | 145 |
141 local app_methods = opt_methods; | 146 local app_methods = opt_methods; |
142 local app_headers = opt_headers; | 147 local app_headers = opt_headers; |
143 local app_credentials = opt_credentials; | 148 local app_credentials = opt_credentials; |
149 local app_origins; | |
150 if opt_origins and not (opt_origins:empty() or opt_origins:contains("*")) then | |
151 opt_origins = opt_origins._items; | |
152 end | |
144 | 153 |
145 local function cors_handler(event_data) | 154 local function cors_handler(event_data) |
146 local request, response = event_data.request, event_data.response; | 155 local request, response = event_data.request, event_data.response; |
147 apply_cors_headers(response, app_methods, app_headers, opt_max_age, app_credentials, request.headers.origin); | 156 apply_cors_headers(response, app_methods, app_headers, opt_max_age, app_credentials, app_origins, request.headers.origin); |
148 end | 157 end |
149 | 158 |
150 local function options_handler(event_data) | 159 local function options_handler(event_data) |
151 cors_handler(event_data); | 160 cors_handler(event_data); |
152 return ""; | 161 return ""; |
153 end | 162 end |
154 | 163 |
155 if event.item.cors then | 164 local cors = cors_overrides[app_name] or event.item.cors; |
156 local cors = event.item.cors; | 165 if cors then |
157 if cors.credentials ~= nil then | 166 if cors.enabled ~= false then |
158 app_credentials = cors.credentials; | 167 if cors.credentials ~= nil then |
159 end | 168 app_credentials = cors.credentials; |
160 if cors.headers then | 169 end |
161 for header, enable in pairs(cors.headers) do | 170 if cors.headers then |
162 if enable and not app_headers:contains(header) then | 171 for header, enable in pairs(cors.headers) do |
163 app_headers = app_headers + set.new { header }; | 172 if enable and not app_headers:contains(header) then |
164 elseif not enable and app_headers:contains(header) then | 173 app_headers = app_headers + set.new { header }; |
165 app_headers = app_headers - set.new { header }; | 174 elseif not enable and app_headers:contains(header) then |
175 app_headers = app_headers - set.new { header }; | |
176 end | |
177 end | |
178 end | |
179 if cors.origins then | |
180 if cors.origins == "*" or cors.origins[1] == "*" then | |
181 app_origins = nil; | |
182 else | |
183 app_origins = set.new(cors.origins)._items; | |
166 end | 184 end |
167 end | 185 end |
168 end | 186 end |
169 end | 187 end |
170 | 188 |