zfcampus/zf-content-negotiation

此包已被废弃,不再维护。作者建议使用laminas-api-tools/api-tools-content-negotiation包代替。

提供内容协商功能的ZF模块

1.4.0 2018-05-07 19:46 UTC

README

仓库于2019年12月31日废弃

此仓库已迁移至laminas-api-tools/api-tools-content-negotiation

Build Status Coverage Status

简介

zf-content-negotiation是一个用于在Zend Framework应用程序中自动化内容协商任务的模块。

提供以下功能:

  • Accept头部媒体类型映射到特定的视图模型类型,并自动将控制器结果转换为这些视图模型类型。
  • 定义Accept头部媒体类型白名单;带有不在白名单中的Accept媒体类型的请求将立即被拒绝,并返回406 Not Acceptable响应。
  • 定义Content-Type头部媒体类型白名单;发送带有不在白名单中的Content-Type媒体类型的请求体内容的请求将被立即拒绝,并返回415 Unsupported Media Type响应。

要求

请参阅composer.json文件。

安装

运行以下composer命令

$ composer require zfcampus/zf-content-negotiation

或者,手动将以下内容添加到您的composer.json文件的require部分

"require": {
    "zfcampus/zf-content-negotiation": "^1.2"
}

然后运行composer update以确保安装模块。

最后,将模块名称添加到项目配置文件config/application.config.php中的modules键下

return [
    /* ... */
    'modules' => [
        /* ... */
        'ZF\ContentNegotiation',
    ],
    /* ... */
];

zf-component-installer

如果您使用zf-component-installer,则该插件将为您安装zf-content-negotiation作为模块。

配置

用户配置

此模块用户配置的最高级别配置键为zf-content-negotiation

键:controllers

controllers键用于将内容协商策略映射到特定的控制器服务名称(从顶级controllers部分)。控制器数组的值部分可以是命名选择器(见下文selectors),或选择器定义。

选择器定义由一个数组组成,数组的键是视图模型名称,值是媒体类型的索引数组,当匹配到这些媒体类型时,将选择该视图模型。

示例

'controllers' => [
    // Named selector:
    'Application\Controller\HelloWorld1' => 'Json',

    // Selector definition:
    'Application\Controller\HelloWorld2' => [
        'ZF\ContentNegotiation\JsonModel' => [
            'application/json',
            'application/*+json',
        ],
    ],
],

键:selectors

selectors 键用于创建用于在多个控制器之间重复使用的命名选择器定义。选择器数组的关键部分将是一个名称,用于关联选择器定义(该定义使用在 controllers 键中描述的格式)。

示例

'selectors' => [
    'Json' => [
        'ZF\ContentNegotiation\JsonModel' => [
            'application/json',
            'application/*+json',
        ],
    ],
],

选择器可以包含多个视图模型,每个视图模型与不同的媒体类型相关联,允许您提供多个表示形式。例如,以下选择器将允许控制器返回 JSON 或 HTML 输出

'selectors' => [
    'HTML-Json' => [
        'ZF\ContentNegotiation\JsonModel' => [
            'application/json',
            'application/*+json',
        ],
        'ZF\ContentNegotiation\ViewModel' => [
            'text/html',            
        ],
    ],
],

键:accept_whitelist

accept_whitelist 键用于指示内容协商模块对于给定的控制器服务名称哪些媒体类型是可接受的。当在键中配置了控制器服务名称以及匹配的媒体类型索引数组时,只有与请求的 Accept 标头匹配的媒体类型才允许被调度。不匹配的媒体类型将收到 406 Cannot honor Accept type specified 响应。

每个控制器服务名称键的值可以是字符串或字符串数组。

示例

'accept_whitelist' => [
    'Application\\Controller\\HelloApiController' => [
        'application/vnd.application-hello+json',
        'application/hal+json',
        'application/json',
    ],
],

键:content_type_whitelist

content_type_whitelist 键用于指示内容协商模块对于请求的 Content-Type 哪些媒体类型是有效的。当在键中配置了控制器服务名称以及匹配的媒体类型索引数组时,只有与请求的 Content-Type 标头匹配的媒体类型才允许被调度。不匹配的媒体类型将收到 415 Invalid content-type specified 响应。

