FOSRestBundle - 在参数包中注入 body 参数是一个好习惯吗?
FOSRestBundle - is a good practice to inject body params in the parameter bag?
我们使用的是 FOS Rest 包,起初我们没有意识到 body 侦听器处于活动状态。
与此同时,我们创建了很多资源,这些资源通过 body 以 JSON 格式接收数据。目前我们只支持 JSON 格式。现在控制器中的很多控制器正在从 Symfony ParameterBag 中检索参数,因为 body 监听器正在那里注入它们。
那么,您认为将此责任留给 body 侦听器并在控制器中通过参数包检索参数是一种好做法吗?这样无论是GET,POST还是body,所有的参数都是通过参数包到达控制器的。
我们正在关注这个问题,因为我们的一些 API 客户在发出请求时没有在 header 中提供 content-type,因此,body 侦听器没有在参数包中注入 body 。所以在控制器中我们没有可用的参数。
提前致谢!
一般来说,API 设计最重要的方面之一应该是实现的一致性,以便您的消费者了解如何与您的系统交互。为此,我将遵循以下模式:
- 如果 body 侦听器有助于您的开发,请保持启用状态;这个监听器是帮助你编写更简单控制器的捷径,所以如果它对你有用,就没有理由放弃它
- 对于期望 JSON 请求 body 的 API 端点,如果正确
Content-type: application/json
header,则向消费者报告他们正在发出非法请求] 丢失(这可以通过在路线上设置 _format
要求来完成;参见 advanced routing example)
如果您必须支持这些未通过 header 的旧用户,您可以在 kernel.request
事件上创建一个具有非常高优先级的侦听器,它只检查检测到的 MIME 类型,如果缺少,则执行如下操作:
if ($request->getRequestFormat() != 'json') {
json_decode($request->getContent());
if (json_last_error() == JSON_ERROR_NONE) {
$request->setRequestFormat('json');
}
}
(这里 json_last_error()
的使用并不完美;请参阅 this question 以获得更详细的讨论。)
最后,如果您还没有,请确保您将 API 控制器限制为正确的请求方法,再次确保它们被正确使用并让你的开发和使用更加一致。例如,如果您使用注释,这就像使用 FOSRestBundle-provided @Get
、@Post
等代替通常的 @Route
一样简单。如果您使用 YML 或 XML 配置,则为 methods
属性.
尽管单个控制器当然可以通过 GET
(带有请求参数)、POST
(通过 URL-encoded 表单数据)或 POST
or PUT
with JSON data and a body listener-conversion, 这使得 API 非常复杂,因为你必须开始维护这些不同的案例,我认为对于您的用户来说,事情也会变得非常困难。
作为这些 API 的消费者,如果我在请求 body 中传递 JSON 但不包括正确的 header,我预计我的请求会失败],如果我将 x-www-form-urlencode
数据传递给 JSON-based API,我预计我的请求会失败。总的来说,对于 API 的维护者和消费者来说,最好严格遵守您接受的内容并始终遵循相同的模式。
我们使用的是 FOS Rest 包,起初我们没有意识到 body 侦听器处于活动状态。
与此同时,我们创建了很多资源,这些资源通过 body 以 JSON 格式接收数据。目前我们只支持 JSON 格式。现在控制器中的很多控制器正在从 Symfony ParameterBag 中检索参数,因为 body 监听器正在那里注入它们。
那么,您认为将此责任留给 body 侦听器并在控制器中通过参数包检索参数是一种好做法吗?这样无论是GET,POST还是body,所有的参数都是通过参数包到达控制器的。
我们正在关注这个问题,因为我们的一些 API 客户在发出请求时没有在 header 中提供 content-type,因此,body 侦听器没有在参数包中注入 body 。所以在控制器中我们没有可用的参数。
提前致谢!
一般来说,API 设计最重要的方面之一应该是实现的一致性,以便您的消费者了解如何与您的系统交互。为此,我将遵循以下模式:
- 如果 body 侦听器有助于您的开发,请保持启用状态;这个监听器是帮助你编写更简单控制器的捷径,所以如果它对你有用,就没有理由放弃它
- 对于期望 JSON 请求 body 的 API 端点,如果正确
Content-type: application/json
header,则向消费者报告他们正在发出非法请求] 丢失(这可以通过在路线上设置_format
要求来完成;参见 advanced routing example) 如果您必须支持这些未通过 header 的旧用户,您可以在
kernel.request
事件上创建一个具有非常高优先级的侦听器,它只检查检测到的 MIME 类型,如果缺少,则执行如下操作:if ($request->getRequestFormat() != 'json') { json_decode($request->getContent()); if (json_last_error() == JSON_ERROR_NONE) { $request->setRequestFormat('json'); } }
(这里
json_last_error()
的使用并不完美;请参阅 this question 以获得更详细的讨论。)最后,如果您还没有,请确保您将 API 控制器限制为正确的请求方法,再次确保它们被正确使用并让你的开发和使用更加一致。例如,如果您使用注释,这就像使用 FOSRestBundle-provided
@Get
、@Post
等代替通常的@Route
一样简单。如果您使用 YML 或 XML 配置,则为methods
属性.尽管单个控制器当然可以通过
GET
(带有请求参数)、POST
(通过 URL-encoded 表单数据)或POST
orPUT
with JSON data and a body listener-conversion, 这使得 API 非常复杂,因为你必须开始维护这些不同的案例,我认为对于您的用户来说,事情也会变得非常困难。
作为这些 API 的消费者,如果我在请求 body 中传递 JSON 但不包括正确的 header,我预计我的请求会失败],如果我将 x-www-form-urlencode
数据传递给 JSON-based API,我预计我的请求会失败。总的来说,对于 API 的维护者和消费者来说,最好严格遵守您接受的内容并始终遵循相同的模式。