iT邦幫忙

2019 iT 邦幫忙鐵人賽

1
Software Development

Laravel 原始碼分析系列 第 33

如何正確地在 Response 加 Header(1)

  • 分享至 

  • xImage
  •  

前一陣子,朋友在社群分享小知識:

$routeMiddleware 裡面的 middleware 加上 $header 的話會有問題,要在 $middleware 宣告才能保證生效

因為剛好筆者正在研究 Laravel 原始碼,所以就認真翻了一下。

Response header 是在分析 bootstrap 流程有提到 index.php 的這行程式碼才會送出:

$response->send();

因此只要了解 $response 如何建構,以及 Pipeline 經過了哪些關卡、被做了哪些修改,就能知道真正問題點在哪了。

Response 如何被建構出來的

在 middleware 裡,我們會預期 $next($request) 回來的結果會是 [Response][] 物件。這可以在 Router 裡找到蛛絲馬跡。在分析 Routing 時,有提到 runRouteWithinStack() 的實作,裡面在執行 Pipeline 的程式碼如下:

return (new Pipeline($this->container))
                ->send($request)
                ->through($middleware)
                ->then(function ($request) use ($route) {
                    // 實際執行 route 的地方在這裡:$route->run()
                    return $this->prepareResponse(
                        $request, $route->run()
                    );
                });

根據 Pipeline 的分析, $next($request) 拿到的結果,正是 prepareResponse() 的回傳結果。換句話說,它就是建構 Response 的方法。

回顧一下 prepareResponse() 的實作,事實上有機會對 Response 做處理的,只有下面這兩個方法:

$response->setNotModified();

$response->prepare($request);

解析 Middleware 的實作細節的時候,有提到 Pipeline 會被使用兩次,一次是上面所說的,也就是朋友所提到的 $routeMiddleware;另一次則是 $middleware,也就是在 Http Kernel 的這段程式碼:

protected function sendRequestThroughRouter($request)
{
    // 略

    return (new Pipeline($this->app))
                ->send($request)
                ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
                ->then($this->dispatchToRouter());
}

dispatchToRouter() 一直到 runRouteWithinStack() 的 call stack 如下:

Kernel::dispatchToRouter();
Router::dispatch();
Router::dispatchToRoute();
Router::runRoute();
Router::runRouteWithinStack();

這過程中,還有另一次 prepareResponse(),但如同上面 runRouteWithinStack() 所說,其實對 header 並沒有特別修改什麼。

因此可以知道建構與 Pipeline 過程,理論上不會影響 response header。


今天先看建構過程與 Pipeline 流程是否有問題,明天再來看預設的 middleware 是否有偷偷對 header 做什麼處理。


上一篇
Redirector 與 UrlGenerator 的關係
下一篇
如何正確地在 Response 加 Header(2)
系列文
Laravel 原始碼分析46
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言