From ebedcf76c924247f4858014aa95e375db4049910 Mon Sep 17 00:00:00 2001 From: Han-Ya-Jun <1581532052@qq.com> Date: Wed, 3 Jul 2024 17:44:00 +0800 Subject: [PATCH 1/6] feat(api/web/doc): doc example add schema example --- .../docs/gateway/gateway_sdk/serializers.py | 1 + .../web/docs/gateway/gateway_sdk/views.py | 22 +++++++++- .../apps/docs/templatetags/__init__.py | 17 ++++++++ .../apps/docs/templatetags/json_filters.py | 42 +++++++++++++++++++ .../apigateway/biz/resource_version.py | 10 +++++ .../apigateway/apigateway/biz/sdk/models.py | 8 ++++ .../apigateway/apigateway/conf/default.py | 1 + .../zh-hans/python_sdk_usage_example_bkapi.md | 28 +++++++++---- .../apigateway/apigateway/utils/openapi.py | 34 +++++++++++++++ 9 files changed, 153 insertions(+), 10 deletions(-) create mode 100644 src/dashboard/apigateway/apigateway/apps/docs/templatetags/__init__.py create mode 100644 src/dashboard/apigateway/apigateway/apps/docs/templatetags/json_filters.py diff --git a/src/dashboard/apigateway/apigateway/apis/web/docs/gateway/gateway_sdk/serializers.py b/src/dashboard/apigateway/apigateway/apis/web/docs/gateway/gateway_sdk/serializers.py index dd9dce011..400db2e9b 100644 --- a/src/dashboard/apigateway/apigateway/apis/web/docs/gateway/gateway_sdk/serializers.py +++ b/src/dashboard/apigateway/apigateway/apis/web/docs/gateway/gateway_sdk/serializers.py @@ -65,6 +65,7 @@ class SDKUsageExampleInputSLZ(serializers.Serializer): ) stage_name = serializers.CharField(help_text="网关环境名称") resource_name = serializers.CharField(help_text="资源名称") + resource_id = serializers.IntegerField(help_text="资源id", required=False) class SDKUsageExampleOutputSLZ(serializers.Serializer): diff --git a/src/dashboard/apigateway/apigateway/apis/web/docs/gateway/gateway_sdk/views.py b/src/dashboard/apigateway/apigateway/apis/web/docs/gateway/gateway_sdk/views.py index ba3ae4b1a..236de4fc1 100644 --- a/src/dashboard/apigateway/apigateway/apis/web/docs/gateway/gateway_sdk/views.py +++ b/src/dashboard/apigateway/apigateway/apis/web/docs/gateway/gateway_sdk/views.py @@ -16,6 +16,7 @@ # We undertake not to change the open source license (MIT license) applicable # to the current version of the project delivered to anyone in the future. # + from django.template.loader import render_to_string from django.utils.decorators import method_decorator from django.utils.timezone import now as timezone_now @@ -23,10 +24,13 @@ from rest_framework import generics, status from apigateway.apps.support.models import GatewaySDK +from apigateway.biz.resource_version import ResourceVersionHandler from apigateway.biz.sdk.gateway_sdk import GatewaySDKHandler from apigateway.biz.sdk.models import SDKDocContext from apigateway.common.django.translation import get_current_language_code from apigateway.common.permissions import GatewayDisplayablePermission +from apigateway.core.models import Release +from apigateway.utils import openapi from apigateway.utils.responses import OKJsonResponse from .serializers import SDKListInputSLZ, SDKUsageExampleInputSLZ, SDKUsageExampleOutputSLZ, StageSDKOutputSLZ @@ -81,13 +85,27 @@ def retrieve(self, request, gateway_name: str, *args, **kwargs): language=programming_language, ).last() + stage_name = slz.validated_data["stage_name"] + + resource_name = slz.validated_data["resource_name"] + + # 获取对应资源的schema + resource_version_id = Release.objects.get_released_resource_version_id(request.gateway.id, stage_name) + resource_id = ResourceVersionHandler.get_resource_id(resource_version_id, resource_name) + resource_schema = ResourceVersionHandler.get_resource_schema(resource_version_id, resource_id) + example = openapi.get_openapi_example(resource_schema) + content = render_to_string( f"api_sdk/{get_current_language_code()}/{programming_language}_sdk_usage_example.md", context=SDKDocContext( gateway_name=request.gateway.name, - stage_name=slz.validated_data["stage_name"], - resource_name=slz.validated_data["resource_name"], + stage_name=stage_name, + resource_name=resource_name, sdk_created_time=(sdk and sdk.created_time) or timezone_now(), + body_example=example.get("body_example", {}), + path_params=example.get("path_params", {}), + query_params=example.get("query_params", {}), + headers=example.get("headers", {}), ).as_dict(), ) diff --git a/src/dashboard/apigateway/apigateway/apps/docs/templatetags/__init__.py b/src/dashboard/apigateway/apigateway/apps/docs/templatetags/__init__.py new file mode 100644 index 000000000..2941673fe --- /dev/null +++ b/src/dashboard/apigateway/apigateway/apps/docs/templatetags/__init__.py @@ -0,0 +1,17 @@ +# +# TencentBlueKing is pleased to support the open source community by making +# 蓝鲸智云 - API 网关(BlueKing - APIGateway) available. +# Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. +# Licensed under the MIT License (the "License"); you may not use this file except +# in compliance with the License. You may obtain a copy of the License at +# +# http://opensource.org/licenses/MIT +# +# 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. +# +# We undertake not to change the open source license (MIT license) applicable +# to the current version of the project delivered to anyone in the future. +# diff --git a/src/dashboard/apigateway/apigateway/apps/docs/templatetags/json_filters.py b/src/dashboard/apigateway/apigateway/apps/docs/templatetags/json_filters.py new file mode 100644 index 000000000..cda888833 --- /dev/null +++ b/src/dashboard/apigateway/apigateway/apps/docs/templatetags/json_filters.py @@ -0,0 +1,42 @@ +# +# TencentBlueKing is pleased to support the open source community by making +# 蓝鲸智云 - API 网关(BlueKing - APIGateway) available. +# Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. +# Licensed under the MIT License (the "License"); you may not use this file except +# in compliance with the License. You may obtain a copy of the License at +# +# http://opensource.org/licenses/MIT +# +# 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. +# +# We undertake not to change the open source license (MIT license) applicable +# to the current version of the project delivered to anyone in the future. +# +# myapp/templatetags/json_filters.py + +import json + +from django import template + +register = template.Library() + + +@register.filter +def pretty_json(value, indent=2): + try: + return json.dumps(value, indent=indent) + except (ValueError, TypeError): + return value + + +@register.filter +def indent_json(value, indent=2): + try: + json_str = json.dumps(value, indent=indent) + lines = json_str.split("\n") + return "\n".join([lines[0]] + [" " * indent + line for line in lines[1:]]) + except (ValueError, TypeError): + return value diff --git a/src/dashboard/apigateway/apigateway/biz/resource_version.py b/src/dashboard/apigateway/apigateway/biz/resource_version.py index 45ee45409..b13ffa369 100644 --- a/src/dashboard/apigateway/apigateway/biz/resource_version.py +++ b/src/dashboard/apigateway/apigateway/biz/resource_version.py @@ -278,6 +278,16 @@ def get_resource_schema(resource_version_id: int, resource_id: int) -> dict: return schema return {} + @staticmethod + def get_resource_id(resource_version_id: int, resource_name: str) -> int: + resource_version = ResourceVersion.objects.filter(id=resource_version_id).first() + if not resource_version: + return 0 + for resource in resource_version.data: + if resource["name"] == resource_name: + return resource["id"] + return 0 + class ResourceDocVersionHandler: @staticmethod diff --git a/src/dashboard/apigateway/apigateway/biz/sdk/models.py b/src/dashboard/apigateway/apigateway/biz/sdk/models.py index fc29ff5d2..721db0350 100644 --- a/src/dashboard/apigateway/apigateway/biz/sdk/models.py +++ b/src/dashboard/apigateway/apigateway/biz/sdk/models.py @@ -31,6 +31,10 @@ class SDKDocContext: resource_name: str sdk_created_time: datetime = field(default_factory=timezone_now) gateway_name_with_underscore: str = "" + body_example: dict = field(default_factory=dict) + path_params: dict = field(default_factory=dict) + query_params: dict = field(default_factory=dict) + headers: dict = field(default_factory=dict) django_settings: Any = settings def as_dict(self): @@ -41,6 +45,10 @@ def as_dict(self): "resource_name": self.resource_name, "sdk_created_time": self.sdk_created_time, "django_settings": self.django_settings, + "body_example": self.body_example, + "path_params": self.path_params, + "query_params": self.query_params, + "headers": self.headers, } diff --git a/src/dashboard/apigateway/apigateway/conf/default.py b/src/dashboard/apigateway/apigateway/conf/default.py index 0309fefc2..05adaa33c 100644 --- a/src/dashboard/apigateway/apigateway/conf/default.py +++ b/src/dashboard/apigateway/apigateway/conf/default.py @@ -85,6 +85,7 @@ "apigateway.account", "apigateway.apps.feature", "apigateway.apps.esb", + "apigateway.apps.docs", "apigateway.apps.esb.bkcore", "apigw_manager.apigw", "apigateway.controller", diff --git a/src/dashboard/apigateway/apigateway/templates/api_sdk/zh-hans/python_sdk_usage_example_bkapi.md b/src/dashboard/apigateway/apigateway/templates/api_sdk/zh-hans/python_sdk_usage_example_bkapi.md index 64d610535..6577db569 100644 --- a/src/dashboard/apigateway/apigateway/templates/api_sdk/zh-hans/python_sdk_usage_example_bkapi.md +++ b/src/dashboard/apigateway/apigateway/templates/api_sdk/zh-hans/python_sdk_usage_example_bkapi.md @@ -1,4 +1,4 @@ - +{% load json_filters %} 创建网关 {{gateway_name}} Client 并调用 API 资源 {{resource_name}} 使用示例: ### 1. Django 项目 @@ -23,7 +23,13 @@ client = get_client_by_request( ) # 请按具体场景修改请求 -client.api.{{resource_name}}(...) +client.api.{{resource_name}}( + data={{ body_example|indent_json:4|safe }}, # 设置请求参数 + path_params={{ path_params|indent_json:4|safe }}, # 设置路径参数 + params={{ query_params|indent_json:4|safe }}, # 设置 querystring + headers={{ headers|indent_json:4|safe }}, # 设置请求头 + timeout=10, # 设置当前请求超时 +) ``` #### 1.2 get_client_by_username @@ -44,7 +50,13 @@ client = get_client_by_username( ) # 请按具体场景修改请求 -client.api.{{resource_name}}(...) +client.api.{{resource_name}}( + data={{ body_example|indent_json:4|safe }}, # 设置请求参数 + path_params={{ path_params|indent_json:4|safe }}, # 设置路径参数 + params={{ query_params|indent_json:4|safe }}, # 设置 querystring + headers={{ headers|indent_json:4|safe }}, # 设置请求头 + timeout=10, # 设置当前请求超时 +) ``` ### 2. 非 Django 项目 @@ -59,11 +71,11 @@ client = Client( ) # 请求网关资源,请按具体场景修改请求,参数与 requests 保持兼容 -client.api.{{resource_name}}( - data={...}, # 设置请求参数 - path_params={...}, # 设置路径参数 - params={...}, # 设置 querystring - headers={...}, # 设置请求头 +client.api.{{ resource_name }}( + data={{ body_example|indent_json:4|safe }}, # 设置请求参数 + path_params={{ path_params|indent_json:4|safe }}, # 设置路径参数 + params={{ query_params|indent_json:4|safe }}, # 设置 querystring + headers={{ headers|indent_json:4|safe }}, # 设置请求头 timeout=10, # 设置当前请求超时 ) ``` diff --git a/src/dashboard/apigateway/apigateway/utils/openapi.py b/src/dashboard/apigateway/apigateway/utils/openapi.py index e081b7dab..9f1757123 100644 --- a/src/dashboard/apigateway/apigateway/utils/openapi.py +++ b/src/dashboard/apigateway/apigateway/utils/openapi.py @@ -19,6 +19,7 @@ import random from faker import Faker +from openapi_schema_to_json_schema import to_json_schema fake = Faker() @@ -67,3 +68,36 @@ def handle_integer(schema): def handle_default(schema): return None + + +def generate_parameters_example(parameters): + path_params = {} + query_params = {} + headers = {} + + for param in parameters: + name = param["name"] + example = param.get("example", "example_value") + if param["in"] == "path": + path_params[name] = example + elif param["in"] == "query": + query_params[name] = example + elif param["in"] == "header": + headers[name] = example + + return path_params, query_params, headers + + +def get_openapi_example(schema): + example = {} + request_body = schema.get("requestBody") + if request_body and "content" in request_body and "application/json" in request_body["content"]: + # todo: 暂时在只支持application/json + json_schema = to_json_schema(request_body["content"]["application/json"]["schema"]) + example["body_example"] = generate_example(json_schema) + parameters = schema.get("parameters", []) + path, query, headers = generate_parameters_example(parameters) + example["path_params"] = path + example["query_params"] = query + example["headers"] = headers + return example From 84a1550569ee458311b485488cd4e9c0e1e8dbc6 Mon Sep 17 00:00:00 2001 From: Han-Ya-Jun <1581532052@qq.com> Date: Wed, 3 Jul 2024 17:50:04 +0800 Subject: [PATCH 2/6] fix(api/web/doc): fix slz --- .../apis/web/docs/gateway/gateway_sdk/serializers.py | 1 + .../apigateway/apis/web/docs/gateway/gateway_sdk/views.py | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/dashboard/apigateway/apigateway/apis/web/docs/gateway/gateway_sdk/serializers.py b/src/dashboard/apigateway/apigateway/apis/web/docs/gateway/gateway_sdk/serializers.py index 400db2e9b..c23fea1fe 100644 --- a/src/dashboard/apigateway/apigateway/apis/web/docs/gateway/gateway_sdk/serializers.py +++ b/src/dashboard/apigateway/apigateway/apis/web/docs/gateway/gateway_sdk/serializers.py @@ -65,6 +65,7 @@ class SDKUsageExampleInputSLZ(serializers.Serializer): ) stage_name = serializers.CharField(help_text="网关环境名称") resource_name = serializers.CharField(help_text="资源名称") + # todo:暂时先不加 resource_id = serializers.IntegerField(help_text="资源id", required=False) diff --git a/src/dashboard/apigateway/apigateway/apis/web/docs/gateway/gateway_sdk/views.py b/src/dashboard/apigateway/apigateway/apis/web/docs/gateway/gateway_sdk/views.py index 236de4fc1..613b24270 100644 --- a/src/dashboard/apigateway/apigateway/apis/web/docs/gateway/gateway_sdk/views.py +++ b/src/dashboard/apigateway/apigateway/apis/web/docs/gateway/gateway_sdk/views.py @@ -89,9 +89,15 @@ def retrieve(self, request, gateway_name: str, *args, **kwargs): resource_name = slz.validated_data["resource_name"] + resource_id = slz.validated_data.get("resource_id") + # 获取对应资源的schema resource_version_id = Release.objects.get_released_resource_version_id(request.gateway.id, stage_name) - resource_id = ResourceVersionHandler.get_resource_id(resource_version_id, resource_name) + + # 如果前端没有传resource_id,通过资源版本s + if not resource_id: + resource_id = ResourceVersionHandler.get_resource_id(resource_version_id, resource_name) + resource_schema = ResourceVersionHandler.get_resource_schema(resource_version_id, resource_id) example = openapi.get_openapi_example(resource_schema) From 94a9b6db001146175901ac8baa686b2cf11fcee7 Mon Sep 17 00:00:00 2001 From: Han-Ya-Jun <1581532052@qq.com> Date: Wed, 3 Jul 2024 17:51:12 +0800 Subject: [PATCH 3/6] fix(docs): fix code explain --- .../apigateway/apis/web/docs/gateway/gateway_sdk/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dashboard/apigateway/apigateway/apis/web/docs/gateway/gateway_sdk/views.py b/src/dashboard/apigateway/apigateway/apis/web/docs/gateway/gateway_sdk/views.py index 613b24270..2fa06f035 100644 --- a/src/dashboard/apigateway/apigateway/apis/web/docs/gateway/gateway_sdk/views.py +++ b/src/dashboard/apigateway/apigateway/apis/web/docs/gateway/gateway_sdk/views.py @@ -94,7 +94,7 @@ def retrieve(self, request, gateway_name: str, *args, **kwargs): # 获取对应资源的schema resource_version_id = Release.objects.get_released_resource_version_id(request.gateway.id, stage_name) - # 如果前端没有传resource_id,通过资源版本s + # 如果前端没有传resource_id,通过资源版本获取一下 if not resource_id: resource_id = ResourceVersionHandler.get_resource_id(resource_version_id, resource_name) From 483608fab690e6de429becde183d6abc711fc22d Mon Sep 17 00:00:00 2001 From: Han-Ya-Jun <1581532052@qq.com> Date: Wed, 3 Jul 2024 17:57:44 +0800 Subject: [PATCH 4/6] fix(api/web/doc): fix lint --- .../apis/web/docs/gateway/gateway_sdk/views.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/dashboard/apigateway/apigateway/apis/web/docs/gateway/gateway_sdk/views.py b/src/dashboard/apigateway/apigateway/apis/web/docs/gateway/gateway_sdk/views.py index 2fa06f035..a270bbc0c 100644 --- a/src/dashboard/apigateway/apigateway/apis/web/docs/gateway/gateway_sdk/views.py +++ b/src/dashboard/apigateway/apigateway/apis/web/docs/gateway/gateway_sdk/views.py @@ -86,20 +86,18 @@ def retrieve(self, request, gateway_name: str, *args, **kwargs): ).last() stage_name = slz.validated_data["stage_name"] - resource_name = slz.validated_data["resource_name"] - resource_id = slz.validated_data.get("resource_id") - # 获取对应资源的schema resource_version_id = Release.objects.get_released_resource_version_id(request.gateway.id, stage_name) + example = {} # 如果前端没有传resource_id,通过资源版本获取一下 - if not resource_id: + if not resource_id and resource_version_id: resource_id = ResourceVersionHandler.get_resource_id(resource_version_id, resource_name) - - resource_schema = ResourceVersionHandler.get_resource_schema(resource_version_id, resource_id) - example = openapi.get_openapi_example(resource_schema) + # 获取对应资源的schema + resource_schema = ResourceVersionHandler.get_resource_schema(resource_version_id, resource_id) + example = openapi.get_openapi_example(resource_schema) content = render_to_string( f"api_sdk/{get_current_language_code()}/{programming_language}_sdk_usage_example.md", From e3dee42fb8ca833e6376a5c9ac82df4ffd746c3c Mon Sep 17 00:00:00 2001 From: Han-Ya-Jun <1581532052@qq.com> Date: Thu, 4 Jul 2024 11:14:52 +0800 Subject: [PATCH 5/6] fix(api/web/docs): fix bug --- src/dashboard/apigateway/apigateway/biz/resource_version.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/dashboard/apigateway/apigateway/biz/resource_version.py b/src/dashboard/apigateway/apigateway/biz/resource_version.py index b13ffa369..b0f784ae7 100644 --- a/src/dashboard/apigateway/apigateway/biz/resource_version.py +++ b/src/dashboard/apigateway/apigateway/biz/resource_version.py @@ -268,7 +268,9 @@ def get_resource_schema(resource_version_id: int, resource_id: int) -> dict: """ 获取指定版本的资源对应的api schema """ - resources_version_schema = OpenAPIResourceSchemaVersion.objects.get(resource_version_id=resource_version_id) + resources_version_schema = OpenAPIResourceSchemaVersion.objects.filter( + resource_version_id=resource_version_id + ).first() if resources_version_schema is None: return {} # 筛选资源数据 From 784b8e32f0352aa952d5f2dcd4a17f3daac54618 Mon Sep 17 00:00:00 2001 From: Han-Ya-Jun <1581532052@qq.com> Date: Mon, 8 Jul 2024 14:46:11 +0800 Subject: [PATCH 6/6] fix(api/web/doc): add test --- .../apigateway/apis/web/release/views.py | 6 +- .../apigateway/biz/resource_version.py | 4 +- .../apigateway/tests/utils/test_openapi.py | 70 +++++++++++++++++++ .../apigateway/apigateway/utils/openapi.py | 6 +- 4 files changed, 80 insertions(+), 6 deletions(-) diff --git a/src/dashboard/apigateway/apigateway/apis/web/release/views.py b/src/dashboard/apigateway/apigateway/apis/web/release/views.py index a44d9c8c8..f44e29a62 100644 --- a/src/dashboard/apigateway/apigateway/apis/web/release/views.py +++ b/src/dashboard/apigateway/apigateway/apis/web/release/views.py @@ -126,9 +126,11 @@ def retrieve(self, request, *args, **kwargs): schema_result["parameter_schema"] = schema.get("parameters", []) schema_result["response_schema"] = schema.get("responses", {}) request_body = schema.get("requestBody") - if request_body: + if request_body and "content" in request_body and "application/json" in request_body["content"]: # todo: 暂时在只支持application/json - json_schema = to_json_schema(request_body["content"]["application/json"]["schema"]) + json_schema = to_json_schema( + request_body["content"]["application/json"]["schema"], {"keepNotSupported": ["example"]} + ) example = openapi.generate_example(json_schema) schema_result.update( { diff --git a/src/dashboard/apigateway/apigateway/biz/resource_version.py b/src/dashboard/apigateway/apigateway/biz/resource_version.py index b0f784ae7..77a447c38 100644 --- a/src/dashboard/apigateway/apigateway/biz/resource_version.py +++ b/src/dashboard/apigateway/apigateway/biz/resource_version.py @@ -284,11 +284,11 @@ def get_resource_schema(resource_version_id: int, resource_id: int) -> dict: def get_resource_id(resource_version_id: int, resource_name: str) -> int: resource_version = ResourceVersion.objects.filter(id=resource_version_id).first() if not resource_version: - return 0 + return -1 for resource in resource_version.data: if resource["name"] == resource_name: return resource["id"] - return 0 + return -1 class ResourceDocVersionHandler: diff --git a/src/dashboard/apigateway/apigateway/tests/utils/test_openapi.py b/src/dashboard/apigateway/apigateway/tests/utils/test_openapi.py index a39a55545..8ffc7210e 100644 --- a/src/dashboard/apigateway/apigateway/tests/utils/test_openapi.py +++ b/src/dashboard/apigateway/apigateway/tests/utils/test_openapi.py @@ -18,6 +18,7 @@ import pytest from apigateway.utils import openapi +from apigateway.utils.openapi import generate_parameters_example, get_openapi_example class TestOpenAPI: @@ -49,3 +50,72 @@ def test_generate_example(self, schema, expected): assert schema["minimum"] <= result <= schema["maximum"] elif "enum" in schema: assert result in schema["enum"] + + @pytest.mark.parametrize( + "parameters, expected_path, expected_query, expected_headers", + [ + ( + [ + {"name": "userId", "in": "path", "example": "123"}, + {"name": "search", "in": "query", "example": "test"}, + {"name": "Authorization", "in": "header", "example": "Bearer token"}, + ], + {"userId": "123"}, + {"search": "test"}, + {"Authorization": "Bearer token"}, + ), + ( + [ + {"name": "userId", "in": "path"}, + {"name": "search", "in": "query"}, + {"name": "Authorization", "in": "header"}, + ], + {"userId": "example_value"}, + {"search": "example_value"}, + {"Authorization": "example_value"}, + ), + ([], {}, {}, {}), + ], + ) + def test_generate_parameters_example(self, parameters, expected_path, expected_query, expected_headers): + path_params, query_params, headers = generate_parameters_example(parameters) + assert path_params == expected_path + assert query_params == expected_query + assert headers == expected_headers + + @pytest.mark.parametrize( + "schema, expected_example", + [ + ( + { + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": {"type": "integer", "example": 1}, + "name": {"type": "string", "example": "test"}, + }, + } + } + } + }, + "parameters": [ + {"name": "userId", "in": "path", "example": "123"}, + {"name": "search", "in": "query", "example": "test"}, + {"name": "Authorization", "in": "header", "example": "Bearer token"}, + ], + }, + { + "body_example": {"id": 1, "name": "test"}, + "path_params": {"userId": "123"}, + "query_params": {"search": "test"}, + "headers": {"Authorization": "Bearer token"}, + }, + ) + ], + ) + def test_get_openapi_example(self, schema, expected_example): + example = get_openapi_example(schema) + assert example == expected_example diff --git a/src/dashboard/apigateway/apigateway/utils/openapi.py b/src/dashboard/apigateway/apigateway/utils/openapi.py index 9f1757123..9c55c614f 100644 --- a/src/dashboard/apigateway/apigateway/utils/openapi.py +++ b/src/dashboard/apigateway/apigateway/utils/openapi.py @@ -89,11 +89,13 @@ def generate_parameters_example(parameters): def get_openapi_example(schema): - example = {} + example = {"body_example": {}, "path_params": {}, "query_params": {}, "headers": {}} request_body = schema.get("requestBody") if request_body and "content" in request_body and "application/json" in request_body["content"]: # todo: 暂时在只支持application/json - json_schema = to_json_schema(request_body["content"]["application/json"]["schema"]) + json_schema = to_json_schema( + request_body["content"]["application/json"]["schema"], {"keepNotSupported": ["example"]} + ) example["body_example"] = generate_example(json_schema) parameters = schema.get("parameters", []) path, query, headers = generate_parameters_example(parameters)