Skip to content

Commit f3a92b3

Browse files
authored
feat(apigw_manager/plugin): 新增 4 个插件 (#243)
1 parent 478fe19 commit f3a92b3

3 files changed

Lines changed: 383 additions & 30 deletions

File tree

sdks/apigw-manager/docs/plugin-use-guide.md

Lines changed: 105 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@
4848
set:
4949
- key: test
5050
value: '2'
51-
remove: []
51+
remove:
52+
- key: X-test
5253
```
5354
5455
## 3. IP 访问保护插件 (配置支持:资源/环境)
@@ -66,8 +67,10 @@
6667
```yaml
6768
- type: bk-ip-restriction
6869
yaml: |-
69-
whitelist: '1.1.1.1'
70-
blacklist: '2.2.2.2'
70+
whitelist: |-
71+
# comment
72+
1.1.1.1
73+
2.2.2.2
7174
message: 'Your IP is not allowed'
7275
```
7376
@@ -90,7 +93,7 @@
9093
rates:
9194
__default:
9295
- period: 1
93-
tokens: 100
96+
tokens: 100
9497
```
9598
9699
## 5. mocking 插件(配置支持:资源)
@@ -108,10 +111,10 @@
108111
```yaml
109112
- type: bk-mock
110113
yaml: |-
111-
response_example: ''
114+
response_example: "{\"hello\": \"world\"}"
112115
response_headers:
113-
- key: key1
114-
value: value1
116+
- key: foo
117+
value: bar
115118
response_status: 200
116119
```
117120
@@ -137,16 +140,16 @@
137140
```yaml
138141
- type: api-breaker
139142
yaml: |-
140-
break_response_body: ''
143+
break_response_body: 'test body'
141144
break_response_headers:
142-
- key: key1
143-
value: value1
145+
- key: foo
146+
value: bar
144147
unhealthy:
145-
http_statuses:
148+
http_statuses:
146149
- 500
147150
successes: 3
148151
healthy:
149-
http_statuses:
152+
http_statuses:
150153
- 200
151154
failures: 3
152155
break_response_code: 502
@@ -177,13 +180,13 @@
177180
yaml: |-
178181
abort:
179182
http_status: 503
180-
body: ''
183+
body: "Fault Injection!"
181184
percentage: 50
182-
vars: ''
183-
unhealthy:
184-
duration: 3
185+
vars: "[[[\"arg_name\", \"==\", \"jack\"], [\"arg_age\", \"==\", 18]]]"
186+
delay:
187+
duration: 3
185188
percentage: 30
186-
vars: ''
189+
vars: "[[[\"http_age\", \"==\", 18]]]"
187190
```
188191
189192
## 8. 请求校验插件 (配置支持:资源)
@@ -202,10 +205,10 @@
202205
```yaml
203206
- type: request-validation
204207
yaml: |-
205-
body_schema: \'{"type": "object"}\'
206-
body_schema: \'{"type": "object"}\'
207-
rejected_msg: ''
208-
rejected_code: 400
208+
body_schema: "{\"type\": \"object\",\"required\": [\"Content-Type\"],\"properties\": {\"Content-Type\": {\"type\": \"string\",\"pattern\": \"^application\\/json$\"}}}"
209+
header_schema: "{\"type\": \"object\",\"required\": [\"required_payload\"],\"properties\": {\"required_payload\": {\"type\": \"string\"},\"boolean_payload\": {\"type\": \"boolean\"},\"array_payload\": {\"type\": \"array\",\"minItems\": 1,\"items\": {\"type\": \"integer\",\"minimum\": 200,\"maximum\": 599},\"uniqueItems\": true,\"default\": [200]}}}"
210+
rejected_msg: "Request header validation failed"
211+
rejected_code: 403
209212
```
210213
211214
## 9. Response 转换插件 (配置支持:资源)
@@ -228,18 +231,19 @@
228231
```yaml
229232
- type: response-rewrite
230233
yaml: |-
231-
status_code: 200
232-
body: ''
233-
vars: ''
234+
body: "{\"code\":\"ok\",\"message\":\"new json body\"}"
234235
body_base64: false
235236
headers:
236237
add:
237-
- key: 'key1: value1'
238-
remove:
239-
- key: key1
238+
- key: X-Server-balancer-addr
239+
value: test
240240
set:
241-
- key: key1
242-
value: value1
241+
- key: X-Server-id
242+
value: "3"
243+
remove:
244+
- key: X-TO-BE-REMOVED
245+
vars: "[[[\"arg_name\", \"==\", \"jack\"], [\"arg_age\", \"==\", 18]]]"
246+
status_code: 200
243247
```
244248
245249
@@ -257,7 +261,78 @@
257261
```yaml
258262
- type: redirect
259263
yaml: |-
260-
uri: ''
264+
uri: '/test/default.html'
261265
ret_code: 302
262266
```
263267
268+
269+
## 11. AccessToken 来源 (配置支持:资源)
270+
271+
### 11.1 参数说明
272+
273+
| 参数 | 类型 | 是否必填 | 默认值 | 描述 |
274+
|------------|--------|------|---------|------------------------|
275+
| source | 字符串 | 是 | "bearer" | 认证令牌的来源,默认是 bearer。 |
276+
277+
### 11.2 配置例子
278+
279+
```yaml
280+
- type: bk-access-token-source
281+
yaml: 'source: bearer'
282+
```
283+
284+
## 12. 限制请求大小 (配置支持:资源/环境)
285+
286+
### 12.1 参数说明
287+
288+
| 参数 | 类型 | 是否必填 | 默认值 | 描述 |
289+
|----------------|------|------|--------|-----------------------------|
290+
| max_body_size | 整数 | 是 | | 最大请求体大小,最大值 33554432(32 M)。 |
291+
292+
### 12.2 配置例子
293+
294+
```yaml
295+
- type: bk-request-body-limit
296+
yaml: 'max_body_size: 1024'
297+
```
298+
299+
300+
## 13. 用户访问限制 (配置支持:资源)
301+
302+
### 13.1 参数说明
303+
304+
| 参数 | 类型 | 是否必填 | 默认值 | 描述 |
305+
|----------------|----|------|----------------------------|-------|
306+
| whitelist | 数组 | 否 | | 白名单。 |
307+
| blacklist | 数组 | 否 | | 黑名单。 |
308+
| message | 字符串 | 否 | The bk-user is not allowed | 错误提示。 |
309+
310+
### 13.2 配置例子
311+
312+
```yaml
313+
- type: bk-user-restriction
314+
yaml: |-
315+
whitelist:
316+
- key: admin
317+
message: 'The bk-user is not allowed'
318+
```
319+
320+
321+
## 14. 代理缓存 (配置支持:资源)
322+
323+
### 14.1 参数说明
324+
325+
| 参数 | 类型 | 是否必填 | 默认值 | 描述 |
326+
|----------------|-----|-------|-----|-------|
327+
| cache_method | 数组 | 是 | GET | 缓存方法,仅支持:GET, HEAD。 |
328+
| cache_ttl | 整数 | 否 | 300 | 缓存时间,最大值 3600 秒。 |
329+
330+
### 14.2 配置例子
331+
332+
```yaml
333+
- type: proxy-cache
334+
yaml: |-
335+
cache_method:
336+
- key: GET
337+
cache_ttl: 300
338+
```

sdks/apigw-manager/src/apigw_manager/plugin/config.py

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,142 @@ def build_bk_username_required() -> Dict[str, str]:
729729
}
730730

