Laravel 底層是如何處理HTTP請求

Laravel00發表於2021-02-04

一、概述

web 伺服器對 HTTP 請求的處理流程大體上都是這樣的:在某個埠監聽請求,請求進入後執行程式,然後將程式執行結果以響應的形式傳送出去。

Laravel 框架構建的 Web 應用處理 HTTP 請求的流程亦是如此。所有 HTTP 請求都會被轉發到單入口檔案 /public/index.php。

二、剖析

逐行分析 index.php 的程式碼。

1、引入自動載入

require __DIR__.'/../vendor/autoload.php';

2、建立一個 Application 例項,作為全域性的服務容器,並將處理請求的核心類Kernel實現例項 繫結到該容器中。

$app = require_once __DIR__.'/../bootstrap/app.php';

注:app.php檔案內的處理:

<?php
// 建立一個 Application 例項
$app = new Illuminate\Foundation\Application(
    $_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);

// 繫結處理HTTP請求的介面實現 到服務容器
$app->singleton(
    Illuminate\Contracts\Http\Kernel::class,
    App\Http\Kernel::class
);

// 繫結處理CLI請求的介面實現 到服務容器
$app->singleton(
    Illuminate\Contracts\Console\Kernel::class,
    App\Console\Kernel::class
);

$app->singleton(
    Illuminate\Contracts\Debug\ExceptionHandler::class,
    App\Exceptions\Handler::class
);

// 返回應用程式例項
return $app;

3、從服務容器中解析處理 HTTP 請求的 Kernel 例項

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

這裡的 make 方法在 Illuminate\Foundation\Application 中,作用就是解析


4、處理 HTTP 請求的核心程式碼

$response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
);

$kernel 是 App\Http\Kernel 的父類,即 Illuminate\Foundation\Http\Kernel,我們進入到 handle() 方法

/**
 * 處理傳入的http請求,獲取一個 Request,返回一個 Response
 * 輸入http請求,返回http響應
 *
 * Handle an incoming HTTP request.
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\Response
 */
public function handle($request)
{
    try {
        $request->enableHttpMethodParameterOverride();
        $response = $this->sendRequestThroughRouter($request);
    } catch (Exception $e) {
        $this->reportException($e);
        $response = $this->renderException($request, $e);
    } catch (Throwable $e) {
        $this->reportException($e = new FatalThrowableError($e));
        $response = $this->renderException($request, $e);
    }
    $this->app['events']->dispatch(
        new RequestHandled($request, $response)
    );
    return $response;
}

我們發現實際進行處理的是 sendRequestThroughRouter() 這個方法

protected function sendRequestThroughRouter($request)
{
    $this->app->instance('request', $request);
    Facade::clearResolvedInstance('request');

    // 在傳送請求到路由之前,先呼叫 bootstrap() 方法運用應用的啟動類
    $this->bootstrap();

    /**
    * 以管道模式來處理 HTTP 請求
    *
    * 全域性中介軟體都校驗通過才會將請求分發到路由器進行處理
    * 路由器會將請求 URL 路徑與應用註冊的所有路由進行匹配,如果有匹配的路由,則先收集該路由所分配的所有路由中介軟體
    * 通過這些路由中介軟體對請求進行過濾,所有路由中介軟體校驗通過才會執行對應的匿名函式或控制器方法,執行相應的請求處理邏輯
    * 最後準備好待傳送給客戶端的響應。
    */
    return (new Pipeline($this->app))
            ->send($request)
            ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
            ->then($this->dispatchToRouter());
}


5、傳送響應

$response->send();


6、終止程式,做一些善後清理工作(主要包括執行終止中介軟體,以及註冊到服務容器的一些終止回撥)

$kernel->terminate($request, $response);



文章來自:www.haveyb.com/article/166
學習與交流:Laravel技術交流微信群

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章