こんにちは、バックエンドエンジニアの中嶋です。
昨今のプロダクト開発ではOpenAPIを用いたスキーマ駆動で行うことが多くなってきました。
もちろん規模や目的によって何を導入すべきか、あるいはスプレッドシートやチャットでの共有で済ませてしまうかは検討が必要ですが、今回はその中の選択肢のひとつとして、LaravelプロジェクトへのL5-Swagger導入とBasic認証の設定について簡単に紹介したいと思います。
1. 前提
確認環境
- Laravel 8.67
- L5-Swagger 8.0.9
OpenAPIとSwaggerとL5-Swagger
OpenAPIは「RESTful APIの仕様を記述するフォーマット」で、
SwaggerはSmartBear社が提供する「OpenAPIを便利に扱うためのツール」の一つです。
What is OpenAPI? Swagger vs. OpenAPI | Swagger Blog
ざっくり、要は「どんなURIのAPIがあってどんなリクエストとレスポンスなのかを定義したり共有できるもの」と言えましょう。
そして今回紹介するL5-Swaggerは、Swaggerの機能をLaravelプロジェクトで使えるようにしたライブラリです。
Laravelのプロジェクトの中でスキーマを定義すれば「/api/documentation」にアクセスすることで以下のようなページが生成&表示でき、APIの実行例を示したりPostmanのように実際にリクエストを送信することもできます。
2. L5-Swaggerの導入
Composerでインストールする
LaravelプロジェクトにおいてComposerでインストールします。
今回はLaravel8系を使用しています。
composer require "darkaonline/l5-swagger"
JSONスキーマを作成する
スキーマはPHPDocにアノーテーションで記述する方法とJSONファイルを直接記述する方法があります。
●アノーテーションの例
提供されているサンプルの記法に倣ってController等のPHPDocにアノーテーションを記述していきます。
/** * @OA\Get( * path="/projects/{id}", * operationId="getProjectById", * tags={"Projects"}, * summary="Get project information", * description="Returns project data", * @OA\Parameter( * name="id", * description="Project id", * required=true, * in="path", * @OA\Schema( * type="integer" * ) * ), * @OA\Response( * response=200, * description="successful operation" * ), * @OA\Response(response=400, description="Bad request"), * @OA\Response(response=404, description="Resource Not Found"), * security={ * { * "oauth2_security_example": {"write:projects", "read:projects"} * } * }, * ) */
記述し終わったら
php artisan l5-swagger:generate
を実行することでSwaggerドキュメントが生成されます。
なおドキュメント生成については.envファイルに、
L5_SWAGGER_GENERATE_ALWAYS=true
を記載すれば、ロードするたびに自動で実行してくれるように設定することもできます。
●JSONの例
プロジェクトの/storage配下に/api-docs/api-docs.json
を作成し、OpenAPI Specificationの記法にて記述していきます。
{ "/pets": { "get": { "description": "Returns all pets from the system that the user has access to", "responses": { "200": { "description": "A list of pets.", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/pet" } } } } } } } } }
JSONで直接定義する場合は特にコマンド実行は不要です。
なおスキーマはブラウザ版のSwaggerEdditerで編集・記述したり、エラーがないかの検証をすることができます。
画面で表示してみる
スキーマが作成できたら/api/documentation
にアクセスします。
プロジェクトにファイルが含まれているので、ローカル環境でも検証サーバーの環境でもアクセスできるのが確認できると思います。
開発の初期段階で仮のレスポンスを返すControllerを定義してサーバーに置いておけば、フロントエンドと共有できるモックサーバーとしても使えそうですね。
3. Basic認証を設定する
作成したAPIドキュメントは便利に使えるのですが、このままでは世界中にSwaggerドキュメントを公開した状態になってしまうのでBasic認証を設定していきます。
LaravelにおいてBasic認証を設定する方法としては、
の3つになるかと思います。
標準の「auth.basicミドルウェア」はDBを使用する形式であることとフレームワークのAuthライブラリに依存してしまうこと、またBasic認証のために他の外部ライブラリに依存したくないという考えから、今回は独自ミドルウェアを作成して設定していきます。
ミドルウェアを作成
適当な分かりやすい名称でミドルウェアを作成します。
php artisan make:middleware OriginalBasicAuthMiddleware
App/Http/Meddleware配下にファイルが生成されるので、中身を実装していきます。 今回の例では実行環境によってenvファイルに定義したユーザー名とパスワードを適用するように設定しています。
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; class OriginalBasicAuthMiddleware { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle(Request $request, Closure $next) { if (config('app.env') === 'local' || config('app.env') === 'testing') { return $next($request); } $username = $request->getUser(); $password = $request->getPassword(); if ($username == config('app.basic_auth_username') && $password == config('app.basic_auth_password')) { return $next($request); } header('WWW-Authenticate: Basic realm="plase user and passwoard!"'); header("HTTP/1.0 401 Unauthorized"); abort(401); return $next($request); } }
kernel.phpに追記
ミドルウェアが作成できたら、kernel.phpにも忘れずに追記して有効にしておきます。今回はルートミドルウェアとして設定します。
/** * The application's route middleware. * * These middleware may be assigned to groups or used individually. * * @var array */ protected $routeMiddleware = [ 'auth' => \App\Http\Middleware\Authenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, 'can' => \Illuminate\Auth\Middleware\Authorize::class, 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class, 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 'org.basic.auth' => \App\Http\Middleware\OriginalBasicAuthMiddleware::class, // 追加 ];
ルーティング設定を変更
最後に、適用させたいルートにミドルウェアを適用させます。 これにはvendorのconfigファイルをpublishする必要があります。
php artisan vendor:publish --provider "L5Swagger\L5SwaggerServiceProvider"
/config/.phpが作成されるので、「Route Group options」の項目に作成したミドルウェアを設定します。
〜略〜 /* * Route Group options */ 'group_options' => [ 'middleware' => ['org.basic.auth'] // 追加 ], ], 〜略〜
アクセスしてみる
認証を設定した環境においてブラウザアクセスしてみると、きちんとBasic認証を求められるように設定できました。
あとはenvファイルに設定したユーザー名とパスワードを入力すればSwaggerドキュメントを表示することができます。
まとめ
今回はLaravelにおけるL5-Swaggerの導入とBasic認証の設定方法について紹介しました。
なおスキーマの定義方法は、アノーテーションかJSONかymlファイルか、Stoplightを使うか等、日々議論していたりします。
これからもフロントエンドはSPAでバックエンドはAPIを提供するという構成は多いと思いますので、 チームメンバーとも話し合いながらより良い開発手法を模索していきたいと思います。
さいごに..
Wizではみんなで良いものを楽しく作るべく、積極的にエンジニアを募集しております。
↓↓興味がある方はぜひご覧ください!