Spectral を使って OpenAPI のエラーチェックを強化する
こんにちは、Gaji-Labo フロントエンドエンジニアの石垣です。
自分が携わっている案件では OpenAPI と openapi-generator-cli を使って API の仕様定義とサーバーのコード生成を行っているのですが、基本的には YAML ファイル上の schema を直接記述して作業しています。
このとき細かい記述ミスがあるとコード生成時にエラーが発生します。しかし openapi-generator-cli が出力するエラーメッセージはわかりにくいことが多いです。
たとえば、 openapi-generator-cli の公式で用意されている petstore.yaml というサンプルドキュメントを使ってエラーを確認してみます。
schemas:
Order:
title: Pet Order
description: An order for a pets from the pet store
type: object
properties:
id:
type: integer
format: int64
id:
type: integer
format: int64
...
以上はサンプルドキュメントの状態から手元で id を重複させたものです。これを openapi-generator-cli でコード生成すると以下のエラーが表示されます。
> openapi-validator@1.0.0 og
> openapi-generator-cli generate
[[v3.0] petstore.yaml] [main] WARN i.s.v.p.util.DeserializationUtils - Error snake-parsing yaml content
[[v3.0] petstore.yaml] io.swagger.v3.parser.util.DeserializationUtils$SnakeException: Duplicate field id
[[v3.0] petstore.yaml] at io.swagger.v3.parser.util.DeserializationUtils$CustomSnakeYamlConstructor.getSingleData(DeserializationUtils.java:415)
[[v3.0] petstore.yaml] at org.yaml.snakeyaml.Yaml.loadFromReader(Yaml.java:490)
[[v3.0] petstore.yaml] at org.yaml.snakeyaml.Yaml.load(Yaml.java:416)
[[v3.0] petstore.yaml] at io.swagger.v3.parser.util.DeserializationUtils.readYamlTree(DeserializationUtils.java:194)
[[v3.0] petstore.yaml] at io.swagger.v3.parser.util.DeserializationUtils.deserializeIntoTree(DeserializationUtils.java:140)
[[v3.0] petstore.yaml] at io.swagger.v3.parser.OpenAPIV3Parser.readContents(OpenAPIV3Parser.java:162)
[[v3.0] petstore.yaml] at io.swagger.v3.parser.OpenAPIV3Parser.readLocation(OpenAPIV3Parser.java:91)
[[v3.0] petstore.yaml] at io.swagger.parser.OpenAPIParser.readLocation(OpenAPIParser.java:16)
[[v3.0] petstore.yaml] at org.openapitools.codegen.config.CodegenConfigurator.toContext(CodegenConfigurator.java:573)
[[v3.0] petstore.yaml] at org.openapitools.codegen.config.CodegenConfigurator.toClientOptInput(CodegenConfigurator.java:631)
[[v3.0] petstore.yaml] at org.openapitools.codegen.cmd.Generate.execute(Generate.java:457)
[[v3.0] petstore.yaml] at org.openapitools.codegen.cmd.OpenApiGeneratorCommand.run(OpenApiGeneratorCommand.java:32)
[[v3.0] petstore.yaml] at org.openapitools.codegen.OpenAPIGenerator.main(OpenAPIGenerator.java:66)
[[v3.0] petstore.yaml] Exception in thread "main" org.openapitools.codegen.SpecValidationException: There were issues with the specification. The option can be disabled via validateSpec (Maven/Gradle) or --skip-validate-spec (CLI).
[[v3.0] petstore.yaml] | Error count: 1, Warning count: 0
[[v3.0] petstore.yaml] Errors:
[[v3.0] petstore.yaml] -Duplicate field id in `/Users/semigura/openapi-validator/petstore.yaml`
[[v3.0] petstore.yaml]
[[v3.0] petstore.yaml] at org.openapitools.codegen.config.CodegenConfigurator.toContext(CodegenConfigurator.java:604)
[[v3.0] petstore.yaml] at org.openapitools.codegen.config.CodegenConfigurator.toClientOptInput(CodegenConfigurator.java:631)
[[v3.0] petstore.yaml] at org.openapitools.codegen.cmd.Generate.execute(Generate.java:457)
[[v3.0] petstore.yaml] at org.openapitools.codegen.cmd.OpenApiGeneratorCommand.run(OpenApiGeneratorCommand.java:32)
[[v3.0] petstore.yaml] at org.openapitools.codegen.OpenAPIGenerator.main(OpenAPIGenerator.java:66)
[[v3.0] petstore.yaml] java -jar "/Users/semigura/openapi-validator/node_modules/@openapitools/openapi-generator-cli/versions/6.0.1.jar" generate --input-spec="/Users/tmp/Documents/works/openapi-validator/petstore.yaml" --generator-name="nodejs-express-server" --output="output" exited with code 1
[v3.0] petstore.yaml
java -jar "/Users/semigura/openapi-validator/node_modules/@openapitools/openapi-generator-cli/versions/6.0.1.jar" generate --input-spec="/Users/semigura/openapi-validator/petstore.yaml" --generator-name="nodejs-express-server" --output="output"
Code generation failed
このエラーメッセージは Duplicate field id
というエラーが表示されてはいますが重複しているフィールドがどこにあるのかが非常にわかりづらいです。
そこでより詳細なエラーメッセージを表示してくれるツールを探してみたところ、Spectral というツールを知ったので今回はその使い方についてまとめたいと思います。
Spectralとは
Spectral は、Stoplight が提供している OpenAPI のリンティングツールです。OpenAPIドキュメントに対して、様々なバリデーションルールを適用し、わかりやすいエラーメッセージを表示してくれます。npm パッケージとして提供されており、簡単にインストールすることができます。
まずはじめに、Spectral で使用するルールセットを設定する必要があります。
Spectral は標準のルールセットを提供しているので、それを活用できます。
echo 'extends: ["spectral:oas"]' > .spectral.yaml
これで Spectralがデフォルトで用意している OAS(OpenAPI Specification) のルールセットを使えるようになりました。
サンプルドキュメントのバリデーション
では実際に先程の petstore.yaml
を使ってバリデーションを行ってみます。
spectral lint petstore.yaml
すると、以下のような詳細なエラーメッセージが表示されます。
/Users/semigura/openapi-validator/petstore.yaml
4:6 warning info-contact Info object must have "contact" object. info
26:20 warning operation-description Operation "description" must be present and non-empty string. paths./pet.post.description
50:20 warning operation-description Operation "description" must be present and non-empty string. paths./pet.put.description
195:20 warning operation-description Operation "description" must be present and non-empty string. paths./pet/{petId}.post.description
205:17 warning operation-success-response Operation must have at least one "2xx" or "3xx" response. paths./pet/{petId}.post.responses
228:20 warning operation-description Operation "description" must be present and non-empty string. paths./pet/{petId}.delete.description
243:17 warning operation-success-response Operation must have at least one "2xx" or "3xx" response. paths./pet/{petId}.delete.responses
255:20 warning operation-description Operation "description" must be present and non-empty string. paths./pet/{petId}/uploadImage.post.description
313:20 warning operation-description Operation "description" must be present and non-empty string. paths./store/order.post.description
382:17 warning operation-success-response Operation must have at least one "2xx" or "3xx" response. paths./store/order/{orderId}.delete.responses
394:17 warning operation-success-response Operation must have at least one "2xx" or "3xx" response. paths./user.post.responses
411:20 warning operation-description Operation "description" must be present and non-empty string. paths./user/createWithArray.post.description
413:17 warning operation-success-response Operation must have at least one "2xx" or "3xx" response. paths./user/createWithArray.post.responses
425:20 warning operation-description Operation "description" must be present and non-empty string. paths./user/createWithList.post.description
427:17 warning operation-success-response Operation must have at least one "2xx" or "3xx" response. paths./user/createWithList.post.responses
439:20 warning operation-description Operation "description" must be present and non-empty string. paths./user/login.get.description
490:20 warning operation-description Operation "description" must be present and non-empty string. paths./user/logout.get.description
492:17 warning operation-success-response Operation must have at least one "2xx" or "3xx" response. paths./user/logout.get.responses
502:20 warning operation-description Operation "description" must be present and non-empty string. paths./user/{username}.get.description
538:17 warning operation-success-response Operation must have at least one "2xx" or "3xx" response. paths./user/{username}.put.responses
565:17 warning operation-success-response Operation must have at least one "2xx" or "3xx" response. paths./user/{username}.delete.responses
618:9 error parser Duplicate key: id components.schemas.Order.properties.id
先ほども表示されていた Duplicate field id
というエラーが、より詳細に表示されています。また、他にも様々なエラーが表示されていることがわかります。
このように Spectral はドキュメントの問題点を詳細に指摘してくれるため記述ミスの発見や修正が容易になります。
まとめ
今回は Spectral を使って OpenAPI ドキュメントのバリデーションを行う方法について紹介しました。
Spectral を使うことで、より詳細なエラーメッセージを表示してくれるため、問題の特定や修正が容易になります。
ぜひ活用してみてください。
Gaji-Labo フロントエンドエンジニア向けご案内資料
Gaji-Labo は Next.js, React, TypeScript 開発の実績と知見があります
フロントエンド開発の専門家である私たちが御社の開発チームに入ることで、バックエンドも含めた全体の開発効率が上がります。
「既存のサイトを Next.js に移行したい」
「人手が足りず信頼できるエンジニアを探している」
「自分たちで手を付けてみたがいまいち上手くいかない」
フロントエンド開発に関わるお困りごとがあれば、まずは一度お気軽に Gaji-Labo にご相談ください。
オンラインでのヒアリングとフルリモートでのプロセス支援にも対応しています。
Next.js, React, TypeScript の相談をする!