每个控制器服务名称键的值可以是字符串或字符串数组。

示例

'content_type_whitelist' => [
    'Application\\Controller\\HelloWorldController' => [
        'application/vnd.application-hello-world+json',
        'application/json',
    ],
],

键:x_http_method_override_enabled

  • 自 1.3.0 版本起

这个布尔标志确定是否默认启用 HttpMethodOverrideListener

键:http_override_methods

  • 自 1.3.0 版本起

http_override_methods 键用于向 HttpMethodOverrideListener 提供允许覆盖的 HTTP 方法的映射,该映射通过 X-HTTP-Method-Override 标头指定。本质上,值是这样的

'Incoming HTTP request method' => $arrayOfAllowedOverrideMethods,

例如,如果您想允许 X-HTTP-Method-Override 标头发起一个使用替代方法的 HTTP GET 请求,您可能可以这样定义

'x_http_method_override_enabled' => true,
'http_override_methods' => [
    'GET' => [
        'HEAD',
        'POST',
        'PUT',
        'DELETE',
        'PATCH',
    ],
];

然后,要发起一个请求,您可以这样做

GET /foo HTTP/1.1
Host: example.com
X-HTTP-Method-Override: PATCH

some=content&more=content

上述请求将被解释为 PATCH 请求。如果通过 HTTP POST 发起相同的请求,或者如果发起一个带有覆盖值 OPTIONSGET 请求,监听器将引发问题,因为在前者中,没有为 POST 定义映射,而在后者中,OPTIONS 不在 GET 的映射中。

系统配置

以下配置在 config/module.config.php 中提供,以使模块能够正常工作

'filters' => [
    'aliases'   => [
        'Zend\Filter\File\RenameUpload' => 'filerenameupload',
    ],
    'factories' => [
        'filerenameupload' => Factory\RenameUploadFilterFactory::class,
    ],
],

'validators' => [
    'aliases'   => [
        'Zend\Validator\File\UploadFile' => 'fileuploadfile',
    ],
    'factories' => [
        'fileuploadfile' => Factory\UploadFileValidatorFactory::class,
    ],
],

'service_manager' => [
    'factories' => [
        ContentTypeListener::class        => InvokableFactory::class,
        'Request'                         => Factory\RequestFactory::class,
        AcceptListener::class             => Factory\AcceptListenerFactory::class,
        AcceptFilterListener::class       => Factory\AcceptFilterListenerFactory::class,
        ContentTypeFilterListener::class  => Factory\ContentTypeFilterListenerFactory::class,
        ContentNegotiationOptions::class  => Factory\ContentNegotiationOptionsFactory::class,
        HttpMethodOverrideListener::class => Factory\HttpMethodOverrideListenerFactory::class,
    ],
],

'controller_plugins' => [
    'aliases' => [
        'routeParam'  => ControllerPlugin\RouteParam::class,
        'queryParam'  => ControllerPlugin\QueryParam::class,
        'bodyParam'   => ControllerPlugin\BodyParam::class,
        'routeParams' => ControllerPlugin\RouteParams::class,
        'queryParams' => ControllerPlugin\QueryParams::class,
        'bodyParams'  => ControllerPlugin\BodyParams::class,
    ],
    'factories' => [
        ControllerPlugin\RouteParam::class  => InvokableFactory::class,
        ControllerPlugin\QueryParam::class  => InvokableFactory::class,
        ControllerPlugin\BodyParam::class   => InvokableFactory::class,
        ControllerPlugin\RouteParams::class => InvokableFactory::class,
        ControllerPlugin\QueryParams::class => InvokableFactory::class,
        ControllerPlugin\BodyParams::class  => InvokableFactory::class,
    ],
],

ZF 事件

监听器

ZF\ContentNegotiation\AcceptListener

此监听器附加到 MvcEvent::EVENT_DISPATCH 事件,优先级为 -10。它负责根据内容协商配置执行实际的选择和转换控制器视图模型。

ZF\ContentNegotiation\ContentTypeListener

