[英]PSR-7 “attributes” on Response object
我正在使用 PSR-7(使用 Zend Expressive)进行开发。 我想出了方法
ServerRequestInterface::withAttribute()
我想知道为什么对象 Response 没有。 我想在“响应端”处理后通过中间件传递元数据。 是否有某种方式在 Response 上传递“属性”以进行后处理? 遵循架构指南来实现这一目标的最佳方法是什么?
最佳实践是使用请求对象在中间件之间传递数据。 响应是发送给客户端的内容,您希望保持这种状态。 请求仅存在于服务器上,您可以添加(敏感数据)属性来传递。 如果出现问题或者您在删除自定义数据之前提前返回响应,那么这无关紧要,因为您的响应是“干净的”。
此外,如果您需要传递数据:中间件始终按照从配置中获取的顺序执行。 这样就可以确保 MiddlewareX 中的请求对象包含 MiddlewareY 设置的数据。
更新:关于如何通过请求传递数据的示例。
中间件 2 设置了一个信使对象,中间件 4 可以使用它来设置再次出路时需要的数据。
<?php
namespace Middleware;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
class Middleware2
{
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next)
{
$messenger = new Messenger();
// Do something else before next middleware
if ($next) {
$response = $next($request->withAttribute(Messenger::class, $messenger), $response);
}
// Do something with the Response after it got back
// At this point the $messenger object contains the updated data from Middleware4
return $response->withHeader('Content-Language', $locale);
}
}
中间件 4 获取信使对象并更新其值。
<?php
namespace Middleware;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
class Middleware4
{
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next)
{
$messenger = $request->getAttribute(Messenger::class);
$messenger->info('going in');
// Do something else before next middleware
if ($next) {
$response = $next($request->withAttribute(FlashMessenger::class, $messenger), $response);
}
// Do something with the Response after it got back
$messenger->info('going out');
return $response->withHeader('Content-Language', $locale);
}
}
PSR-7
规范仅为服务器请求定义属性。 它们主要用于存储从传入请求中推导出的元数据,以便稍后在您到达域层时使用它们。
另一方面,响应通常在域层中创建,并在实际发送到客户端之前遍历所有中间件堆栈。 因此,添加到响应中的元数据将无法实际使用。
我想如果您想将数据从内部中间件传递到外部中间件,最好的方法是使用响应标头。
不确定这是否是“最佳实践”,但另一种可能性是简单地将您的数据对象注入中间件。
中间件 2 注入了一个信使对象并在其上设置了一些数据:
<?php
namespace Middleware;
use Interop\Http\Server\MiddlewareInterface;
use Interop\Http\Server\RequestHandlerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class Middleware2
{
private $messenger;
public function __construct(Messenger $messenger)
{
$this->messenger = $messenger;
}
public function process(
ServerRequestInterface $request,
RequestHandlerInterface $handler
): ResponseInterface {
$this->messenger->foo = 'bar';
$response = $handler->handle($request);
if ($this->messenger->foo = 'baz') {
return $response->withHeader('Really-Important-Header', 'Baz');
}
return $response;
}
}
中间件 4 更改数据:
<?php
namespace Middleware;
use Interop\Http\Server\MiddlewareInterface;
use Interop\Http\Server\RequestHandlerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class Middleware4
{
private $messenger;
public function __construct(Messenger $messenger)
{
$this->messenger = $messenger;
}
public function process(
ServerRequestInterface $request,
RequestHandlerInterface $handler
): ResponseInterface {
$this->messenger->foo = 'baz';
return $handler->handle($request);
}
}
您甚至可以使用其中一个中间件作为信使。
警告:您必须确保使用相同的信使对象构造两个类。 但这似乎是大多数依赖注入容器的情况。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.