laravel-openapiライブラリ ドキュメントを出力してみる 番外編 レスポンスのHTTPステータス

# 概要

- laravel-openapiにてレスポンスのHTTPステータスの種類と指定方法をまとめてみる。

# 前提

- 下記の記事の内容と若干かぶるのでこちらも読んで頂くとスムーズかもしれません。
    - [laravel-openapi ドキュメントを出力してみる vol3 レスポンス](https://qiita.com/miriwo/items/eef47179adcc68d107c2)

# レスポンスのHTTPステータスを指定する方法

- 下記のようにリクエストクラスでHTTPステータスを指定する。

    ```php
    <?php
    
    namespace App\OpenApi\Responses;
    
    use App\OpenApi\Schemas\UserUpdateOkResponseSchema;
    use GoldSpecDigital\ObjectOrientedOAS\Objects\MediaType;
    use GoldSpecDigital\ObjectOrientedOAS\Objects\Response;
    use Vyuldashev\LaravelOpenApi\Factories\ResponseFactory;
    
    class UserUpdateOkResponse extends ResponseFactory
    {
        public function build(): Response
        {
            return Response::ok()
                ->description('成功レスポンス')
                ->content(
                    MediaType::json()
                        ->schema(UserUpdateOkResponseSchema::ref())
                );
        }
    }
    ```

- 上記処理の`Response::ok()`の部分でHTTPステータスを指定している。この箇所を用意されているライブラリのスタティックな関数にしてあげることでレスポンスのHTTPステータスを変更する事ができる。
- `Response::ok()`の部分でHTTPステータスを指定しているため、レスポンスの種類だけリクエストクラスのファイル記載が必要になる。（200 OKでUserUpdateOkResponse.php、400 BadRequestで　UserUpdateBadRequestResponse.phpの様に）

# 任意のHTTPステータスの指定

- HTTPステータス指定関数は`アプリ名ディレクトリ/vendor/goldspecdigital/oooas/src/Objects/Response.php`で定義されている。デフォルトでいくつかのHTTPステータスに対応する関数が定義されている。
- HTTPステータスと関数の対応表を下記に記載する。

    | HTTPステータス | 関数 |
    | --- | --- |
    | 200 | ok() |
    | 201 | created() |
    | 301 | movedPermanently() |
    | 302 | movedTemporarily() |
    | 400 | badRequest() |
    | 401 | unauthorized() |
    | 403 | forbidden() |
    | 404 | notFound() |
    | 422 | unprocessableEntity() |
    | 429 | tooManyRequests() |
    | 500 | internalServerError() |

# 使いたいHTTPステータスが存在しない場合（オーバーライド編）

- レスポンスで使いたいHTTPステータスが存在しない場合、当該クラスをオーバーライドすることで解決できる。
- たとえはlaravelのCSRF対応忘れによる419エラーを追加して指定したい場合は下記のように作業する。
    1. オーバーライド用ベースレスポンスクラスの作成
    1. 当該のステータスを記載するレスポンスクラスの継承元をオーバーライド用ベースレスポンスクラスに変更
    1. 定義した関数をスタティックに呼び出して独自HTTPステータス割当
- 実際に上記の方法でやってみた。
- オーバーライド用ベースレスポンスクラスを記載するOrgResponse.phpを`アプリ名ディレクトリ/app/OpenAPI/Responses`ディレクトリ直下に作成する。
- OrgResponse.phpを下記のように記載する。（`Response::csrf()`としたときに419が変えるよう関数を追加）

    ```アプリ名ディレクトリ/app/OpenAPI/Requests/OrgResponse.php
    <?php
    
    declare(strict_types=1);
    
    namespace App\OpenApi\Responses;
    
    use GoldSpecDigital\ObjectOrientedOAS\Objects\Response;
    
    /**
     * @property int|null $statusCode
     * @property string|null $description
     * @property \GoldSpecDigital\ObjectOrientedOAS\Objects\Header[]|null $headers
     * @property \GoldSpecDigital\ObjectOrientedOAS\Objects\MediaType[]|null $content
     * @property \GoldSpecDigital\ObjectOrientedOAS\Objects\Link[]|null $links
     */
    class OrgResponse extends Response
    {
        /**
         * @param string|null $objectId
         * @return static
         */
        public static function csrf(string $objectId = null): self
        {
            return static::create($objectId)
                ->statusCode(419)
                ->description('CSRF指定忘れのエラー');
        }
    }
    ```

- 下記の様にレスポンスクラスでOrgResponseをuseする。

    ```php
    <?php
    
    namespace App\OpenApi\Responses;
    
    use App\Models\User;
    use App\OpenApi\Schemas\UserUpdateBadRequestResponseSchema;
    use GoldSpecDigital\ObjectOrientedOAS\Objects\MediaType;
    use App\OpenApi\Responses\OrgResponse as Response;
    use Vyuldashev\LaravelOpenApi\Factories\ResponseFactory;
    
    class UserUpdateBadRequestResponse extends ResponseFactory
    {
        public function build(): Response
        {
            return Response::csrf()
                ->description('419 エラー')
                ->content(
                    MediaType::json()
                        ->schema(UserUpdateBadRequestResponseSchema::ref())
                );
        }
    }
    ```

- あとは上記のレスポンスクラスを任意のコントローラーの関数にアノテーションで指定すれば良い。

# 使いたいHTTPステータスが存在しない場合（レスポンスクラスで指定編）

- オーバーライドまでしなくても当該のレスポンスクラスにメソッドチェーンで指定することで独自のHTTPステータスでレスポンスが返せるようだ。
- オーバーライド編で記載したものと同じ様に419のレスポンスを返してみよう。
- 下記の様にstatusCode()関数をメソッドチェーンに含ませて引数でステータスコードを指定してあげれば良い。

    ```php
    <?php
    
    namespace App\OpenApi\Responses;
    
    use App\Models\User;
    use App\OpenApi\Schemas\UserUpdateBadRequestResponseSchema;
    use GoldSpecDigital\ObjectOrientedOAS\Objects\MediaType;
    use App\OpenApi\Responses\OrgResponse as Response;
    use Vyuldashev\LaravelOpenApi\Factories\ResponseFactory;
    
    class UserUpdateBadRequestResponse extends ResponseFactory
    {
        public function build(): Response
        {
            return Response::create()
                ->statusCode(419)
                ->content(
                    MediaType::json()
                        ->schema(UserUpdateBadRequestResponseSchema::ref())
                );
        }
    }
    ```

- 独自のHTTPステータスを別のレスポンスでも使う場合、オーバーライドを用いたほうが良さそうだ。
- 独自のHTTPステータスを当該のリクエストでしか使わない場合、レスポンスクラスで指定したほうが良さそうだ。