ac / web-services-bundle
提供开发RESTful API的工具。
Requires
- php: >=5.4.0
- fzaninotto/faker: ~1.3
- jms/serializer-bundle: ~0.13
- lstrojny/functional-php: *@dev
- mockery/mockery: ~0.9
- symfony/framework-bundle: ~2.2
- willdurand/negotiation: ~1.2
Requires (Dev)
- phpunit/phpunit: ~4.0
- sensio/framework-extra-bundle: ~2.2
- symfony/monolog-bundle: ~2.2
- symfony/symfony: ~2.2
Conflicts
- jms/serializer: <0.15
- jms/serializer-bundle: <0.13
README
此捆绑包提供了用于开发RESTful API的通用API工作流程工具。
NIH: 此捆绑包中许多功能已在FOSRestBundle中存在,如果需要安全性,请使用该捆绑包。此捆绑包正在定期进行重大开发。
特性
- 为注册的API事件触发请求生命周期事件
- 利用JMS Metadata将传入数据序列化为已存在的对象的反序列化对象
- 可选地将响应数据作为输出响应的一部分
- 默认处理xml、json、jsonp和yml响应
- 轻松将验证错误转换为有用的API响应
- 轻松将传入数据序列化到现有对象中
安装
-
在您的
composer.json
中require ""ac/web-services-bundle": "~0.2.0"
" -
使用composer更新它:
composer update ac/web-services-bundle
-
在您的
AppKernel.php
中启用use AC\WebServicesBundle\ACWebServicesBundle; //... public function getBundles() { //... $bundles = array( //... new ACWebServicesBundle() //... ); //.... }
-
在您的
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
服务自动序列化为请求的数据传输格式。
例如
-
请求到
http://example.com/api/foo?_format=json
-
路由到控制器
MyBundle\Controller\FooController::someAction
-
它看起来像这样
<?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 )); } }
-
将返回此结果
{ "foo": "bar", "baz": 23 }
请注意,将
_format
参数更改为xml
或yml
将返回这些格式的数据结构。
注意:如果缺少
_format
参数,则将返回默认格式,通常是json
。
响应数据 & 代码抑制
默认情况下,API响应还将包括一个包含HTTP响应代码和消息的response
属性。此信息也包含在实际响应中,但作为方便API消费者而提供在响应体中。
此外,在某些情况下,一些客户端不正确地尊重实际的HTTP规范。如果处理此类客户端,捆绑包允许您进行始终返回200
响应代码的API请求。如果发生这种情况,实际的HTTP代码和消息仍然会在响应体中正确设置。
上面的示例响应,如果include_response_data
为true
,则看起来像这样
{
"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); }