osm/easy-rest-bundle

简单轻量级包,提供基于 JSON 的请求/响应和异常处理支持,用于使用 Symfony 开发 RESTful API。

安装量: 1,446

依赖关系: 0

建议者: 0

安全: 0

星标: 9

关注者: 2

分支: 2

开放问题: 0

类型:symfony-bundle

1.5.1 2019-03-05 10:58 UTC

This package is auto-updated.

Last update: 2024-09-06 09:14:10 UTC


README

SensioLabsInsight

简单轻量级包,提供基于 JSON 的请求/响应和异常处理支持,用于使用 Symfony 开发 RESTful API。

特性包括

  • 监听器用于解码 JSON 请求体并从 Request 类中访问它
  • 用于将 JSON 请求映射到普通 PHP 对象的 ParamConverter(使用 Symfony Serializer)
  • (自 1.3.0 版起) 使用 PHPDoc 提示支持嵌套对象和数组
  • 用于创建转换为 JSON 的 JSON 响应的监听器
    • 自动确定 DELETE 和 POST 响应的正确 HTTP 状态码
  • 异常控制器用于提供错误详情
    • 支持 Symfony 验证错误
    • 在开发环境中提供堆栈跟踪
  • 支持 Symfony 2 和 3
  • 仅使用纯监听器,易于配置和禁用某些功能。

不支持

  • XML 序列化器或无格式辅助工具
  • 头部格式协商

安装

步骤 1: 下载包

打开命令控制台,进入您的项目目录,并执行以下命令以下载此包的最新稳定版本

$ composer require osm/easy-rest-bundle "~1"

此命令需要您全局安装 Composer,具体请参阅 Composer 文档中的 安装章节

步骤 2: 启用包

然后,通过将其添加到项目 app/AppKernel.php 文件中注册的包列表中来启用包

<?php
// app/AppKernel.php

// ...
class AppKernel extends Kernel
{
    public function registerBundles()
    {
        $bundles = array(
            // ...

            new Osm\EasyRestBundle\OsmEasyRestBundle(),
        );

        // ...
    }

    // ...
}

步骤 3: 配置

app/config/config.yml 中启用包的配置

osm_easy_rest: ~

默认配置下,所有监听器和异常控制器都将启用。您可以使用以下选项更改此行为

osm_easy_rest:
    enable_exception_listener: true
    enable_json_param_converter: false
    enable_json_response_listener: true
    enable_request_body_listener: true

使用方法

JSON 请求和响应

响应

响应由 JsonResponseListener 监听器处理。它直接使用 Symfony JsonResponse 类来创建响应。您可以简单地使用数组或 JsonSerializable 对象。

GET 请求和响应

curl -i localhost:8000/v1/users/12/details

控制器

/**
 * @Method({"GET"})
 * @Route("/v1/users/12/details")
 */
public function getUserDetailsSample()
{
    return [
        'user' => [
            'id' => '8f262cd7-9f2d-4bca-825e-e2444b1a57e0',
            'username' => 'o',
            'isEnabled' => true,
            'roles' => [
                'ROLE_USER',
                'ROLE_ADMIN'
            ]
        ]
    ];
}

响应将如下所示

HTTP/1.1 200 OK
Cache-Control: no-cache, private
Connection: close
Content-Type: application/json

{
    "user": {
        "id": "8f262cd7-9f2d-4bca-825e-e2444b1a57e0", 
        "isEnabled": true, 
        "roles": [
            "ROLE_USER", 
            "ROLE_ADMIN"
        ], 
        "username": "o"
    }
}

请求

请求由 RequestContentListener 处理,它尝试将请求体转换为数组并将其包装在 ParameterBag 中。它仅对 POSTPUTPATCH 请求激活。因此,您可以从 Symfony 请求对象中访问这些参数。

带有 JSON 体的 POST 请求示例

curl -i -X POST \
  http://localhost:8000/access-tokens \
  -H 'content-type: application/json' \
  -d '{
	"username": "o",
	"password": "t0o53cur#",
}'

在控制器中,您可以访问参数,例如

/**
 * @Method({"POST"})
 * @Route("/access-tokens")
 */
public function createTokenAction(Request $request) {
    $username = $request->request->get('username'); // Will produce 'o'
    $password = $request->request->get('password'); // Will produce 't0o53cur#'
    
    ....
}

Json Param Converter

您还可以使用 PHP 对象进行映射和验证请求。您的请求对象应实现 JsonRequestInterface 接口。

use Osm\EasyRestBundle\ParamConverter\JsonRequestInterface;
use Symfony\Component\Validator\Constraints as Assert;

class CreateTokenRequest implements JsonRequestInterface
{

