ac/web-services-bundle

提供开发RESTful API的工具。

0.4.5 2015-10-02 18:22 UTC

README

Build Status

此捆绑包提供了用于开发RESTful API的通用API工作流程工具。

NIH: 此捆绑包中许多功能已在FOSRestBundle中存在,如果需要安全性,请使用该捆绑包。此捆绑包正在定期进行重大开发。

特性

  • 为注册的API事件触发请求生命周期事件
  • 利用JMS Metadata将传入数据序列化为已存在的对象的反序列化对象
  • 可选地将响应数据作为输出响应的一部分
  • 默认处理xml、json、jsonp和yml响应
  • 轻松将验证错误转换为有用的API响应
  • 轻松将传入数据序列化到现有对象中

安装

  1. 在您的composer.json中require ""ac/web-services-bundle": "~0.2.0""

  2. 使用composer更新它:composer update ac/web-services-bundle

  3. 在您的AppKernel.php中启用

    use AC\WebServicesBundle\ACWebServicesBundle;
    
    //...
    
    public function getBundles()
    {
        //...
        $bundles = array(
            //...
            new ACWebServicesBundle()
            //...
        );
        //....
    }
  4. 在您的app/config/config.yml中配置捆绑包

    这是一个示例配置块。所有部分都是可选的,并在随后的章节中详细说明。

    ac_web_services:
        serializer:
            allow_deserialize_into_target: true
        response_format_headers:
            yml:
                'Content-Type': 'text/x-yaml; charset=UTF-8'
            csv:
                'Content-Type': 'text/csv; charset=UTF-8'
        paths:
            '{^/api/override}':
                include_exception_data: false
                include_response_data: false
                allow_code_suppression: false
                allow_jsonp: false
                default_response_format: json
            '{^/api/}':
                include_exception_data: true
                include_response_data: true
                allow_code_suppression: true
                allow_jsonp: true
                default_response_format: json
                http_exception_map:
                    'AC\WebServicesBundle\Tests\Fixtures\FixtureBundle\BundleException': { code: 403, message: 'Custom error message' }
                additional_headers:
                    'x-custom-acwebservices': 'foo-bar-baz'

API路径配置

一般来说,您通过设置应用于某些路由的值来配置API的一般行为。当请求与配置的路径匹配时,会注册一个事件订阅者,该订阅者具有相关配置。此订阅者触发额外的API事件,类似于内核事件。从您的控制器中,您可以返回原始数据结构,这些数据结构可能包括通过JMSSerializerBundle配置进行序列化的对象。从控制器返回的信息将由serializer服务自动序列化为请求的数据传输格式。

例如

  1. 请求到http://example.com/api/foo?_format=json

  2. 路由到控制器MyBundle\Controller\FooController::someAction

  3. 它看起来像这样

     <?php
    
     namespace MyBundle\Controller;
     use Symfony\Bundle\FrameworkBundle\Controller\Controller;
     use AC\WebServicesBundle\ServiceResponse;
    
     class FooController extends Controller
     {
         public function someAction()
         {
             return new ServiceResponse(array(
                 'foo' => 'bar',
                 'baz' => 23
             ));
         }
     }
    
  4. 将返回此结果

     {
         "foo": "bar",
         "baz": 23
     }
    

请注意,将_format参数更改为xmlyml将返回这些格式的数据结构。

注意:如果缺少_format参数,则将返回默认格式,通常是json

响应数据 & 代码抑制

默认情况下,API响应还将包括一个包含HTTP响应代码和消息的response属性。此信息也包含在实际响应中,但作为方便API消费者而提供在响应体中。

此外,在某些情况下,一些客户端不正确地尊重实际的HTTP规范。如果处理此类客户端,捆绑包允许您进行始终返回200响应代码的API请求。如果发生这种情况,实际的HTTP代码和消息仍然会在响应体中正确设置。

上面的示例响应,如果include_response_datatrue,则看起来像这样

{
    "response": {
        "code": 200,
        "message": "OK"
    },
    "foo": "bar",
    "baz": 23
}

异常

在抛出异常的API路由上,它们将被捕获并使用上述描述的响应数据序列化。请注意,如果启用了代码抑制,实际的响应代码将始终为200,并且实际响应代码必须在返回的对象中检索。

如果从控制器抛出HTTP异常,则消息和代码将被保留。但是,如果抛出其他异常,则捆绑包将将其转换为带有500响应代码和默认"内部服务器错误"消息的HttpException

此行为也可以配置 - 您可以指定其他异常类的映射,以及应返回的HTTP状态码和消息。

异常返回上述描述的响应数据结构,例如

{
    "response": {
        "code": 500,
        "message": "Internal Server Error"
    }
}

事件

处理API请求时,该包会为所有API请求触发一些额外的事件。这些事件对于触发其他功能非常有用,例如记录或指标收集,这些功能应适用于所有API服务路由。触发的事件包括

  • ac.webservice.request - 当发起API请求,并且成功匹配到控制器时
  • ac.webservice.exception - 如果在API路由过程中遇到错误
  • ac.webservice.response - API的最终响应
  • ac.webservice.terminate - 发送API响应后

您可以使用ac.webservice.listener容器标签为这些事件中的任何一个注册监听器服务,或通过ac.webservice.subscriber标签注册多个事件的订阅者。

ValidationException

TODO: document ValidationException, see https://github.com/AmericanCouncils/WebServicesBundle/issues/3

序列化附加信息

如果serializer.allow_deserialize_into_target配置为true,将注册一些额外服务,允许将序列化数据写入预存在的对象。以下是一个来自控制器的示例用法

use AC\WebServicesBundle\Serializer\DeserializationContext;
use AC\WebServicesBundle\ServiceResponse;

//...

public function userUpdateAction(Request $req)
{
    $user = //... fetch pre-existing user however you do that
    $serializer = $this->container->get('serializer');
    $context = DeserializationContext::create()
        ->setTarget($user)
        ->setSerializeNested(true)
    ;

    //we'll assume the input is json for documentation purposes
    $modifiedUser = $serializer->deserialize($req->getContent(), get_class($user), 'json', $context);

    return ServiceResponse::create($modifiedUser);
}