如何为 404 页面创建 OpenAPI 部分?
Posted
技术标签:
【中文标题】如何为 404 页面创建 OpenAPI 部分?【英文标题】:How do I create the OpenAPI section for the 404 page? 【发布时间】:2021-12-30 08:13:31 【问题描述】:我正在使用OpenApi 3。我使用的工具Owasp Zap 查看 OpenAPI 文档并创建虚假请求。当它收到 404 时,它会抱怨它没有 OpenAPI 承诺的媒体类型。
但我没有在 OpenAPI 文档中写任何关于如何处理 404 的内容。显然,我无法编写无限数量的错误端点并记录它们返回 404。
在 OpenAPI yaml 或 json 中记录此内容的正确方法是什么?
这是一个最小的 yaml 文件...我确信这个文件确实说明了 404,即。 404 不在合同中,因此工具抱怨 404 是有效响应,但 404 是资源丢失时网站应返回的内容
---
"openapi": "3.0.0"
paths:
/Foo/:
get:
responses:
"200":
content:
application/json:
schema:
$ref: "#/components/schemas/Foo"
default:
description: Errors
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
components:
schemas:
Foo:
type: object
required:
- name
properties:
name:
type: string
Error:
type: object
required:
- error
properties:
error:
type: string
message:
type: string
data:
type: object
【问题讨论】:
这可能是您托管 API 的网络服务器的问题吗? 问题可能是任何事情。值得一提的是,它是一个 python 应用程序——在烧瓶之上的连接。 措辞似乎有点不清楚:ZAP 是按照模式(即使用指定的路径)还是随机路径生成请求?后一种情况似乎更像是工具的问题——您可以添加一个带有 404 响应的/
路径,但这似乎很麻烦,特别是因为 OpenAPI 只允许一个级别的模式匹配 (github.com/OAI/OpenAPI-Specification/issues/892)
@ChrisAdams - 它还生成像 admin.php 这样的端点,然后抱怨它得到了 404。我会试试,我猜它相当于 "/Param" 其中 Param 是不存在的端点。
当 OpenAPI 的增强功能落地时肯定会很好,因为您可以记录例如一种常见的错误格式,但我将其归类为 ZAP 中的缺陷:如果它做了 API 合同没有说明它可以做的事情并获得标准状态码作为回报,那不是问题。
【参考方案1】:
这已经提出但尚未实施:https://github.com/OAI/OpenAPI-Specification/issues/521
在 cmets 中有人提出了一个建议:https://github.com/OAI/OpenAPI-Specification/issues/521#issuecomment-513055351,这会减少你的代码,但你仍然需要为 N 个路径 * M 个方法插入 N*M 个条目。
由于我们没有能力根据我们的需求更改规范,剩下的就是我们自己调整。
从您的个人资料来看,您似乎是 Windows 用户。例如,您可以为您的 .yaml
文件(Add menu item to windows context menu only for specific filetype、Adding a context menu item in Windows for a specific file extension)创建一个新的资源管理器上下文菜单,并使其运行自动填充文件的脚本。
这里是一个名为yamlfill404.py
的示例python 脚本,它将以path/to/pythonexecutable/python.exe path/to/python/script/yamlfill404.py %1
之类的方式在上下文调用中使用,其中%1
是被右键单击的文件的路径。
Python 文件:
import yaml
from sys import argv
import re
order = ['openapi','paths','components']
level0re = re.compile('(?<=\n)[^ ][^:]+')
def _propfill(rootnode, nodes, value):
if len(nodes) == 1:
rootnode[nodes[0]] = value
if len(nodes) > 1:
nextnode = rootnode.get(nodes[0])
if rootnode.get(nodes[0]) is None:
nextnode =
rootnode[nodes[0]] = nextnode
_propfill(nextnode, nodes[1:], value)
def propfill(rootnode, nodepath, value):
_propfill(rootnode, [n.replace('__slash__','/') for n in nodepath.replace('\/','__slash__').split('/')], value)
def yamlfill(filepath):
with open(filepath, 'r') as file:
yamltree = yaml.safe_load(file)
#propfill(yamltree, 'components/schemas/notFoundResponse/...', '')
propfill(yamltree, 'components/responses/notFound/description', 'Not found response')
propfill(yamltree, 'components/responses/notFound/content/application\/json/schema/$ref', '#/components/schemas/notFoundResponse')
responses = [mv['responses'] if 'responses' in mv else [] for pk,pv in (yamltree['paths'].items() if 'paths' in yamltree else []) for mk,mv in pv.items()]
for response in responses:
propfill(response, '404/$ref', '#/components/responses/notFound')
yamlstring = yaml.dump(yamltree)
offsets = [i[1] for i in sorted([(order.index(f.group(0)) if f.group(0) in order else len(order),f.start()-1) for f in [f for f in level0re.finditer('\n'+yamlstring)]])]
offsets = [(offset,(sorted([o for o in offsets if o > offset]+[len(yamlstring)-1])[0])) for offset in offsets]
with open(filepath[:-5]+'_404.yaml', 'w') as file:
file.write(''.join(['\n'+yamlstring[o[0]:o[1]] for o in offsets]).strip())
yamlfill(argv[-1])
它处理%1
,即path/to/original.yaml
,并将其保存为path/to/original_404.yaml
(但您可以更改它以覆盖原来的)。
此示例脚本更改了 yaml 格式(引号类型、间距、排序等),因为使用了 pyyaml
的库。我不得不用order = ['openapi','paths','components']
重新排序文件,因为它失去了排序。为了减少干扰,也许更适合手动插入。也许一个只使用正则表达式。 Maye 使用awk
,有很多方法。
不幸的是,这只是一个 hack 而不是解决方案。
【讨论】:
以上是关于如何为 404 页面创建 OpenAPI 部分?的主要内容,如果未能解决你的问题,请参考以下文章