    /**
     * @Assert\NotBlank()
     */
    private $username;

    /**
     * @Assert\NotBlank()
     * @Assert\Regex("/(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[\W])/", message="Your password should contain a digit, a lowercase, an uppercase and a special character.")
     * @Assert\Length(min="8")
     */
    private $password;

    // Getter / setters removed for brevity

}

从控制器访问和验证

带有 JSON 体的 POST 请求示例

curl -i -X POST \
  http://localhost:8000/access-tokens \
  -H 'content-type: application/json' \
  -d '{
	"username": "o",
	"password": "t0o53cur#",
}'

参数转换器直接将 JSON 请求反序列化为您的对象。

/**
 * @Route()
 * @Method("POST")
 * @throws ValidationException
 */
public function createTokenAction(CreateTokenRequest $createTokenRequest, ValidatorInterface $validator)
{
    $errors = $validator->validate($createTokenRequest);

    if (count($errors)) {
        throw new ValidationException($errors);
    }

    $createTokenRequest->getUsername(); // Will produce 'o'
    $createTokenRequest->getPassword(); // Will produce 't0o53cur#'
}

处理异常和验证错误

默认情况下,异常控制器还将处理的异常转换为具有相应 HTTP 状态码的严格签名 JSON 响应。

/**
 * @Route("/test/precondition-failed")
 */
public function testPreconditionFailed(Request $request) {
    ...
    if (!$hasRequirements) {
        throw new PreconditionFailedHttpException('Invalid condition');
    }
}

响应将如下所示

$ curl -i localhost:8000/test/precondition-failed


HTTP/1.1 412 Precondition Failed
Cache-Control: no-cache, private
Connection: close
Content-Type: application/json

{
    "code": 0, 
    "errors": [], 
    "message": "Invalid condition", 
    "status_code": 412, 
    "status_text": "Precondition Failed", 
    "trace": []
}

development 模式下,对于未处理的异常,响应中也包含堆栈跟踪。

验证错误和 ExceptionWrapper

对于异常,此包附带 ExceptionWrapper,用于以优雅的方式创建错误响应。

与 Symfony 验证器错误一起使用

/**
 * @Method({"POST"})
 * @Route("/access-tokens")
 */
public function createTokenAction(Request $request) {
    ....

    $errors = $this->get('validator')->validate(
        $request->request->all(),
        new Assert\Collection(
            [
                'username' => [
                    new Assert\NotBlank(),
                ],
                'password' => [
                    new Assert\NotBlank(),
                    new Assert\Length(['min' => 5]),
                ],
            ]
        )
    );

    return (new ExceptionWrapper())
        ->setErrorsFromConstraintViolations($errors)
        ->setMessage(ErrorMessagesInterface::VALIDATION_ERROR)
        ->setStatusCode(Response::HTTP_UNPROCESSABLE_ENTITY)
        ->getResponse();
}

一个我们预期会失败的示例请求

curl -i -X POST \
  http://localhost:8000/access-tokens \
  -H 'content-type: application/json' \
  -d '{
	"username": "",
	"password": "t0o53cur#",
	"extra_field": false
}'

响应将如下所示

HTTP/1.1 422 Unprocessable Entity
Cache-Control: no-cache, private
Connection: close
Content-Type: application/json

{
    "code": 0, 
    "errors": [
        {
            "message": "This value should not be blank.", 
            "path": "username"
        }, 
        {
            "message": "This field was not expected.", 
            "path": "extra_field"
        }
    ], 
    "message": "Validation Failed", 
    "status_code": 422, 
    "status_text": "Unprocessable Entity", 
    "trace": []
}

您还可以构建自己的自定义错误详情

/**
 * @Route("/test/weird-error-test")
 */
public function getWeirdErrors()
{
    return (new ExceptionWrapper())
        ->setMessage('Something going wrong')
        ->setStatusCode(Response::HTTP_I_AM_A_TEAPOT)
        ->addError('foo', 'I don\'t expect an input like this')
        ->addError('bar', 'This should be an integer')
        ->getResponse();

}

您期望得到以下结构的响应

curl -i localhost:8000/test/weird-error-test


HTTP/1.1 418 I'm a teapot
Cache-Control: no-cache, private
Connection: close
Content-Type: application/json

{
    "code": 0, 
    "errors": [
        {
            "message": "I don't expect an input like this", 
            "path": "foo"
        }, 
        {
            "message": "This should be an integer", 
            "path": "bar"
        }
    ], 
    "message": "Something going wrong", 
    "status_code": 418, 
    "status_text": "I'm a teapot", 
    "trace": []
}

许可证

此包在 MIT 许可证下分发。版权所有 (c) 2015-2018 Osman Ungur