此监听器附加到 MvcEvent::EVENT_ROUTE 事件,优先级为 -625。它负责检查 Content-Type 标头,以确定如何反序列化内容体。然后,值将保存在 ParameterDataContainer 中,该容器存储在 MvcEvent 对象的 ZFContentNegotiationParameterData 键下。

ZF\ContentNegotiation\AcceptFilterListener

此监听器附加到 MvcEvent::EVENT_ROUTE 事件,优先级为 -625。它负责确保由路由选择的控制器配置为响应当前请求的 Accept 标头中指定的特定媒体类型。如果不能,它将通过返回一个 406 Cannot honor Accept type specified 响应来短路 MVC 分发过程。

ZF\ContentNegotiation\ContentTypeFilterListener

此监听器附加到 MvcEvent::EVENT_ROUTE 事件,优先级为 -625。它负责确保匹配的路由控制器可以接受由当前请求的 Content-Type 标头中指定的媒体类型指定请求体中的内容。如果不能,它将通过返回一个 415 Invalid content-type specified 响应来短路 MVC 分发过程。

ZF\ContentNegotiation\HttpMethodOverrideListener

  • 自 1.3.0 版本起

此监听器附加到 MvcEvent::EVENT_ROUTE 事件,优先级为 -40,但只有当 x_http_method_override_enabled 配置标志被打开时。它负责检查是否存在 X-HTTP-Method-Override 标头,如果存在,则检查它是否包含当前 HTTP 请求方法调用允许的值集。如果是,则将 HTTP 请求方法重置为该标头的值。

ZF 服务

控制器插件

ZF\ContentNegotiation\ControllerPlugin\RouteParam (简称 "routeParam")

一个控制器插件(Zend\Mvc\Controller\AbstractActionController 可调用)将返回从路由匹配中获得的具有特定名称的单个参数。

use Zend\Mvc\Controller\AbstractActionController;

class IndexController extends AbstractActionController
{
    public function indexAction()
    {
        return $this->routeParam('id', 'someDefaultValue');
    }
}

ZF\ContentNegotiation\ControllerPlugin\QueryParam (简称 "queryParam")

一个控制器插件(Zend\Mvc\Controller\AbstractActionController 可调用)将返回从当前请求查询字符串中获得的单个参数。

use Zend\Mvc\Controller\AbstractActionController;

class IndexController extends AbstractActionController
{
    public function indexAction()
    {
        return $this->queryParam('foo', 'someDefaultValue');
    }
}

ZF\ContentNegotiation\ControllerPlugin\BodyParam (简称 "bodyParam")

一个控制器插件(Zend\Mvc\Controller\AbstractActionController 可调用)将返回从内容协商内容体中获得的单个参数。

use Zend\Mvc\Controller\AbstractActionController;

class IndexController extends AbstractActionController
{
    public function indexAction()
    {
        return $this->bodyParam('foo', 'someDefaultValue');
    }
}

ZF\ContentNegotiation\ControllerPlugin\RouteParams (简称 "routeParams")

一个控制器插件(Zend\Mvc\Controller\AbstractActionController 可调用)将返回所有路由参数。

use Zend\Mvc\Controller\AbstractActionController;

class IndexController extends AbstractActionController
{
    public function indexAction()
    {
        return $this->routeParams()
    }
}

ZF\ContentNegotiation\ControllerPlugin\QueryParams (简称 "queryParams")

一个控制器插件(Zend\Mvc\Controller\AbstractActionController 可调用对象),将返回所有查询参数。

use Zend\Mvc\Controller\AbstractActionController;

class IndexController extends AbstractActionController
{
    public function indexAction()
    {
        return $this->queryParams()
    }
}

ZF\ContentNegotiation\ControllerPlugin\BodyParams(别名 "bodyParams")

一个控制器插件(Zend\Mvc\Controller\AbstractActionController 可调用对象),将返回所有内容协商的正文参数。

use Zend\Mvc\Controller\AbstractActionController;

class IndexController extends AbstractActionController
{
    public function indexAction()
    {
        return $this->bodyParams()
    }
}