From c648694f33be91a7c009219188dcd8e1a97b0b35 Mon Sep 17 00:00:00 2001 From: batman-ezio Date: Tue, 16 Mar 2021 11:03:19 +0800 Subject: [PATCH 01/11] feat: add allow_origins_by_regex to cors plugin --- apisix/plugins/cors.lua | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/apisix/plugins/cors.lua b/apisix/plugins/cors.lua index fc90dc18b69f..5014f9ceaf18 100644 --- a/apisix/plugins/cors.lua +++ b/apisix/plugins/cors.lua @@ -19,6 +19,7 @@ local ngx = ngx local plugin_name = "cors" local str_find = core.string.find local re_gmatch = ngx.re.gmatch +local re_find = ngx.re.find local lrucache = core.lrucache.new({ @@ -151,6 +152,17 @@ local function set_cors_headers(conf, ctx) end end +local function get_match_domain(allow_origins, req_origin) + if allow_origins == req_origin or allow_origins == '*' then + return req_origin + else + local matched = re_find(req_origin, allow_origins, "jo") + if matched then + return req_origin + end + end +end + function _M.rewrite(conf, ctx) if ctx.var.request_method == "OPTIONS" then @@ -171,15 +183,20 @@ function _M.header_filter(conf, ctx) return 500, {message = "get multiple origin cache failed: " .. err} end + local match_domain + if multiple_origin then - if multiple_origin[req_origin] then - allow_origins = req_origin - else - return + for origin,i in pairs(multiple_origin) do + match_domain = get_match_domain(origin, req_origin) + if match_domain then + break + end end + else + match_domain = get_match_domain(allow_origins, req_origin) end - ctx.cors_allow_origins = allow_origins + ctx.cors_allow_origins = match_domain set_cors_headers(conf, ctx) end From 7798a285eebfd63ce0b37cec630463ed43f8e8ef Mon Sep 17 00:00:00 2001 From: batman-ezio Date: Tue, 16 Mar 2021 12:13:12 +0800 Subject: [PATCH 02/11] feat: add allow_origins_by_regex to cors plugin --- apisix/plugins/cors.lua | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/apisix/plugins/cors.lua b/apisix/plugins/cors.lua index 5014f9ceaf18..05827a798175 100644 --- a/apisix/plugins/cors.lua +++ b/apisix/plugins/cors.lua @@ -154,10 +154,10 @@ end local function get_match_domain(allow_origins, req_origin) if allow_origins == req_origin or allow_origins == '*' then - return req_origin + return allow_origins else local matched = re_find(req_origin, allow_origins, "jo") - if matched then + if matched then return req_origin end end @@ -188,7 +188,7 @@ function _M.header_filter(conf, ctx) if multiple_origin then for origin,i in pairs(multiple_origin) do match_domain = get_match_domain(origin, req_origin) - if match_domain then + if match_domain then break end end @@ -196,8 +196,10 @@ function _M.header_filter(conf, ctx) match_domain = get_match_domain(allow_origins, req_origin) end - ctx.cors_allow_origins = match_domain - set_cors_headers(conf, ctx) + if match_domain then + ctx.cors_allow_origins = match_domain + set_cors_headers(conf, ctx) + end end return _M From 14cd7819329100e086d8e84dcd9f66cf96825277 Mon Sep 17 00:00:00 2001 From: batman-ezio Date: Tue, 16 Mar 2021 16:00:22 +0800 Subject: [PATCH 03/11] feat: add allow_origins_by_regex to cors plugin --- apisix/plugins/cors.lua | 98 +++++++++++++++++++++++++++-------------- 1 file changed, 65 insertions(+), 33 deletions(-) diff --git a/apisix/plugins/cors.lua b/apisix/plugins/cors.lua index 05827a798175..a849438a0686 100644 --- a/apisix/plugins/cors.lua +++ b/apisix/plugins/cors.lua @@ -19,6 +19,7 @@ local ngx = ngx local plugin_name = "cors" local str_find = core.string.find local re_gmatch = ngx.re.gmatch +local re_compile = require("resty.core.regex").re_match_compile local re_find = ngx.re.find @@ -74,7 +75,19 @@ local schema = { "if you set this option to 'true', you can not use '*' for other options.", type = "boolean", default = false - } + }, + allow_origins_by_regex = { + type = "array", + description = + "you can use regex to allow specific origins when no credentials," .. + "for example use [.*.test.com] to allow a.test.com and b.test.com", + items = { + type = "string", + minLength = 1, + maxLength = 4096, + }, + uniqueItems = true, + }, } } @@ -122,6 +135,14 @@ function _M.check_schema(conf) return false, "you can not set '*' for other option when 'allow_credential' is true" end end + if conf.allow_origins_by_regex then + for i, re_rule in ipairs(conf.allow_origins_by_regex) do + local ok, err = re_compile(re_rule, "j") + if not ok then + return false, err + end + end + end return true end @@ -134,7 +155,7 @@ local function set_cors_headers(conf, ctx) end core.response.set_header("Access-Control-Allow-Origin", ctx.cors_allow_origins) - if ctx.cors_allow_origins ~= "*" then + if ctx.cors_allow_origins ~= "*" or next(conf.allow_origins_by_regex) ~= nil then core.response.add_header("Vary", "Origin") end @@ -152,26 +173,7 @@ local function set_cors_headers(conf, ctx) end end -local function get_match_domain(allow_origins, req_origin) - if allow_origins == req_origin or allow_origins == '*' then - return allow_origins - else - local matched = re_find(req_origin, allow_origins, "jo") - if matched then - return req_origin - end - end -end - - -function _M.rewrite(conf, ctx) - if ctx.var.request_method == "OPTIONS" then - return 200 - end -end - - -function _M.header_filter(conf, ctx) +local function process_with_allow_origins(conf, ctx) local allow_origins = conf.allow_origins local req_origin = core.request.header(ctx, "Origin") if allow_origins == "**" then @@ -183,21 +185,51 @@ function _M.header_filter(conf, ctx) return 500, {message = "get multiple origin cache failed: " .. err} end - local match_domain - if multiple_origin then - for origin,i in pairs(multiple_origin) do - match_domain = get_match_domain(origin, req_origin) - if match_domain then - break - end + if multiple_origin[req_origin] then + allow_origins = req_origin + else + return end - else - match_domain = get_match_domain(allow_origins, req_origin) end - if match_domain then - ctx.cors_allow_origins = match_domain + return allow_origins +end + +local function process_with_allow_origins_by_regex(conf, ctx) + local req_origin = core.request.header(ctx, "Origin") + + if not conf.allow_origins_by_regex_rules_concat then + local allow_origins_by_regex_rules = {} + for i, re_rule in ipairs(conf.allow_origins_by_regex) do + allow_origins_by_regex_rules[i] = re_rule + end + conf.allow_origins_by_regex_rules_concat = core.table.concat(allow_origins_by_regex_rules, "|") + end + + local matched = re_find(req_origin, conf.allow_origins_by_regex_rules_concat, "jo") + if matched then + return req_origin + end +end + + +function _M.rewrite(conf, ctx) + if ctx.var.request_method == "OPTIONS" then + return 200 + end +end + + +function _M.header_filter(conf, ctx) + local allow_origins + if next(conf.allow_origins_by_regex) ~= nil then + allow_origins = process_with_allow_origins_by_regex(conf, ctx) + else + allow_origins = process_with_allow_origins(conf, ctx) + end + if allow_origins then + ctx.cors_allow_origins = allow_origins set_cors_headers(conf, ctx) end end From e60a7c746144bd307515c56b563c17c6dc12063c Mon Sep 17 00:00:00 2001 From: batman-ezio Date: Wed, 17 Mar 2021 16:15:59 +0800 Subject: [PATCH 04/11] feat: add allow_origins_by_regex to cors plugin --- apisix/plugins/cors.lua | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/apisix/plugins/cors.lua b/apisix/plugins/cors.lua index a849438a0686..61d032446310 100644 --- a/apisix/plugins/cors.lua +++ b/apisix/plugins/cors.lua @@ -197,6 +197,9 @@ local function process_with_allow_origins(conf, ctx) end local function process_with_allow_origins_by_regex(conf, ctx) + if conf.allow_origins_by_regex == nil or next(conf.allow_origins_by_regex) == nil then + return + end local req_origin = core.request.header(ctx, "Origin") if not conf.allow_origins_by_regex_rules_concat then @@ -204,7 +207,8 @@ local function process_with_allow_origins_by_regex(conf, ctx) for i, re_rule in ipairs(conf.allow_origins_by_regex) do allow_origins_by_regex_rules[i] = re_rule end - conf.allow_origins_by_regex_rules_concat = core.table.concat(allow_origins_by_regex_rules, "|") + conf.allow_origins_by_regex_rules_concat = core.table.concat( + allow_origins_by_regex_rules, "|") end local matched = re_find(req_origin, conf.allow_origins_by_regex_rules_concat, "jo") @@ -222,11 +226,11 @@ end function _M.header_filter(conf, ctx) + -- Try allow_origins first, if mismatched, try allow_origins_by_regex. local allow_origins - if next(conf.allow_origins_by_regex) ~= nil then + allow_origins = process_with_allow_origins(conf, ctx) + if not allow_origins then allow_origins = process_with_allow_origins_by_regex(conf, ctx) - else - allow_origins = process_with_allow_origins(conf, ctx) end if allow_origins then ctx.cors_allow_origins = allow_origins From eb54f7c9602f9b7243fd658e9a3f3d902563dc31 Mon Sep 17 00:00:00 2001 From: batman-ezio Date: Wed, 17 Mar 2021 20:54:44 +0800 Subject: [PATCH 05/11] feat: add allow_origins_by_regex to cors plugin --- apisix/plugins/cors.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apisix/plugins/cors.lua b/apisix/plugins/cors.lua index 61d032446310..50541fb16bce 100644 --- a/apisix/plugins/cors.lua +++ b/apisix/plugins/cors.lua @@ -21,6 +21,8 @@ local str_find = core.string.find local re_gmatch = ngx.re.gmatch local re_compile = require("resty.core.regex").re_match_compile local re_find = ngx.re.find +local ipairs = ipairs +local next = next local lrucache = core.lrucache.new({ @@ -150,12 +152,13 @@ end local function set_cors_headers(conf, ctx) local allow_methods = conf.allow_methods + local allow_origins_by_regex = conf.allow_origins_by_regex or {} if allow_methods == "**" then allow_methods = "GET,POST,PUT,DELETE,PATCH,HEAD,OPTIONS,CONNECT,TRACE" end core.response.set_header("Access-Control-Allow-Origin", ctx.cors_allow_origins) - if ctx.cors_allow_origins ~= "*" or next(conf.allow_origins_by_regex) ~= nil then + if ctx.cors_allow_origins ~= "*" or next(allow_origins_by_regex) ~= nil then core.response.add_header("Vary", "Origin") end @@ -197,7 +200,8 @@ local function process_with_allow_origins(conf, ctx) end local function process_with_allow_origins_by_regex(conf, ctx) - if conf.allow_origins_by_regex == nil or next(conf.allow_origins_by_regex) == nil then + local allow_origins_by_regex = conf.allow_origins_by_regex or {} + if next(allow_origins_by_regex) == nil then return end local req_origin = core.request.header(ctx, "Origin") From 58b45ed6271cd21d361318be9043b86aaafd9697 Mon Sep 17 00:00:00 2001 From: batman-ezio Date: Thu, 18 Mar 2021 09:31:25 +0800 Subject: [PATCH 06/11] feat: add allow_origins_by_regex to cors plugin --- apisix/plugins/cors.lua | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/apisix/plugins/cors.lua b/apisix/plugins/cors.lua index 50541fb16bce..0fd0ef66380b 100644 --- a/apisix/plugins/cors.lua +++ b/apisix/plugins/cors.lua @@ -177,7 +177,7 @@ local function set_cors_headers(conf, ctx) end local function process_with_allow_origins(conf, ctx) - local allow_origins = conf.allow_origins + local allow_origins = conf.allow_origins or {} local req_origin = core.request.header(ctx, "Origin") if allow_origins == "**" then allow_origins = req_origin or '*' @@ -200,7 +200,7 @@ local function process_with_allow_origins(conf, ctx) end local function process_with_allow_origins_by_regex(conf, ctx) - local allow_origins_by_regex = conf.allow_origins_by_regex or {} + local allow_origins_by_regex = conf.allow_origins_by_regex if next(allow_origins_by_regex) == nil then return end @@ -222,6 +222,11 @@ local function process_with_allow_origins_by_regex(conf, ctx) end +local function match_origins(ctx, allow_origins) + return core.request.header(ctx, "Origin") == allow_origins or allow_origins == '*' +end + + function _M.rewrite(conf, ctx) if ctx.var.request_method == "OPTIONS" then return 200 @@ -233,7 +238,7 @@ function _M.header_filter(conf, ctx) -- Try allow_origins first, if mismatched, try allow_origins_by_regex. local allow_origins allow_origins = process_with_allow_origins(conf, ctx) - if not allow_origins then + if not match_origins(ctx,allow_origins) then allow_origins = process_with_allow_origins_by_regex(conf, ctx) end if allow_origins then From dc87949e8e4de45a26b190ae3fad8e460567d48a Mon Sep 17 00:00:00 2001 From: batman-ezio Date: Thu, 18 Mar 2021 10:19:53 +0800 Subject: [PATCH 07/11] feat: add allow_origins_by_regex to cors plugin --- apisix/plugins/cors.lua | 5 +- docs/en/latest/plugins/cors.md | 1 + docs/zh/latest/plugins/cors.md | 1 + t/plugin/cors.t | 128 +++++++++++++++++++++++++++++++++ 4 files changed, 133 insertions(+), 2 deletions(-) diff --git a/apisix/plugins/cors.lua b/apisix/plugins/cors.lua index 0fd0ef66380b..f08433a6c011 100644 --- a/apisix/plugins/cors.lua +++ b/apisix/plugins/cors.lua @@ -82,7 +82,7 @@ local schema = { type = "array", description = "you can use regex to allow specific origins when no credentials," .. - "for example use [.*.test.com] to allow a.test.com and b.test.com", + "for example use [.*\\.test.com] to allow a.test.com and b.test.com", items = { type = "string", minLength = 1, @@ -200,7 +200,7 @@ local function process_with_allow_origins(conf, ctx) end local function process_with_allow_origins_by_regex(conf, ctx) - local allow_origins_by_regex = conf.allow_origins_by_regex + local allow_origins_by_regex = conf.allow_origins_by_regex or {} if next(allow_origins_by_regex) == nil then return end @@ -215,6 +215,7 @@ local function process_with_allow_origins_by_regex(conf, ctx) allow_origins_by_regex_rules, "|") end + -- core.log.warn("regex: ", conf.allow_origins_by_regex_rules_concat, "\n ") local matched = re_find(req_origin, conf.allow_origins_by_regex_rules_concat, "jo") if matched then return req_origin diff --git a/docs/en/latest/plugins/cors.md b/docs/en/latest/plugins/cors.md index bd3ee75eb4a3..0f135b7266b1 100644 --- a/docs/en/latest/plugins/cors.md +++ b/docs/en/latest/plugins/cors.md @@ -43,6 +43,7 @@ title: cors | expose_headers | string | optional | "*" | | Which headers are allowed to set in response when access cross-origin resource. Multiple value use `,` to split. | | max_age | integer | optional | 5 | | Maximum number of seconds the results can be cached.. Within this time range, the browser will reuse the last check result. `-1` means no cache. Please note that the maximum value is depended on browser, please refer to [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age#Directives) for details. | | allow_credential | boolean | optional | false | | Enable request include credential (such as Cookie etc.). According to CORS specification, if you set this option to `true`, you can not use '*' for other options. | +| allow_origins_by_regex | array | optional | nil | | Use regex expressions to match which origins is allowed to enable CORS, for example, [".*\.test.com"] can use to match all subdomain of test.com | > **Tips** > diff --git a/docs/zh/latest/plugins/cors.md b/docs/zh/latest/plugins/cors.md index cef32dea454c..672ba11fe008 100644 --- a/docs/zh/latest/plugins/cors.md +++ b/docs/zh/latest/plugins/cors.md @@ -43,6 +43,7 @@ title: cors | expose_headers | string | 可选 | "*" | | 允许跨域访问时响应方携带哪些非 `CORS规范` 以外的 Header, 多个值使用 `,` 分割。 | | max_age | integer | 可选 | 5 | | 浏览器缓存 CORS 结果的最大时间,单位为秒,在这个时间范围内浏览器会复用上一次的检查结果,`-1` 表示不缓存。请注意各个浏览器允许的的最大时间不同,详情请参考 [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age#Directives)。 | | allow_credential | boolean | 可选 | false | | 是否允许跨域访问的请求方携带凭据(如 Cookie 等)。根据 CORS 规范,如果设置该选项为 `true`,那么将不能在其他选项中使用 `*`。 | +| allow_origins_by_regex | array | 可选 | nil | | 使用正则表达式数组来匹配允许跨域访问的 Origin, 如[".*\.test.com"] 可以匹配任何test.com的子域名`*`。 | > **提示** > diff --git a/t/plugin/cors.t b/t/plugin/cors.t index ec6166ce6e6c..d5c8f0bc583d 100644 --- a/t/plugin/cors.t +++ b/t/plugin/cors.t @@ -757,4 +757,132 @@ GET /t --- response_body eval qr/failed to check the configuration of plugin cors err: you can not/ --- no_error_log + + +=== TEST 28: set route (regex specified) +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "plugins": { + "cors": { + "allow_origins": "http://sub.domain.com,http://sub2.domain.com", + "allow_methods": "GET,POST", + "allow_headers": "headr1,headr2", + "expose_headers": "ex-headr1,ex-headr2", + "max_age": 50, + "allow_credential": true, + "allow_origins_by_regex":[".*\\.test.com"] + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/hello" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed +--- no_error_log [error] + + + +=== TEST 29: regex specified +--- request +GET /hello HTTP/1.1 +--- more_headers +Origin: http://a.test.com +resp-vary: Via +--- response_body +hello world +--- response_headers +Access-Control-Allow-Origin: http://a.test.com +Vary: Via, Origin +Access-Control-Allow-Methods: GET,POST +Access-Control-Allow-Headers: headr1,headr2 +Access-Control-Expose-Headers: ex-headr1,ex-headr2 +Access-Control-Max-Age: 50 +Access-Control-Allow-Credentials: true +--- no_error_log +[error] + + +=== TEST 30: set route (regex specified not match) +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "plugins": { + "cors": { + "allow_origins": "http://sub.domain.com,http://sub2.domain.com", + "allow_methods": "GET,POST", + "allow_headers": "headr1,headr2", + "expose_headers": "ex-headr1,ex-headr2", + "max_age": 50, + "allow_credential": true, + "allow_origins_by_regex":[".*\\.test.com"] + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/hello" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed +--- no_error_log +[error] + + + +=== TEST 31: regex specified not match +--- request +GET /hello HTTP/1.1 +--- more_headers +Origin: http://a.test2.com +resp-vary: Via +--- response_body +hello world +--- response_headers +Access-Control-Allow-Origin: +Access-Control-Allow-Methods: +Access-Control-Allow-Headers: +Access-Control-Expose-Headers: +Access-Control-Max-Age: +Access-Control-Allow-Credentials: +--- no_error_log +[error] + + From 02978ea77bdea4deb3ca9ffe78681c1e1bea4758 Mon Sep 17 00:00:00 2001 From: batman-ezio Date: Thu, 18 Mar 2021 10:37:03 +0800 Subject: [PATCH 08/11] feat: add allow_origins_by_regex to cors plugin --- t/plugin/cors.t | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/t/plugin/cors.t b/t/plugin/cors.t index d5c8f0bc583d..ca246489cc42 100644 --- a/t/plugin/cors.t +++ b/t/plugin/cors.t @@ -759,6 +759,7 @@ qr/failed to check the configuration of plugin cors err: you can not/ --- no_error_log + === TEST 28: set route (regex specified) --- config location /t { @@ -823,6 +824,7 @@ Access-Control-Allow-Credentials: true [error] + === TEST 30: set route (regex specified not match) --- config location /t { @@ -884,5 +886,3 @@ Access-Control-Max-Age: Access-Control-Allow-Credentials: --- no_error_log [error] - - From 57a8e20bbf11d8a8fce188cb1d856ed23ea2c4c9 Mon Sep 17 00:00:00 2001 From: batman-ezio Date: Fri, 19 Mar 2021 08:11:23 +0800 Subject: [PATCH 09/11] feat: add allow_origins_by_regex to cors plugin --- apisix/plugins/cors.lua | 26 +++++++++--------- docs/en/latest/plugins/cors.md | 2 +- t/plugin/cors.t | 49 +++++++++++++++++++++++++++++++--- 3 files changed, 58 insertions(+), 19 deletions(-) diff --git a/apisix/plugins/cors.lua b/apisix/plugins/cors.lua index f08433a6c011..253e83fc6303 100644 --- a/apisix/plugins/cors.lua +++ b/apisix/plugins/cors.lua @@ -88,6 +88,7 @@ local schema = { minLength = 1, maxLength = 4096, }, + minItems = 1, uniqueItems = true, }, } @@ -152,13 +153,12 @@ end local function set_cors_headers(conf, ctx) local allow_methods = conf.allow_methods - local allow_origins_by_regex = conf.allow_origins_by_regex or {} if allow_methods == "**" then allow_methods = "GET,POST,PUT,DELETE,PATCH,HEAD,OPTIONS,CONNECT,TRACE" end core.response.set_header("Access-Control-Allow-Origin", ctx.cors_allow_origins) - if ctx.cors_allow_origins ~= "*" or next(allow_origins_by_regex) ~= nil then + if ctx.cors_allow_origins ~= "*" or conf.allow_origins_by_regex ~= nil then core.response.add_header("Vary", "Origin") end @@ -176,9 +176,8 @@ local function set_cors_headers(conf, ctx) end end -local function process_with_allow_origins(conf, ctx) - local allow_origins = conf.allow_origins or {} - local req_origin = core.request.header(ctx, "Origin") +local function process_with_allow_origins(conf, ctx, req_origin) + local allow_origins = conf.allow_origins if allow_origins == "**" then allow_origins = req_origin or '*' end @@ -199,12 +198,10 @@ local function process_with_allow_origins(conf, ctx) return allow_origins end -local function process_with_allow_origins_by_regex(conf, ctx) - local allow_origins_by_regex = conf.allow_origins_by_regex or {} - if next(allow_origins_by_regex) == nil then +local function process_with_allow_origins_by_regex(conf, ctx, req_origin) + if conf.allow_origins_by_regex == nil then return end - local req_origin = core.request.header(ctx, "Origin") if not conf.allow_origins_by_regex_rules_concat then local allow_origins_by_regex_rules = {} @@ -223,8 +220,8 @@ local function process_with_allow_origins_by_regex(conf, ctx) end -local function match_origins(ctx, allow_origins) - return core.request.header(ctx, "Origin") == allow_origins or allow_origins == '*' +local function match_origins(req_origin, allow_origins) + return req_origin == allow_origins or allow_origins == '*' end @@ -236,11 +233,12 @@ end function _M.header_filter(conf, ctx) + local req_origin = core.request.header(ctx, "Origin") -- Try allow_origins first, if mismatched, try allow_origins_by_regex. local allow_origins - allow_origins = process_with_allow_origins(conf, ctx) - if not match_origins(ctx,allow_origins) then - allow_origins = process_with_allow_origins_by_regex(conf, ctx) + allow_origins = process_with_allow_origins(conf, ctx, req_origin) + if not match_origins(req_origin, allow_origins) then + allow_origins = process_with_allow_origins_by_regex(conf, ctx, req_origin) end if allow_origins then ctx.cors_allow_origins = allow_origins diff --git a/docs/en/latest/plugins/cors.md b/docs/en/latest/plugins/cors.md index 0f135b7266b1..2268c1602793 100644 --- a/docs/en/latest/plugins/cors.md +++ b/docs/en/latest/plugins/cors.md @@ -43,7 +43,7 @@ title: cors | expose_headers | string | optional | "*" | | Which headers are allowed to set in response when access cross-origin resource. Multiple value use `,` to split. | | max_age | integer | optional | 5 | | Maximum number of seconds the results can be cached.. Within this time range, the browser will reuse the last check result. `-1` means no cache. Please note that the maximum value is depended on browser, please refer to [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age#Directives) for details. | | allow_credential | boolean | optional | false | | Enable request include credential (such as Cookie etc.). According to CORS specification, if you set this option to `true`, you can not use '*' for other options. | -| allow_origins_by_regex | array | optional | nil | | Use regex expressions to match which origins is allowed to enable CORS, for example, [".*\.test.com"] can use to match all subdomain of test.com | +| allow_origins_by_regex | array | optional | nil | | Use regex expressions to match which origin is allowed to enable CORS, for example, [".*\.test.com"] can use to match all subdomain of test.com | > **Tips** > diff --git a/t/plugin/cors.t b/t/plugin/cors.t index ca246489cc42..8c561e7d9be8 100644 --- a/t/plugin/cors.t +++ b/t/plugin/cors.t @@ -825,7 +825,27 @@ Access-Control-Allow-Credentials: true -=== TEST 30: set route (regex specified not match) +=== TEST 30: regex specified not match +--- request +GET /hello HTTP/1.1 +--- more_headers +Origin: http://a.test2.com +resp-vary: Via +--- response_body +hello world +--- response_headers +Access-Control-Allow-Origin: +Access-Control-Allow-Methods: +Access-Control-Allow-Headers: +Access-Control-Expose-Headers: +Access-Control-Max-Age: +Access-Control-Allow-Credentials: +--- no_error_log +[error] + + + +=== TEST 31: set route (multiple regex specified ) --- config location /t { content_by_lua_block { @@ -841,7 +861,7 @@ Access-Control-Allow-Credentials: true "expose_headers": "ex-headr1,ex-headr2", "max_age": 50, "allow_credential": true, - "allow_origins_by_regex":[".*\\.test.com"] + "allow_origins_by_regex":[".*\\.test.com",".*\\.example.org"] } }, "upstream": { @@ -869,11 +889,32 @@ passed -=== TEST 31: regex specified not match +=== TEST 32: multiple regex specified match --- request GET /hello HTTP/1.1 --- more_headers -Origin: http://a.test2.com +Origin: http://foo.example.org +resp-vary: Via +--- response_body +hello world +--- response_headers +Access-Control-Allow-Origin: http://foo.example.org +Vary: Via, Origin +Access-Control-Allow-Methods: GET,POST +Access-Control-Allow-Headers: headr1,headr2 +Access-Control-Expose-Headers: ex-headr1,ex-headr2 +Access-Control-Max-Age: 50 +Access-Control-Allow-Credentials: true +--- no_error_log +[error] + + + +=== TEST 33: multiple regex specified not match +--- request +GET /hello HTTP/1.1 +--- more_headers +Origin: http://foo.example.com resp-vary: Via --- response_body hello world From 7b408fe4150f80d87a6fd549aeda3ee8ac515d45 Mon Sep 17 00:00:00 2001 From: batman-ezio Date: Fri, 19 Mar 2021 08:27:40 +0800 Subject: [PATCH 10/11] feat: add allow_origins_by_regex to cors plugin --- apisix/plugins/cors.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/apisix/plugins/cors.lua b/apisix/plugins/cors.lua index 253e83fc6303..bcff693dbab3 100644 --- a/apisix/plugins/cors.lua +++ b/apisix/plugins/cors.lua @@ -22,7 +22,6 @@ local re_gmatch = ngx.re.gmatch local re_compile = require("resty.core.regex").re_match_compile local re_find = ngx.re.find local ipairs = ipairs -local next = next local lrucache = core.lrucache.new({ From 95cc60c714ed87e1a1492c5de2b28b7b4f01db22 Mon Sep 17 00:00:00 2001 From: batman-ezio Date: Fri, 19 Mar 2021 10:21:00 +0800 Subject: [PATCH 11/11] feat: add allow_origins_by_regex to cors plugin --- apisix/plugins/cors.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apisix/plugins/cors.lua b/apisix/plugins/cors.lua index bcff693dbab3..4b0b7c4b4a77 100644 --- a/apisix/plugins/cors.lua +++ b/apisix/plugins/cors.lua @@ -157,7 +157,7 @@ local function set_cors_headers(conf, ctx) end core.response.set_header("Access-Control-Allow-Origin", ctx.cors_allow_origins) - if ctx.cors_allow_origins ~= "*" or conf.allow_origins_by_regex ~= nil then + if ctx.cors_allow_origins ~= "*" then core.response.add_header("Vary", "Origin") end