codeasashu/openapi-validator

验证数据是否符合提供的openapi规范

1.0.0 2019-09-21 18:04 UTC

This package is auto-updated.

Last update: 2024-09-22 05:32:23 UTC


README

验证数据是否符合 openapi v3规范

功能

  1. 检查必填字段
  2. 检查数据类型
  3. 支持嵌套结构
  4. 支持区分符
  5. 支持allOf, anyOf
  6. 支持可为空
  7. 解析本地引用(组件)
  8. 支持additionalProperties

与Dredd不同,它不需要示例,也不检查数据是否与示例匹配

安装

composer req --dev mmal/openapi-validator

要求

您的openapi规范必须有效,您可以使用Speccy先检查您的模式

此库假设每个操作都有operationId

示例

假设我们有一个由以下OpenAPI规范描述的api

openapi: 3.0.2
info:
  title: Cards
  description: Cards and decks api
  contact:
    name: Mieszko Malawski
  license:
    name: GNU AGPLv3
    url: https://gnu.ac.cn/licenses/agpl.txt
  version: 1.0.0
tags:
  -
    name: Cards
paths:
  /cards:
    summary: Path used to manage the list of cards.
    description: The REST endpoint/path used to list and create zero or more card entities.  This path contains a GET and POST operation to perform the list and create tasks, respectively.
    get:
      tags:
        - Cards
      summary: List All cards
      description: Gets a list of all card entities.
      operationId: getcards
      responses:
        200:
          description: Successful response - returns an array of card entities.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/card'
components:
  schemas:
    card:
      title: Root Type for card
      description: The root of the card type's schema.
      required:
      - id
      - name
      - power
      type: object
      properties:
        id:
          description: "unique id"
          type: string
          format: int64
          readOnly: true
        name:
          type: string
        power:
          description: "how powerfull card is on the board"
          format: int32
          type: integer
      example:
        id: "23423423"
        name: "Geralt"
        power: 10
        

我们有服务器实现(这当然是一个示例 - 通常您会从某些存储中获取数据)

<?php
declare(strict_types=1);


namespace AppBundle\Controller;


use GOG\Common\OAuthSecurityBundle\Controller\OAuthController;
use Symfony\Component\HttpFoundation\JsonResponse;

class CardsController extends OAuthController
{
    public function getCardsAction()
    {
        return new JsonResponse(
            [
                [
                    'id' => '123123',
                    'name' => 'Geralt',
                    'power' => 10,
                ],
                [
                    'id' => '45653',
                    'name' => 'Vernon Roche',
                    'power' => 10,
                ]
            ]
        );
    }
}

如何验证服务器实现按描述工作?使用openapi-validator与任何HTTP客户端

<?php
declare(strict_types=1);


namespace AppBundle\Tests\Controller;


use Mmal\OpenapiValidator\Validator;
use Symfony\Component\Yaml\Yaml;

class CardsControllerTest extends BaseControllerTest
{
    const SPEC_PATH = __DIR__.'/../../../../docs/api.yml';
    
    /** @var Validator */
    static $openaApiValidator;

    static public function setUpBeforeClass()
    {
        parent::setUpBeforeClass();
        self::$openaApiValidator = new Validator(Yaml::parse(self::SPEC_PATH));
    }

    public function testGetCards()
    {
        $this->makeRequest('GET', '/cards');
    }

    protected function makeRequest($method, $uri, $content = '')
    {
        $client = $this->getTestClient();
        $client->request(
            $method,
            $uri
        );
        $response = $client->getResponse();

        $result = self::$openaApiValidator->validateBasedOnRequest(
            $uri,
            $method,
            $response->getStatusCode(),
            json_decode($response->getContent(), true)
        );
        self::assertFalse($result->hasErrors(), $result);

        return RESTResponse::fromHTTPResponse($response);
    }
}
  1. 将您的规范加载到验证器中
  2. 使用任何HTTP客户端发送请求
  3. 将请求URI、请求方法、响应代码和响应体传递给验证器(可选地,媒体类型,默认为application/json)
  4. 验证器将确定对于方法'GET'、路径'/cards'和响应代码200,所需的响应模式是
card:
  title: Root Type for card
  description: The root of the card type's schema.
  required:
  - id
  - name
  - power
  type: object
  properties:
	id:
	  description: "unique id"
	  type: string
	  format: int64
	  readOnly: true
	name:
	  type: string
	power:
	  description: "how powerfull card is on the board"
	  format: int32
	  type: integer
  example:
	id: "23423423"
	name: "Geralt"
	power: 10


  1. 实际响应体将根据该模式进行验证
  2. 将生成结果对象,如果响应无效,则结果对象将包含错误

在这种情况下,响应是有效的

image info

现在让我们引入一些错误

 public function getCardsAction()
    {
        return new JsonResponse(
            [
                [
                    'id' => '123123',
                    'name' => 'Geralt',
                    'power' => 10,
                ],
                [
                 //   'id' => '45653',
                    'name' => 'Vernon Roche',
                    'power' => 10,
                ]
            ]
        );
    }
    

第二个项目的必填字段id缺失

image info

让我们再破坏一些其他东西

public function getCardsAction()
    {
        return new JsonResponse(
            [
                [
                    'id' => '123123',
                    'name' => 'Geralt',
                    'power' => 10,
                ],
                [
                    'id' => '45653',
                    'name' => 'Vernon Roche',
                    'power' => '10',
                ]
            ]
        );
    }
    

power字段应该是整数(第二个项目)

image info

其他库

  1. Dredd - 目前仅支持swagger/openapi v2,v3的支持尚未提供
  2. Swagger - 仅支持v2

待办事项

  1. 支持所有openapi格式
  2. 支持not关键字

这是如何工作的?

将openapi规范转换为json模式,然后使用justinrainbow/json-schema进行验证