synatos / porta
OpenAPI 3.0 验证
Requires
- php: >=8.1
- ext-json: *
- gm314/nitria: *
- symfony/yaml: *
Requires (Dev)
- codeception/codeception: 4.2.*
This package is not auto-updated.
Last update: 2024-09-27 12:39:54 UTC
README
Porta 是希腊语,意为门。该项目可以用作 Rest API 端点的门。Open API 标准允许精确描述 REST API 中的信息在服务器进入和离开时的内容。该标准可用于:1. 使用 Swagger 等工具描述接口/文档 2. 验证传入和传出的 REST 消息 3. 生成请求/响应类,允许将未类型化的数组/json 转换为类型化对象。
描述
Porta 是一个 Open API 3.0 架构验证器,用于 Http 请求。本实现的特色功能:
- 验证 JSON 请求和响应
- 使用对象操作/构建 Open API 架构
- 注册自己的格式验证器
- 为给定的架构生成请求和响应类
- 将 Open API 架构编译为类。
安装
composer require synatos/porta
导入/导出
您可以轻松导入/导出 JSON/Yaml 文件
use Synatos\Porta\Model\OpenAPI; $openAPI = new OpenAPI(); # yaml $openAPI->fromYamlFile(__DIR__ . "/my-open-api.yml"); $openAPI->toYamlFile(__DIR__ . "/export.yml"); # json $openAPI->fromJSONFile("my-open-api.json"); $openAPI->toJSONFile(__DIR__ . "/export.json");
验证
请求验证
请求可以轻松地与给定的架构进行验证。重要提示:请确保请求内容的类型已在 HTTP 标头中设置。Open API 允许多种工件进行验证
- 查询参数
- 路由参数
- HTTP 头部
- Cookie
- 请求体
以下示例显示了如何使用 Open API 架构验证 HTTP 请求。
use Synatos\Porta\Http\ContentType; use Synatos\Porta\Http\HttpHeader; use Synatos\Porta\Model\OpenAPI; use Synatos\Porta\Porta; require_once '../vendor/autoload.php'; $openAPI = new OpenAPI(); $openAPI->fromJSONFile(__DIR__ . '/open-api.json'); $porta = new Porta(); $porta->setOpenAPI($openAPI); $path = "/api/security/login-with-password"; $method = "POST"; $header = [ HttpHeader::CONTENT_TYPE => ContentType::APPLICATION_JSON ]; $query = []; $requestBody = json_encode([ "email" => "email@email.com", "password" => "abcd1234" ]); $validationMessageList = $porta->validateRequest($path, $method, $header,$query, $requestBody);
注册自己的格式验证器
Open API 规范允许定义格式来更详细地指定数据类型
"然而,格式是一个开放值,因此您可以使用任何格式,甚至不是由 OpenAPI 规范定义的格式,例如:"(来源 https://swagger.org.cn/docs/specification/data-models/data-types/#string)
使用 Porta,您可以注册自己的验证器来处理格式。以下是一个示例
use Synatos\Porta\Contract\Validator; use Synatos\Porta\Http\ContentType; use Synatos\Porta\Http\HttpHeader; use Synatos\Porta\Model\OpenAPI; use Synatos\Porta\Model\Schema; use Synatos\Porta\Porta; use Synatos\Porta\Validator\FormatValidatorFactory; require_once '../vendor/autoload.php'; class EmailValidator implements Validator { public function validate(Schema $schema, $value, array $propertyPath): array { echo "validating " . $value . PHP_EOL; return []; } } FormatValidatorFactory::addFormatValidator("email", new EmailValidator());
从架构生成 PHP 类
架构会变得越来越大,解析 json/yaml 包括文件加载可能会变得耗时。因此,可以将现有架构编译成一个包含架构数组内联的类
use Synatos\Porta\Generator\OpenAPIClassGenerator; use Synatos\Porta\Model\OpenAPI; require_once '../vendor/autoload.php'; $openAPI = new OpenAPI(); $openAPI->fromJSONFile(__DIR__ . '/open-api.json'); $fullyQualifiedClassName = "Example\\CompiledSchema"; $psrPrefix = ""; $baseDir = __DIR__; $openAPIClassGenerator = new OpenAPIClassGenerator(); $openAPIClassGenerator->generate($openAPI, $fullyQualifiedClassName, $psrPrefix, $baseDir);
此编译的类将包含以下内容
class CompiledSchema { /** * @var OpenAPI */ private static $openAPI; /** * * @return OpenAPI */ public static function getOpenAPI() : OpenAPI { if (self::$openAPI === null) { self::$openAPI = new OpenAPI(); self::$openAPI->fromArray([ /* schema will be compiled into an array */]); } return self::$openAPI; } }
生成 Open API 类
您可以为给定的架构生成一个包含所有类型属性的类。此外,两个方法 \JsonSerializable
和 fromArray(array $data)
允许从数组中初始化并再次生成数组。这样,您就不需要访问数组了,而是可以从数组中创建 Schema 对象,并以完全类型化的方式与对象一起工作。
$schemaContent = json_decode(file_get_contents(__DIR__ . '/request-schema.json'), true); $schema = new Schema(); $schema->fromArray($schemaContent); $psrPrefix = ""; $baseDir = __DIR__; $namespace = "Example"; $className = "UserRequest"; $generator = new SchemaToPHPGenerator($psrPrefix, $baseDir); $generator->generateSchema($namespace, $className, $schema); // see example/compile-schema-class.php
生成的类将如下所示
class UserRequest implements \JsonSerializable { /** * @var string */ protected $id; /** * @param string|null $id * * @return void */ public function setId(?string $id) { $this->id = $id; } /** * * @return string|null */ public function getId() : ?string { return $this->id; } /** * @param array $array * * @return void */ public function fromArray(array $array) {/* ... */} /** * * @return array */ public function jsonSerialize() : array {/* ... */}
模型操作
Open API 中的每个工件都有一个对象表示。因此,您可以轻松构建 Schema、操作或其他任何部分
use Synatos\Porta\Http\ContentType; use Synatos\Porta\Model\MediaType; use Synatos\Porta\Model\OpenAPI; use Synatos\Porta\Model\Operation; use Synatos\Porta\Model\PathItem; use Synatos\Porta\Model\RequestBody; use Synatos\Porta\Model\Schema; require_once '../vendor/autoload.php'; $intSchema = new Schema(); $intSchema->setType(Schema::TYPE_INTEGER); $intSchema->setNullable(false); $objectSchema = new Schema(); $objectSchema->setNullable(true); $objectSchema->setProperties([ "intProperty" => $intSchema ]); $requestMediaType = new MediaType(); $requestMediaType->setSchema($objectSchema); $requestBody = new RequestBody(); $requestBody->setRequired(true); $requestBody->setContent([ ContentType::APPLICATION_JSON => $requestMediaType ]); $operation = new Operation(); $operation->setRequestBody($requestBody); $pathItem = new PathItem(); $pathItem->setOperationByMethod(PathItem::METHOD_POST, $operation); $openAPI = new OpenAPI(); $openAPI->setPaths([ "/api/do/something" => $pathItem ]);