中间件 / 协商
实现内容协商的中间件
Requires
- php: ^7.2 || ^8.0
- middlewares/utils: ^3.0 || ^4.0
- psr/http-server-middleware: ^1.0
- willdurand/negotiation: ^3.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^2.0
- laminas/laminas-diactoros: ^2.2
- oscarotero/php-cs-fixer-config: ^1.0
- phpstan/phpstan: ^0.12
- phpunit/phpunit: ^8|^9|^10|^11
- squizlabs/php_codesniffer: ^3.0
README
使用 wildurand/Negotiation 实现内容协商的中间件。包含以下组件:
需求
- PHP >= 7.2
- PSR-7 http 库
- PSR-15 中间件分发器
安装
此包可通过 Composer 安装和自动加载,名称为 middlewares/negotiation。
composer require middlewares/negotiation
示例
Dispatcher::run([ new Middlewares\ContentType(), new Middlewares\ContentLanguage(['en', 'gl', 'es']), new Middlewares\ContentEncoding(['gzip', 'deflate']), ]);
ContentType
使用 Accept
头和文件扩展名检测首选 MIME 类型,并使用此值编辑头。如果缺失,也会添加 Content-Type
头到响应中。
在第一个参数中定义协商格式的优先级排序。默认使用 这些
//Use the default types $negotiator = new Middlewares\ContentType(); //Use only few types $negotiator = new Middlewares\ContentType(['html', 'json']); //Use only few types and configure some of them $negotiator = new Middlewares\ContentType([ 'html', 'json', 'txt' => [ 'extension' => ['txt'], 'mime-type' => ['text/plain'], 'charset' => true, ] ]);
errorResponse
如果协商没有匹配的格式,默认情况下中间件使用列表中第一个可用的格式(默认为 text/html
)。使用此选项返回一个 406
错误。可选地,您可以提供一个 Psr\Http\Message\ResponseFactoryInterface
,该接口将用于创建响应。如果没有定义,将使用 Middleware\Utils\Factory 自动检测。
$responseFactory = new MyOwnResponseFactory(); //Use default html format (the first provided) if no valid format was detected (By default) $negotiator = new Middlewares\ContentType(['html', 'json']); //Return a 406 response if no valid format was detected $negotiator = (new Middlewares\ContentType(['html', 'json']))->errorResponse(); //Return a 406 response using a specific responseFactory if no valid format was detected $negotiator = (new Middlewares\ContentType(['html', 'json']))->errorResponse($responseFactory);
charsets
协商中可用的字符集,通过 Accept-Charset
头。默认为 UTF-8
。
$negotiator = (new Middlewares\ContentType())->charsets(['UTF-8', 'ISO-8859-1']);
noSniff
添加 X-Content-Type-Options: nosniff
头,以减轻 MIME 混淆攻击。默认启用。
//Disable noSniff header $negotiator = (new Middlewares\ContentType())->noSniff(false);
attribute
将格式名称(如 json
、html
、css
等)存储在 ServerRequest
的属性中。
ContentLanguage
使用 Accept-Language
头或路径前缀检测首选语言,并使用此值编辑头。如果缺失,也会添加 Content-Language
头到响应中。
第一个参数是一个数组,包含按优先级排序的可协商语言。如果没有选择其他语言进行协商,则使用第一个值作为默认值。
$request = Factory::createServerRequest('GET', '/') ->withHeader('Accept-Language', 'gl-es, es;q=0.8, en;q=0.7'); Dispatcher::run([ new Middlewares\ContentLanguage(['es', 'en']), function ($request) { $language = $request->getHeaderLine('Accept-Language'); switch ($language) { case 'es': return 'Hola mundo'; case 'en': return 'Hello world'; } } ], $request);
usePath
启用此选项后,将使用基本路径来检测语言。如果您为每种语言有不同的路径,则这很有用,例如 /gl/foo
和 /en/foo
。
注意:路径中的语言优先于 Accept-Language
头。
$request = Factory::createServerRequest('GET', '/en/hello-world'); Dispatcher::run([ (new Middlewares\ContentLanguage(['es', 'en']))->usePath(), function ($request) { $language = $request->getHeaderLine('Accept-Language'); switch ($language) { case 'es': return 'Hola mundo'; case 'en': return 'Hello world'; } } ], $request);
redirect
用于返回一个 302
响应,重定向到包含语言的路径。这仅在启用 usePath
时有效,例如,如果请求 URI 是 /welcome
,则返回重定向到 /en/welcome
。
$responseFactory = new MyOwnResponseFactory(); //Use not only the Accept-Language header but also the path prefix to detect the language $negotiator = (new Middlewares\ContentLanguage(['es', 'en']))->usePath(); //Returns a redirection with the language in the path if it's missing $negotiator = (new Middlewares\ContentLanguage(['es', 'en']))->usePath()->redirect(); //Returns a redirection using a specific response factory $negotiator = (new Middlewares\ContentLanguage(['es', 'en']))->usePath()->redirect($responseFactory);
ContentEncoding
检测首选编码类型,通过 Accept-Encoding
头并使用此值编辑头。
$request = Factory::createServerRequest('GET', '/') ->withHeader('Accept-Encoding', 'gzip,deflate'); Dispatcher::run([ new Middlewares\ContentEncoding(['gzip']), function ($request) { echo $request->getHeaderLine('Accept-Encoding'); //gzip } ], $request);
有关最近更改的更多信息,请参阅 CHANGELOG,有关贡献的详细信息,请参阅 CONTRIBUTING。
MIT许可证(MIT)。请参阅许可证获取更多信息。