Swaggerを使ってライブラリ非公開のAPIにライブラリを作って見た
仕事で少し検証をしてみたくなったAPIサービスが見つかりました。
オンデマンドに印刷・発送をするためのAPIサービスなんですが、対応予定言語にJavaがない!REST APIだからどうとでもなるとは言え、フレームワーク的な部分のコードをゴリゴリと書きたくないですよね。本末転倒な楽しさに目覚めてしまう可能性もありますし(そっちかよ)。
というわけで、API仕様も公開されていますし、Swaggerの練習がてら自力でライブラリ生成をして使ってみました。
Swagger is 何?
Open API Specificationの開発者ツールフレームワークで、APIのデザイン、ドキュメンテーション、開発を支援する仕様とツール群を提供しています。Open API SpecificationとはアプリケーションにRESTful APIを作るための書式です。
ツール類は以下の3つで構成されています。
- Swagger Editor -> まあその名の通り、オンラインエディタ(Local Datastoreに保存)かnodeかdockerを選べます
- Swagger Codegen -> Open API Specificationから各種環境用のサーバスタブやライブラリを生成するためのツール
- Swagger UI -> Open API Specificationからインタラクティブな機能を持った開発者向けドキュメントを生成するツールとその開発ドキュメントそのもの
今回サーバスタブは作っていません。
Open API Specification
細かい仕様はここを読みましょう。
定義はymlでもjsonでも書けます。エンドポイントや認証フロー、APIのIn/Outの各種データモデルを定義することができます。
Swaggerに感じる可能性
個人的には、このAPI SpecificationをAPI Gatewayに流してエンドポイントはそっちで管理、実装レイヤはAWS Lambdaという構成にできる方がいいのではないかと思っています。フロントエンドとサービスを切り離して、コンテキストでわけられた各種サービスのエンドポイントをつなぎ合わせて構成に、というとなんかMicroserviceっぽいですね。この構成にする上で、開発者に公開するドキュメントやライブラリは必須なわけですが、設計レベルからのアプローチで設計ドキュメントと実装の一致を測りやすくなっているのは良い感触です。
コンテキストの境界づけをAPIを提供する単位で行うことができ、別のコンテキストの裏口的なアクセスをなるべくブロックすることができます。そういう意味でDDDの各種実装パターンにおける実際のアーキテクチャのリファレンスが少し変わるのではないかと(パターン自体はあまり変わらないのではないかと思っている)。
というわけで使ってみた
swagger.yaml自体は仕様に基づいて書いただけなので、リポジトリをご査収ください。
で、検証している時にいくつか課題があったのでその内容をメモっておきます。
Swagger UIからAPIにアクセスできない
実際に仕様を書いてSwagger UIからアクセスしてみようとすると、こんなエラーが出ました。
Fetch API cannot load https://api.codenberg.io/v1/auth/token. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://editor.swagger.io' is therefore not allowed access. The response had HTTP status code 404. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Swagger UIからのアクセスは当然Originではないので、許可されていませんよ、ということ。オンラインエディタで最初に確認しましたが、dockerのコンテナ立ててlocalhostでエディタ立ててもVS Codeの拡張機能使っても同様でした。コンテナはまあ想像していましたが、VS Codeの拡張機能もnode使っているんでしょうね。ちなみに、認証に限らずAPI全般で同じ状態でした。
今回のケースはサーバサイドの問題です。どこまで許可するか、とかセキュリティの問題はありそうですが、少なくとも開発、テスト時に必要なレベルは許可されていないとツール類からアクセスできないのは非常に不便ですね。プルリクエスト投げた時にコメントで追加しています。
生成されるライブラリの認証フロー実装
Javaのライブラリを出力して、検証してみました。で、サンプルとして一緒に出力されるコードが以下のような感じなんですよね。
package sample; import io.swagger.client.*; import io.swagger.client.auth.*; import io.swagger.client.model.*; import io.swagger.client.api.FormatsApi; /** * Created by mao on 2017/06/26. */ public class Application { public static void main(String[] args) { ApiClient defaultClient = Configuration.getDefaultApiClient(); // Configure OAuth2 access token for authorization: codenberg_auth OAuth codenberg_auth = (OAuth) defaultClient.getAuthentication("codenberg_auth"); codenberg_auth.setAccessToken("Access Token"); FormatsApi apiInstance = new FormatsApi(); try { InlineResponse2001 result = apiInstance.getFormats(new Body3()); System.out.println(result); } catch (ApiException e) { System.err.println("Exception when calling FormatsApi#getFormatById"); e.printStackTrace(); } } }
出力されるライブラリはOAuthの認証フローは実装されず、AccessTokenをセットする前提になっている。認証フローは別のライブラリなどで考慮する出力仕様のようです。他の言語のライブラリ出力ではどうなるかまでは検証していませんが、まあこの辺は知っていればいいだけの話かと。
あと、若干クラス名のつけ方が自動生成っぽいというかアレですね。この辺はもしかしたら定義の仕方次第で回避方法はあるのかも。
ちなみに、ライブラリからのアクセスはうまくいきました。いちいち出力して検証するわけには行かないので、クロスドメインの問題自体はサーバサイドで対応した方がいいですが、回避方法というか検証方法自体は残されている、ということで。
まとめ(というかお願いプリーズ)
自力でライブラリを生成して試せる、というのは非常にありがたいですね。API開発者は各言語用のライブラリを提供する必要はないので、swagger.yamlだけでも公開しておいてくれると非常に助かります。はいはいAPIね、Javaがねーじゃんそっ閉じってことをしなくて済むようになるので。
ちなみに私はSwaggerファイルの仕様というか、長くなりがちなファイル構成に不満がありまくりんぐでしたので、RAMLに乗り換えてみようかと思っております。