在许多文件中分割swagger定义

时间:2016-02-22 11:24:54

标签: api rest swagger contract raml

问题:如何跨文件拆分swagger定义?该领域有哪些可能性?问题详情如下:

我想要的例子 - 在RAML中

我确实有RAML的经验,我的工作是,例如:

/settings:
  description: |
    This resource defines application & components configuration
  get:
    is: [ includingCustomHeaders ]
    description: |
      Fetch entire configuration
    responses:
      200:
        body:
          example: !include samples/settings.json
          schema: !include schemas/settings.json

最后两行在这里很重要 - 带有!include <filepath>的内容 - 在RAML中我可以将我的整个合同拆分成许多文件,这些文件只是由RAML解析器动态包含(并且RAML解析器被所有基础工具使用)在RAML)。

我的好处是:

  • 我的合同更清晰,更容易维护,因为架构不是内联的
  • 但这非常重要:我可以在其他工具中重用模式文件来进行验证,模拟生成,存根,生成测试等。换句话说,这样我就可以在契约(RAML,本例)和其他工具(非RAML,非swagger,只是基于JSONschema的工具)中重用模式文件。

回到Swagger

据我所知,swagger支持$ref关键字,允许加载外部文件。但是这些文件是通过HTTP / AJAX获取的还是只是本地文件?

是否支持整个规范,或者只是支持它的一些工具和一些不支持的工具?

我发现here是swagger的输入必须是一个文件。这对大型项目来说非常不方便:

  • 因为尺寸
  • 因为如果我想使用非招摇的话,我就无法重用架构

或者,换句话说,在分割文件方面,我可以用闪光灯来实现同样的目标吗?

4 个答案:

答案 0 :(得分:6)

The specification允许多个位置的引用,但无处不在。这些引用的解析取决于规范的托管位置 - 以及您尝试做的事情。

对于像渲染动态用户界面之类的东西,那么是的,你需要最终将整个定义加载到单个对象&#34;这可能是由许多文件组成的。如果执行代码生成,则可以直接从文件系统加载定义。但最终有一些摇摆解析器在进行分辨率,这在Swagger中比其他定义格式更细粒度和可控制。

在您的情况下,您将使用指向架构引用的JSON指针:

responses:
  200:
    description: the response
    schema:

通过本地参考

      $ref: '#/definitions/myModel'

通过绝对参考:

      $ref: 'http://path/to/your/resource'

通过相对引用,相对于加载此文档的位置&#39;

      $ref: 'resource.json#/myModel

通过内联定义

      type: object
      properties:
        id:
          type: string

答案 1 :(得分:1)

有关如何在多个文件中拆分Swagger文档的详细信息,请参阅this answer。这是使用JSON完成的,但同样的概念可以应用于RAML。

编辑:在此处添加链接内容

Swagger JSON的基本结构应如下所示:

{
"swagger": "2.0",
"info": {
    "title": "",
    "version": "version number here"
},
"basePath": "/",
"host": "host goes here",
"schemes": [
    "http"
],
"produces": [
    "application/json"
],
"paths": {},
"definitions": {}
}

pathsdefinitions是您需要插入API支持的路径以及描述响应对象的模型定义的地方。您可以动态填充这些对象。这样做的一种方法是为每个实体的路径和模型分别创建一个文件。

假设您的API中的一个对象是“汽车”。

路径:

{
"paths": {
    "/cars": {
        "get": {
            "tags": [
                "Car"
            ],
            "summary": "Get all cars",
            "description": "Returns all of the cars.",             
            "responses": {
                "200": {
                    "description": "An array of cars",
                    "schema": {
                        "type": "array",
                        "items": {
                            "$ref": "#/definitions/car"
                        }
                    }
                },
                "404": {
                    "description": "error fetching cars",
                    "schema": {
                        "$ref": "#/definitions/error"
                    }
                }
            }
        }
    }
}

型号:

{
"car": {
    "properties": {
        "_id": {
            "type": "string",
            "description": "car unique identifier"
        },
        "make": {
            "type": "string",
            "description": "Make of the car"
        },
        "model":{
            "type": "string",
            "description": "Model of the car."
        }
    }
}
}

然后,您可以将每个文件放在自己的文件中。启动服务器时,可以获取这两个JSON对象,并将它们附加到基本swagger对象中的相应对象(pathsdefinitions),并将该基础对象作为Swagger JSON对象提供

您还可以通过在服务器启动时仅执行一次附加来进一步优化此功能(因为在服务器运行时API文档不会更改)。然后,当命中“serve Swagger docs”端点时,您可以返回在服务器启动时创建的缓存Swagger JSON对象。

可以通过向/api-docs发送请求来截取“服务Swagger文档”端点,如下所示:

app.get('/api-docs', function(req, res) {
  // return the created Swagger JSON object here
});

答案 2 :(得分:1)

当我使用引用分割OpenAPI V3文件时,我尝试避免使用袜子抽屉反模式,而是对YAML文件使用功能分组。

我也这样做,以便每个YAML文件本身都是有效的OpenAPI V3规范。

我从openapi.yaml文件开始。

openapi: 3.0.3
info:
  title: MyAPI
  description: |
    This is the public API for my stuff.
  version: "3"
tags:
  # NOTE: the name is needed as the info block uses `title` rather than name
  - name: Authentication
    $ref: 'authn.yaml#/info'
paths:
  # NOTE: here are the references to the other OpenAPI files 
  #  from the path.  Note because OpenAPI requires paths to
  #  start with `/` and that is already used as a separator
  #  replace the `/` with `%2F` for the path reference.
  '/authn/start':
    $ref: 'authn.yaml#/paths/%2Fstart'

然后在功能组中:

openapi: 3.0.3
info:
  title: Authentication
  description: |
    This is the authentication module.
  version: "3"
paths:
  # NOTE: don't include the `/authn` prefix here that top level grouping is
  #  in the `openapi.yaml` file.
  '/start':
    get:
      responses:
        "200":
          description: OK

通过这种分离,您可以独立地将每个文件或整个API作为一个组进行测试。

在某些地方您可能会重复自己,但是这样做可以限制使用“公共”库时破坏对其他API端点所做的更改的机会。

但是,您仍应具有一些通用的定义库,例如:

  • 错误
  • 安全性

此方法有一个局限性,那就是“鉴别符”(尽管这可能是ReDoc的问题,但是如果您的类型在openapi.yaml ReDoc之外具有鉴别符,则无法正确呈现。

答案 3 :(得分:0)

你可以使用$ ref但没有很好的灵活性,我建议你使用像'Yamlinc'这样的外部工具处理YAML,它使用'$ include'标签将多个文件混合成一个。

了解详情:https://github.com/javanile/yamlinc