如何正确覆盖 `Illuminate\Routing\Router::toResponse` 以便为空响应发送 HTTP 状态代码 204?

Posted

技术标签:

【中文标题】如何正确覆盖 `Illuminate\\Routing\\Router::toResponse` 以便为空响应发送 HTTP 状态代码 204?【英文标题】:How to properly overwrite `Illuminate\Routing\Router::toResponse` in order to send HTTP status code 204 for empty responses?如何正确覆盖 `Illuminate\Routing\Router::toResponse` 以便为空响应发送 HTTP 状态代码 204? 【发布时间】:2022-01-15 20:42:23 【问题描述】:

我的 Laravel 项目有很多控制器方法,这些方法在成功时根本不返回任何内容或 void。我希望(更准确地说是需要)这些方法最终向客户端返回 204 No Content 响应。我想避免在我需要的每个控制器方法中添加return response()->noContent()。但是,如果我不这样做,Laravel 会向客户端发送一个带有空正文的 200 OK 响应。

方法Illuminate\Routing\Router::toResponse($request, $response) 负责这个。参数$response 等于控制器方法的返回值。如果控制器方法没有返回任何内容,$response 等于 null。方法toResponse($request, $response) 将参数$response 与不同的条件匹配,如果没有匹配toResponse($request, $response),则创建一个SymfonyResponse,状态码为200,主体为空。我想覆盖这个方法并添加另一个条件。如果$response === null,那么toResponse($request, $response) 应该创建一个SymfonfyResponse,状态码为204。

我的主要问题是我没有找到任何信息如何使框架调用我自己的路由器类实现。

【问题讨论】:

【参考方案1】:

找到了一个比覆盖Router 更容易的解决方案。我可以使用在控制器方法运行之后、但在响应发送到客户端之前修改响应的中间件:所谓的响应中间件(参见Laravel Documentation "Middleware $ Responses")。

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * Ensures that responses with empty content return status code 204.
 *
 * This fixes a bug in Laravel.
 */
class FixStatusCode 
  /**
   * Handle an incoming request.
   *
   * @param Request  $request
   * @param \Closure $next
   *
   * @return Response
   *
   * @throws \InvalidArgumentException
   */
  public function handle(Request $request, Closure $next): Response 
    /** @var Response $response */
    $response = $next($request);
    
    if (empty($response->getContent())) 
      $response->setStatusCode(Response::HTTP_NO_CONTENT);
    
    
    return $response;
  

然后,我必须像在App\Http\Kernel::$middleware 中的任何其他中间件一样注册这个中间件。

【讨论】:

以上是关于如何正确覆盖 `Illuminate\Routing\Router::toResponse` 以便为空响应发送 HTTP 状态代码 204?的主要内容,如果未能解决你的问题,请参考以下文章

Facebook SDK - 如何正确覆盖 onActivityResult()?

如何在 Python 中正确覆盖和调用超方法

如何在 Chrome 中覆盖用户代理样式表并正确显示我的设计

如何在 Java 中正确覆盖 toString()?

如何在情节提要中正确创建覆盖视图?

如何正确覆盖 `Illuminate\Routing\Router::toResponse` 以便为空响应发送 HTTP 状态代码 204?