731731

732+
def build_bk_request_body_limit(
733+
max_body_size: int,
734+
) -> Dict[str, str]:
735+
"""generate bk-request-body-limit plugin config
736+
737+
Args:
738+
max_body_size (int): 最大请求体大小,最大值 33554432(32 M)。
739+
740+
Raises:
741+
ValueError: max_body_size must be between 1 byte and 33554432 bytes
742+
743+
Returns:
744+
{
745+
"type": "bk-request-body-limit",
746+
"yaml": "max_body_size: 1024\n"
747+
}
748+
"""
749+
750+
if not (1 <= int(max_body_size) <= 32 * 1024 * 1024):
751+
raise ValueError("max_body_size must be between 1 byte and 33554432 bytes")
752+
753+
return {
754+
"type": "bk-request-body-limit",
755+
"yaml": yaml_dump(
756+
{
757+
"max_body_size": max_body_size,
758+
}
759+
),
760+
}
761+
762+
763+
def build_bk_user_restriction(
764+
whitelist: Optional[List[str]] = None,
765+
blacklist: Optional[List[str]] = None,
766+
) -> Dict[str, str]:
767+
"""generate bk-user-restriction plugin config
768+
769+
Args:
770+
whitelist (Optional[List[str]], optional): 用户白名单列表。Defaults to None.
771+
blacklist (Optional[List[str]], optional): 用户黑名单列表。Defaults to None.
772+
773+
Raises:
774+
ValueError: whitelist and blacklist can not be set at the same time
775+
ValueError: whitelist or blacklist should be set
776+
777+
Returns:
778+
{
779+
"type": "bk-user-restriction",
780+
"yaml": "whitelist:\n - key: admin\n"
781+
}
782+
"""
783+
784+
if whitelist and blacklist:
785+
raise ValueError("whitelist and blacklist can not be set at the same time")
786+
787+
if not (whitelist or blacklist):
788+
raise ValueError("whitelist or blacklist should be set")
789+
790+
if whitelist:
791+
return {
792+
"type": "bk-user-restriction",
793+
"yaml": yaml_dump(
794+
{
795+
"whitelist": [{"key": k} for k in whitelist],
796+
},
797+
),
798+
}
799+
800+
if blacklist:
801+
return {
802+
"type": "bk-user-restriction",
803+
"yaml": yaml_dump(
804+
{
805+
"blacklist": [{"key": k} for k in blacklist],
806+
},
807+
),
808+
}
809+
810+
811+
def build_bk_legacy_invalid_params() -> Dict[str, str]:
812+
"""generate bk-legacy-invalid-params plugin config
813+
814+
Returns:
815+
{
816+
"type": "bk-legacy-invalid-params",
817+
"yaml": ""
818+
}
819+
"""
820+
821+
return {
822+
"type": "bk-legacy-invalid-params",
823+
"yaml": "",
824+
}
825+
826+
827+
def build_proxy_cache(
828+
cache_method: List[str],
829+
cache_ttl: int = 300,
830+
) -> Dict[str, str]:
831+
"""generate proxy-cache plugin config
832+
833+
Args:
834+
cache_method (List[str]): 缓存方法,仅支持:GET, HEAD。Defaults to [GET].
835+
cache_ttl (int): 缓存时间,最大值 3600 秒。Defaults to 300.
836+
837+
Raises:
838+
ValueError: cache_method only supports GET and HEAD
839+
ValueError: cache_ttl must be between 1 and 3600 seconds
840+
841+
Returns:
842+
{
843+
"type": "proxy-cache",
844+
"yaml": "cache_method:\n - key: GET\n cache_ttl: 300\n"
845+
}
846+
"""
847+
848+
cache_method_data = []
849+
for method in cache_method:
850+
if method not in ["GET", "HEAD"]:
851+
raise ValueError("cache_method only supports GET and HEAD")
852+
cache_method_data.append({"key": method})
853+
854+
if not (1 <= cache_ttl <= 3600):
855+
raise ValueError("cache_ttl must be between 1 and 3600 seconds")
856+
857+
return {
858+
"type": "proxy-cache",
859+
"yaml": yaml_dump(
860+
{
861+
"cache_method": cache_method_data,
862+
"cache_ttl": cache_ttl,
863+
}
864+
),
865+
}
866+
867+
732868
def _check_percentage(percentage: int, location: str):
733869
if percentage and not (0 < percentage <= 100):
734870
raise ValueError(f"The percentage of {location} must be greater than 0 and less than or equal to 100")

0 commit comments

Comments
 (0)