Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: using rewrite phase and add lru cache for multiple origin #1531

Merged
merged 5 commits into from
May 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 53 additions & 44 deletions apisix/plugins/cors.lua
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,30 @@ local _M = {
schema = schema,
}

local function create_mutiple_origin_cache(conf)
if not str_find(conf.allow_origins, ",", 1, true) then
return nil
end
local origin_cache = {}
local iterator, err = re_gmatch(conf.allow_origins, "([^,]+)", "jiox")
if not iterator then
core.log.error("match origins failed: ", err)
return nil
end
while true do
local origin, err = iterator()
if err then
core.log.error("iterate origins failed: ", err)
return nil
end
if not origin then
break
end
origin_cache[origin[0]] = true
end
return origin_cache
end

function _M.check_schema(conf)
local ok, err = core.schema.check(schema, conf)
if not ok then
Expand All @@ -85,63 +109,48 @@ function _M.check_schema(conf)
return true
end

function _M.access(conf, ctx)
local function set_cors_headers(conf, ctx)
local allow_methods = conf.allow_methods
if allow_methods == "**" then
allow_methods = "GET,POST,PUT,DELETE,PATCH,HEAD,OPTIONS,CONNECT,TRACE"
end

ngx.header["Access-Control-Allow-Origin"] = ctx.cors_allow_origins
ngx.header["Access-Control-Allow-Methods"] = allow_methods
ngx.header["Access-Control-Allow-Headers"] = conf.allow_headers
ngx.header["Access-Control-Max-Age"] = conf.max_age
if conf.allow_credential then
ngx.header["Access-Control-Allow-Credentials"] = true
end
ngx.header["Access-Control-Expose-Headers"] = conf.expose_headers
end

function _M.rewrite(conf, ctx)
local allow_origins = conf.allow_origins
local req_origin = core.request.header(ctx, "Origin")
if allow_origins == "**" then
allow_origins = ngx.var.http_origin or '*'
allow_origins = req_origin or '*'
end
local multiple_origin, err = core.lrucache.plugin_ctx(plugin_name, ctx,
create_mutiple_origin_cache, conf)
if err then
return 500, {message = "get mutiple origin cache failed: " .. err}
end
if str_find(allow_origins, ",", 1, true) then
local finded = false
local iterator, err = re_gmatch(allow_origins, "([^,]+)", "jiox")
if not iterator then
return 500, {message = "match origins failed", error = err}
end
while true do
local origin, err = iterator()
if err then
return 500, {message = "iterate origins failed", error = err}
end
if not origin then
break
end

if origin[0] == ngx.var.http_origin then
allow_origins = origin[0]
finded = true
break
end
end
if not finded then
if multiple_origin then
if multiple_origin[req_origin] then
allow_origins = req_origin
else
return
end
end

ctx.cors_allow_origins = allow_origins
set_cors_headers(conf, ctx)

if ctx.var.request_method == "OPTIONS" then
return 200
end
end

function _M.header_filter(conf, ctx)
if not ctx.cors_allow_origins then
-- no origin matched, don't add headers
return
end

local allow_methods = conf.allow_methods
if allow_methods == "**" then
allow_methods = "GET,POST,PUT,DELETE,PATCH,HEAD,OPTIONS,CONNECT,TRACE"
end

ngx.header["Access-Control-Allow-Origin"] = ctx.cors_allow_origins
ngx.header["Access-Control-Allow-Methods"] = allow_methods
ngx.header["Access-Control-Allow-Headers"] = conf.allow_headers
ngx.header["Access-Control-Expose-Headers"] = conf.expose_headers
ngx.header["Access-Control-Max-Age"] = conf.max_age
if conf.allow_credential then
ngx.header["Access-Control-Allow-Credentials"] = true
end
end

return _M
65 changes: 65 additions & 0 deletions t/plugin/cors.t
Original file line number Diff line number Diff line change
Expand Up @@ -426,3 +426,68 @@ OPTIONS /hello HTTP/1.1

--- no_error_log
[error]



=== TEST 15: set route(auth plugins faills)
--- 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": {
"key-auth": {},
"cors": {
"allow_origins": "**",
"allow_methods": "**",
"allow_headers": "*",
"expose_headers": "*"
}
},
"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 16: auth failed still work
--- request
GET /hello HTTP/1.1
--- more_headers
Origin: https://sub.domain.com
ExternalHeader1: val
ExternalHeader2: val
ExternalHeader3: val
--- response_body
{"message":"Missing API key found in request"}
--- error_code: 401
--- response_headers
Access-Control-Allow-Origin: https://sub.domain.com
Access-Control-Allow-Methods: GET,POST,PUT,DELETE,PATCH,HEAD,OPTIONS,CONNECT,TRACE
Access-Control-Allow-Headers: *
Access-Control-Expose-Headers: *
Access-Control-Max-Age: 5
Access-Control-Allow-Credentials:
--- no_error_log
[error]