Zend Expressive 2 - REST API(JSON) - 版本控制(在标题中) - FastRoute?

时间:2017-10-21 08:38:36

标签: php rest api versioning zend-expressive

我正在构建Zend Expressive 2 REST API(JSON)并希望直接对我的API进行版本控制。我使用Zend ServiceManager + FastRoute进行路由。

我找到了这个用于REST API版本控制的有用链接,并决定在请求标头中使用版本控制:

问题:

如何实现api版本控制;详细介绍了中间件动作的路由;在表达2? (使用FastRoute)

接受标题(带版本的JSON API):

<head>
</head>
<body>
<table>
  <tr>
    <td>Name:</td>
    <td id="idname"></td>
  </tr>
</table>
<script type="text/javascript">
  function getUrlVars() {
    var vars = {};
    var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi,
      function (m, key, value) {
        vars[key] = value;
      });
    return vars;
  }

  var name= unescape(getUrlVars().txtname);
  document.getElementById("idname").innerHTML = name;
</script>
</body>

期望的结构(应用):

Accept: application/vnd.api+json;version=2

我的代码片段:(版本检测有效,但如何路由?)

pipeline.php

/
 config/
 data/
 public/
 src/
     App/
         V1/
            Action/
                   SomeResource.php        // <- in Version 1
                   ...
         V2/
             Action/
                   SomeResource.php        // <- in Version 2
                   ...
         ...
vendor/
...

routes.php文件

<?php
// ...
// The error handler should be the first (most outer) middleware to catch
// all Exceptions.
$app->pipe(ErrorHandler::class);
$app->pipe(ContentTypeJsonApiVersioning::class);  // <-- detect version work quite well
$app->pipe(ServerUrlMiddleware::class);

ContentTypeJsonApiVersioning.php

<?php
// ...
//
$app->route('/api/some-resource[/{id:\d+}]',
    [
        Auth\Action\AuthAction::class,
        Zend\Expressive\Helper\BodyParams\BodyParamsMiddleware::class,
        App\Action\SomeResourceAction::class
    ],
    ['GET', 'POST', 'PUT', 'DELETE'],
    'api.route.name'
);

1 个答案:

答案 0 :(得分:0)

fastroute做的是在URL上抛出一个正则表达式并解析它。因此传递请求属性不起作用。我可以想办法让它发挥作用:

  • 不要在标题中使用版本控制,而是在网址中使用它。但由于你特别要求它,我想这不是一个选择。
  • 重写ContentTypeJsonApiVersioning中的URL,并在将请求传递给路由器之前更新请求。所以基本上把它重写为/api/v1/resource/id
  • 将所有api请求传递给APiMiddlewareAction并在那里检查请求中传递的版本并加载正确的操作。

在最后一种情况下,你可以只有一条类似于:

的路线
[
    'name'            => 'api',
    'path'            => '/api/{resource:\w+}[/{resourceId:\d+}[/{relation:\w+}[/{relationId:\d+}]]]',
    'middleware'      => ApiMiddleware::class,
    'allowed_methods' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
    'options'         => [
        'defaults' => [
        ],
    ],
],

可能有更多解决方案。