pedrosalpr/laravel-api-problem

这是我的包 laravel-api-problem

0.0.3 2024-06-28 12:02 UTC

README

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

本包的目的是根据RFC 9457标准,简化API请求的错误输出。

它将错误输出转换为具有以下特征的json格式

  • 头部
    • Content-Type: application/problem+json
  • 响应
    • type:标识发生错误的错误类型的URI,例如 https://example.com/validation-error
    • title:人类可读的标识符,通常类型字段应该与同一类型的标题字段一起使用。例如,表单验证失败。
    • status:HTTP状态码的副本。
    • detail:有关特定问题的更多信息,如果适当,还包括纠正它的步骤。例如,有关表单验证问题的信息:用户名已被占用,请选择不同的用户名。
    • instance:特定发生情况的标识符,可能对客户端没有用,但可以包含在错误报告示例中。
    • 附加字段:可以添加任何字段以提供更多信息,并且预期消费客户端将忽略它们不支持的字段。
      • timestamp: (RFC 9457增强):指示问题生成的时间戳。这有助于记录和跟踪错误,特别是在时间至关重要的系统中。

示例

服务器响应

HTTP/1.1 422 Unprocessable Entity
Content-Type: application/problem+json
Content-Language: en
{
     "status": 422,
     "type": "https://example.test/validation-error",
     "title": "Form validation failed",
     "detail": "One or more fields have validation errors. Please check and try again.",
     "instance": "http://example.test/api/test/1",
     "timestamp": "2024-02-09T11:55:51.252968Z",
     "errors": [
        {
            "name": "username",
            "reason": "Username is already taken."
        },
        {
            "name": "email",
            "reason": "Email format is invalid."
        }
    ]
}

安装

您可以通过composer安装此包

composer require pedrosalpr/laravel-api-problem

用法

默认模式(Laravel 9和10的旧版本)

要使用它,只需进入Exceptions\Handler.php中的register方法,并添加以下代码

use Pedrosalpr\LaravelApiProblem\LaravelApiProblem;

public function register(): void
{
    ...

    $this->renderable(function (\Throwable $e, Request $request) {
        if ($request->is('api/*') || $this->shouldReturnJson($request, $e)) {
            $apiProblem = new LaravelApiProblem($e, $request);
            return $apiProblem->render();
        }
    });
}

如果您想调试,只需在返回之前添加以下行

dd($apiProblem->toDebuggableArray());

默认模式(Laravel 11)

要使用它,请将以下代码添加到bootstrap/app.php文件中的异常闭包

use Pedrosalpr\LaravelApiProblem\LaravelApiProblem;

    ...

    ->withExceptions(function (Exceptions $exceptions) {
        $exceptions->render(function (\Throwable $e, Request $request) {
            if ($request->is('api/*') || $this->shouldReturnJson($request, $e)) {
                $apiProblem = new LaravelApiProblem($e, $request);
                return $apiProblem->render();
            }
        });
    })...

在Api Problem模式中创建异常

存在创建扩展LaravelApiProblemException的异常的可能性。

这已经使得将异常转换为Api Problem模式变得更容易。

要这样做,只需运行以下命令

php artisan laravel-api-problem:exception {name}

例如

php artisan laravel-api-problem:exception DummyException

这将在Exceptions\ApiProblem内部创建一个异常类;

<?php

namespace App\Exceptions\ApiProblem;

use Pedrosalpr\LaravelApiProblem\Exceptions\LaravelApiProblemException;

class DummyException extends LaravelApiProblemException
{

}

自定义模式

如果您想自定义一个Api Problem类以添加您关于哪些错误响应应返回的指南,只需使用以下命令扩展该类

php artisan laravel-api-problem:extend

例如

php artisan laravel-api-problem:extend DummyApiProblem

这将在ApiProblem内部创建一个Api Problem类;

<?php

namespace App\ApiProblem;

use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Pedrosalpr\LaravelApiProblem\Http\LaravelHttpApiProblem;
use Pedrosalpr\LaravelApiProblem\LaravelApiProblem;

class DummyApiProblem extends LaravelApiProblem
{
    public function __construct(
        protected \Throwable $exception,
        protected Request $request
    ) {
        match (get_class($exception)) {
            \Exception::class => $this->dummy(),
            default => parent::__construct($exception, $request)
        };
    }

    protected function dummy()
    {
        $extensions = [
            'errors' => "Dummy",
        ];
        $this->apiProblem = new LaravelHttpApiProblem(
            Response::HTTP_I_AM_A_TEAPOT,
            $this->exception->getMessage(),
            $this->getUriInstance(),
            $extensions
        );
    }
}

并在匹配中添加异常类名称及其相应的方法,例如dummy()

Laravel 9和10的旧版本

Handler.php文件中将LaravelApiProblem对象实例替换为DummyApiProblem

    $this->renderable(function (\Throwable $e, Request $request) {
        if ($request->is('api/*') || $this->shouldReturnJson($request, $e)) {
            $apiProblem = new DummyApiProblem($e, $request);
            return $apiProblem->render();
        }
    });

Laravel 11

将以下代码添加到bootstrap/app.php文件中的异常闭包

    ->withExceptions(function (Exceptions $exceptions) {
        $exceptions->render(function (\Throwable $e, Request $request) {
            if ($request->is('api/*') || $this->shouldReturnJson($request, $e)) {
                $apiProblem = new DummyApiProblem($e, $request);
                return $apiProblem->render();
            }
        });
    })

测试

待办事项

变更日志

请参阅CHANGELOG以获取有关最近更改的更多信息。

贡献

请参阅CONTRIBUTING以获取详细信息。

安全漏洞

请查阅我们如何报告安全漏洞的安全策略(点击此处)

致谢

许可证

MIT许可证(MIT)。请参阅许可证文件以获取更多信息。