laminas-api-tools/api-tools-content-negotiation

Laminas 模块,提供内容协商功能

1.8.0 2023-07-10 20:56 UTC

README

Build Status

🇷🇺 俄罗斯公民

我们是来自不同国家的 Laminas 参与者。我们中的许多人都有在俄罗斯和乌克兰的朋友、亲戚和同事。我们中的一些人出生在俄罗斯。我们中的一些人目前住在俄罗斯。我们中的一些人的祖父母在二战中与法西斯作战。在这里,没有人支持法西斯主义。

我们其中一个人有一个乌克兰亲戚,她和儿子一起从家中逃出。由于前方道路上的轰炸,火车延误了。我们有一些朋友躲在防空洞里。在空袭后,我们焦急地等待他们的消息,空袭无差别地攻击医院、学校、幼儿园和住宅。我们不从任何媒体上得知这些,我们是直接看到的。

您足够信任我们使用我们的程序,我们请求您再次信任我们。我们需要帮助。走出家门,抗议这场毫无意义的战争。停止杀戮。说“停止战争!”

🇺🇸 致俄罗斯公民

我们来自世界各地。我们中的许多人都在俄罗斯和乌克兰有朋友、家人和同事。我们中的一些人出生在俄罗斯。我们中的一些人目前住在俄罗斯。我们中的一些人的祖父母在二战中与纳粹作战。在这里,没有人支持法西斯主义。

团队成员之一有一个乌克兰亲戚,她和儿子一起从家中逃出。由于前方道路上的轰炸,火车延误了。我们有一些朋友躲在防空洞里。在空袭后,我们焦急地等待他们的消息,空袭无差别地攻击医院、学校、幼儿园和住宅。我们不是从任何媒体上得知这些,这是我们亲身体验的。

您足够信任我们使用我们的软件。我们要求您信任我们说出真相。我们需要您的帮助。走出家门,抗议这场不必要的战争。停止杀戮。说“停止战争!”

简介

api-tools-content-negotiation 是一个模块,用于在 Laminas 框架应用程序中自动执行内容协商任务。

提供以下功能

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

需求

请参阅 composer.json 文件。

安装

运行以下 composer 命令

$ composer require laminas-api-tools/api-tools-content-negotiation

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

"require": {
    "laminas-api-tools/api-tools-content-negotiation": "^1.2"
}

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

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

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

laminas-component-installer

如果您使用 laminas-component-installer,该插件将自动将 api-tools-content-negotiation 作为模块安装。

配置

用户配置

此模块用户配置的最高级键是 api-tools-content-negotiation

键:controllers

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

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

示例

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

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

键:selectors

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

示例

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

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

'selectors' => [
    'HTML-Json' => [
        'Laminas\ApiTools\ContentNegotiation\JsonModel' => [
            'application/json',
            'application/*+json',
        ],
        'Laminas\ApiTools\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 发出相同的请求,或者使用包含 OPTIONS 重写值的 GET 请求,监听器将引发问题,因为在前一种情况下,没有为 POST 定义映射,而在后一种情况下,OPTIONS 不在 GET 的映射中。

系统配置

以下配置在 config/module.config.php 中提供,以启用模块的功能

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

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

'service_manager' => [
    'factories' => [
        ContentTypeListener::class        => InvokableFactory::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,
    ],
],

层压事件

监听器

Laminas\ApiTools\ContentNegotiation\AcceptListener

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

Laminas\ApiTools\ContentNegotiation\ContentTypeListener

此监听器连接到MvcEvent::EVENT_ROUTE事件,优先级为-625。它负责检查Content-Type头,以确定内容主体应该如何反序列化。然后,这些值将被保存在ParameterDataContainer中,并存储在MvcEvent对象的LaminasContentNegotiationParameterData键中。

Laminas\ApiTools\ContentNegotiation\AcceptFilterListener

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

Laminas\ApiTools\ContentNegotiation\ContentTypeFilterListener

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

Laminas\ApiTools\ContentNegotiation\HttpMethodOverrideListener

  • 自 1.3.0 版本以来

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

层压服务

控制器插件

Laminas\ApiTools\ContentNegotiation\ControllerPlugin\RouteParam (也称为 "routeParam")

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

use Laminas\Mvc\Controller\AbstractActionController;

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

Laminas\ApiTools\ContentNegotiation\ControllerPlugin\QueryParam (也称为 "queryParam")

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

use Laminas\Mvc\Controller\AbstractActionController;

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

Laminas\ApiTools\ContentNegotiation\ControllerPlugin\BodyParam (也称为 "bodyParam")

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

use Laminas\Mvc\Controller\AbstractActionController;

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

Laminas\ApiTools\ContentNegotiation\ControllerPlugin\RouteParams (也称为 "routeParams")

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

use Laminas\Mvc\Controller\AbstractActionController;

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

Laminas\ApiTools\ContentNegotiation\ControllerPlugin\QueryParams (也称为 "queryParams")

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

use Laminas\Mvc\Controller\AbstractActionController;

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

Laminas\ApiTools\ContentNegotiation\ControllerPlugin\BodyParams (也称为 "bodyParams")

一个控制器插件(Laminas\Mvc\Controller\AbstractActionController可调用)将返回所有内容协商主体参数。

use Laminas\Mvc\Controller\AbstractActionController;

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