-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
features: append cors plugin #1327
Changes from 10 commits
9ba9c88
d369b9c
f6aa92f
3450b65
3fa7118
0f1051a
3da4737
2f3327b
eba991f
954bb1c
8bbc29d
054988b
79e4421
b7fcb39
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -144,6 +144,6 @@ plugins: # plugin list | |
- tcp-logger | ||
- proxy-mirror | ||
- kafka-logger | ||
|
||
- cors | ||
stream_plugins: | ||
- mqtt-proxy |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
<!-- | ||
# | ||
# Licensed to the Apache Software Foundation (ASF) under one or more | ||
# contributor license agreements. See the NOTICE file distributed with | ||
# this work for additional information regarding copyright ownership. | ||
# The ASF licenses this file to You under the Apache License, Version 2.0 | ||
# (the "License"); you may not use this file except in compliance with | ||
# the License. You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
# | ||
--> | ||
|
||
# [English](cors.md) | ||
|
||
# 目录 | ||
|
||
- [**简介**](#简介) | ||
- [**属性**](#属性) | ||
- [**如何启用**](#如何启用) | ||
- [**测试插件**](#测试插件) | ||
- [**禁用插件**](#禁用插件) | ||
|
||
## 简介 | ||
|
||
`cors` 插件可以让你轻易地为服务端启用 [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) 的返回头。 | ||
|
||
## 属性 | ||
|
||
- `allow_origins`: `可选`.允许跨域访问的Origin, 格式如:`scheme`://`host`:`port`, 比如: https://somehost.com:8081. 多个值使用 `,` 分割, `allow_credential` 为 `false` 时可以使用 `*` 来表示所有 Origin均允许通过。你也可以在启用了 `allow_credential` 后使用 `**` 强制允许所有Origin都通过,但请注意这样存在安全隐患。默认值为 `*`。 | ||
- `allow_methods`: `可选`.允许跨域访问的Method, 比如: `GET`, `POST`等。多个值使用 `,` 分割, `allow_credential` 为 `false` 时可以使用 `*` 来表示所有 Origin均允许通过。你也可以在启用了 `allow_credential` 后使用 `**` 强制允许所有 Method 都通过,但请注意这样存在安全隐患。默认值为 `*`。 | ||
- `allow_headers`: `可选`.允许跨域访问时请求方携带哪些非 CORS规范 以外的 Header, 多个值使用 `,` 分割。默认值为 `*`。 | ||
- `expose_headers`: `可选`.允许跨域访问时响应方携带哪些非 CORS规范 以外的 Header, 多个值使用 `,` 分割。默认值为 `*`。 | ||
- `max_age`: `可选`.浏览器缓存CORS结果的最大时间, 单位为秒, 在这个时间范围内浏览器会复用上一次的检查结果, `-1` 表示不缓存。请注意各个浏览器允许的的最大时间不用, 详情请参考 [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age#Directives). 默认值为 `5`。 | ||
- `allow_credential`: 是否允许跨域访问的请求方携带凭据(如 Cookie 等), 默认值为: `false`。 | ||
|
||
## 如何启用 | ||
创建 `Route` 或 `Service` 对象,并配置 `cors` 插件。 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add a blank line |
||
```shell | ||
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' | ||
{ | ||
"methods": ["GET"], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we can remove this line |
||
"uri": "/hello", | ||
"plugins": { | ||
"cors": {} | ||
}, | ||
"upstream": { | ||
"type": "roundrobin", | ||
"nodes": { | ||
"127.0.0.1:8080": 1 | ||
} | ||
} | ||
}' | ||
``` | ||
|
||
## 测试插件 | ||
请求下接口, 发现接口已经返回了`CORS`相关的header, 代表插件生效 | ||
```shell | ||
curl http://127.0.0.1:9080/hello -v | ||
... | ||
< Server: APISIX web server | ||
< Access-Control-Allow-Origin: * | ||
< Access-Control-Allow-Methods: * | ||
< Access-Control-Allow-Headers: * | ||
< Access-Control-Expose-Headers: * | ||
< Access-Control-Max-Age: 5 | ||
... | ||
``` | ||
|
||
## 禁用插件 | ||
|
||
从配置中移除`cors`插件即可。 | ||
```shell | ||
$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' | ||
{ | ||
"methods": ["GET"], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we can remove this line |
||
"uri": "/hello", | ||
"plugins": {}, | ||
"upstream": { | ||
"type": "roundrobin", | ||
"nodes": { | ||
"127.0.0.1:8080": 1 | ||
} | ||
} | ||
}' | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
<!-- | ||
# | ||
# Licensed to the Apache Software Foundation (ASF) under one or more | ||
# contributor license agreements. See the NOTICE file distributed with | ||
# this work for additional information regarding copyright ownership. | ||
# The ASF licenses this file to You under the Apache License, Version 2.0 | ||
# (the "License"); you may not use this file except in compliance with | ||
# the License. You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
# | ||
--> | ||
|
||
# [Chinese](cors-cn.md) | ||
|
||
# Summary | ||
|
||
- [**Description**](#Description) | ||
- [**Attributes**](#Attributes) | ||
- [**How To Enable**](#how-to-Enable) | ||
- [**Test Plugin**](#test-plugin) | ||
- [**Disable Plugin**](#disable-plugin) | ||
|
||
## Description | ||
|
||
`cors` plugin can help you enable [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) easily. | ||
|
||
## Attributes | ||
|
||
- `allow_origins`: `optional`.Which Origins is allowed to enable CORS, format as:`scheme`://`host`:`port`, for example: https://somehost.com:8081. Multiple origin use `,` to split. When `allow_credential` is `false`, you can use `*` to indicate allow all any origin. you alse can allow all any origins forcefully using `**` even already enable `allow_credential`, but it will bring some securiy risks. Default value: `*`. | ||
- `allow_methods`: `optional`.Which Method is allowed to enable CORS, such as: `GET`, `POST` etc. Multiple method use `,` to split. When `allow_credential` is `false`, you can use `*` to indicate allow all any method. You alse can allow all any method forcefully using `**` even already enable `allow_credential`, but it will bring some securiy risks. Default value: `*`. | ||
- `allow_headers`: `optional`.Which headers are allowed to set in requst when access cross-origin resource. Multiple value use `,` to split. Default value: `*`. | ||
- `expose_headers`: `optional`.Which headers are allowed to set in response when access cross-origin resource. Multiple value use `,` to split. Default value: `*`. | ||
- `max_age`: `optional`.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.Default value: `5`. | ||
- `allow_credential`: Enable request include credentia (such as Cookie etc.), Default avlue: `false`. | ||
|
||
## How To Enable | ||
Create a `Route` or `Service` object and configure `cors` plugin. | ||
```shell | ||
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' | ||
{ | ||
"methods": ["GET"], | ||
"uri": "/hello", | ||
"plugins": { | ||
"cors": {} | ||
}, | ||
"upstream": { | ||
"type": "roundrobin", | ||
"nodes": { | ||
"127.0.0.1:8080": 1 | ||
} | ||
} | ||
}' | ||
``` | ||
|
||
## Test Plugin | ||
curl to server, you will find the headers about `CORS` is be returned, it means plugin is working fine. | ||
```shell | ||
curl http://127.0.0.1:9080/hello -v | ||
... | ||
< Server: APISIX web server | ||
< Access-Control-Allow-Origin: * | ||
< Access-Control-Allow-Methods: * | ||
< Access-Control-Allow-Headers: * | ||
< Access-Control-Expose-Headers: * | ||
< Access-Control-Max-Age: 5 | ||
... | ||
``` | ||
|
||
## Disable Plugin | ||
Remove plugin from configuraion. | ||
```shell | ||
$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' | ||
{ | ||
"methods": ["GET"], | ||
"uri": "/hello", | ||
"plugins": {}, | ||
"upstream": { | ||
"type": "roundrobin", | ||
"nodes": { | ||
"127.0.0.1:8080": 1 | ||
} | ||
} | ||
}' | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
-- | ||
-- Licensed to the Apache Software Foundation (ASF) under one or more | ||
-- contributor license agreements. See the NOTICE file distributed with | ||
-- this work for additional information regarding copyright ownership. | ||
-- The ASF licenses this file to You under the Apache License, Version 2.0 | ||
-- (the "License"); you may not use this file except in compliance with | ||
-- the License. You may obtain a copy of the License at | ||
-- | ||
-- http://www.apache.org/licenses/LICENSE-2.0 | ||
-- | ||
-- Unless required by applicable law or agreed to in writing, software | ||
-- distributed under the License is distributed on an "AS IS" BASIS, | ||
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
-- See the License for the specific language governing permissions and | ||
-- limitations under the License. | ||
-- | ||
local core = require("apisix.core") | ||
local ngx = ngx | ||
local plugin_name = "cors" | ||
local str_find = string.find | ||
local re_gmatch = ngx.re.gmatch | ||
|
||
local schema = { | ||
type = "object", | ||
properties = { | ||
allow_origins = { | ||
description = | ||
"you can use '*' to allow all origins when no credentials," .. | ||
"'**' to allow forcefully(it will bring some security risks, be carefully)," .. | ||
"multiple origin use ',' to split. default: *.", | ||
type = "string", | ||
default = "*" | ||
}, | ||
allow_methods = { | ||
description = | ||
"you can use '*' to allow all methods when no credentials and '**'," .. | ||
"'**' to allow forcefully(it will bring some security risks, be carefully)," .. | ||
"multiple method use ',' to split. default: *.", | ||
type = "string", | ||
default = "*" | ||
}, | ||
allow_headers = { | ||
description = | ||
"you can use '*' to allow all header when no credentials," .. | ||
"multiple header use ',' to split. default: *.", | ||
type = "string", | ||
default = "*" | ||
}, | ||
expose_headers = { | ||
description = | ||
"you can use '*' to expose all header when no credentials," .. | ||
"multiple header use ',' to split. default: *.", | ||
type = "string", | ||
default = "*" | ||
}, | ||
max_age = { | ||
description = | ||
"maximum number of seconds the results can be cached." .. | ||
"-1 mean no cached,the max value is depend on browser," .. | ||
"more detail plz check MDN. default: 5.", | ||
type = "integer", | ||
default = 5 | ||
}, | ||
allow_credential = { | ||
type = "boolean", | ||
default = false | ||
}, | ||
} | ||
} | ||
|
||
local _M = { | ||
version = 0.1, | ||
priority = 4000, | ||
type = 'auth', | ||
name = plugin_name, | ||
schema = schema, | ||
} | ||
|
||
function _M.check_schema(conf) | ||
local ok, err = core.schema.check(schema, conf) | ||
if not ok then | ||
return false, err | ||
end | ||
|
||
return true | ||
end | ||
|
||
function _M.header_filter(conf, ctx) | ||
if conf.allow_origins == "**" then | ||
conf.allow_origins = ngx.var.http_origin or '*' | ||
end | ||
if str_find(conf.allow_origins, ",", 1, true) then | ||
local finded = false | ||
local iterator, err = re_gmatch(conf.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 | ||
conf.allow_origins = origin[0] | ||
finded = true | ||
break | ||
end | ||
end | ||
if not finded then | ||
return | ||
end | ||
end | ||
|
||
if conf.allow_methods == "**" then | ||
conf.allow_methods = "GET,POST,PUT,DELETE,PATCH,HEAD,OPTIONS,CONNECT,TRACE" | ||
end | ||
|
||
ngx.header["Access-Control-Allow-Origin"] = conf.allow_origins | ||
ngx.header["Access-Control-Allow-Methods"] = conf.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 | ||
|
||
if ctx.var.request_method == "OPTIONS" then | ||
return 200 | ||
end | ||
end | ||
|
||
return _M |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"
可选
. " -> "可选
,"There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use Chinese commas
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add space between English and Chinese