老熟女激烈的高潮_日韩一级黄色录像_亚洲1区2区3区视频_精品少妇一区二区三区在线播放_国产欧美日产久久_午夜福利精品导航凹凸

重慶分公司,新征程啟航

為企業提供網站建設、域名注冊、服務器等服務

Laravel中處理OPTIONS請求的原理是什么

Laravel中處理OPTIONS請求的原理是什么,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

成都創新互聯是專業的建華網站建設公司,建華接單;提供成都網站設計、網站制作,網頁設計,網站設計,建網站,PHP網站建設等專業做網站服務;采用PHP框架,可快速的進行建華網站開發網頁制作和功能擴展;專業做搜索引擎喜愛的網站,專業的做網站團隊,希望更多企業前來合作!

1. 問題描述

Laravel處理OPTIONS方式請求的機制是個謎。

假設我們請求的URL是http://localhost:8080/api/test,請求方式是OPTIONS

如果請求的URL不存在相關的其它方式(如GETPOST)的請求,則會返回404 NOT FOUND的錯誤。

如果存在相同URL的請求,會返回一個狀態碼為200的成功響應,但沒有任何額外內容。

舉例而言,在路由文件routes/api.php中如果存在下面的定義,則以OPTIONS方式調用/api/test請求時,返回狀態碼為200的成功響應。

Route::get('/test', 'TestController@test');

但同時通過分析可以發現,這個OPTIONS請求不會進到此api路由文件的生命周期內,至少該GET請求所在路由文件api所綁定的中間件是沒有進入的。

此時如果手動添加一個OPTIONS請求,比如:

Route::get('/test', 'TestController@test');
Route::options('/test', function(Request $request) {
    return response('abc');
});

則至少會進入該GET請求所在路由文件api綁定的中間件,可以在相關handle函數中捕獲到這個請求。

2. 分析源碼

通過仔細查看Laravel的源碼,發現了一些端倪。

在文件vendor/laravel/framework/src/Illuminate/Routing/RouteCollection.php的第159行左右,源碼內容如下:

        $routes = $this->get($request->getMethod());

        // First, we will see if we can find a matching route for this current request
        // method. If we can, great, we can just return it so that it can be called
        // by the consumer. Otherwise we will check for routes with another verb.
        $route = $this->matchAgainstRoutes($routes, $request);

        if (! is_null($route)) {
            return $route->bind($request);
        }

        // If no route was found we will now check if a matching route is specified by
        // another HTTP verb. If it is we will need to throw a MethodNotAllowed and
        // inform the user agent of which HTTP verb it should use for this route.
        $others = $this->checkForAlternateVerbs($request);

        if (count($others) > 0) {
            return $this->getRouteForMethods($request, $others);
        }

        throw new NotFoundHttpException;

這里的邏輯是:

1. 首先根據當前HTTP方法(GET/POST/PUT/...)查找是否有匹配的路由,如果有(if(! is_null($route))條件成立),非常好,綁定后直接返回,繼續此后的調用流程即可;

2. 否則,根據$request的路由找到可能匹配的HTTP方法(即URL匹配,但是HTTP請求方式為其它品種的),如果count($others) > 0)條件成立,則繼續進入$this->getRouteForMethods($request, $others);方法;

3. 否則拋出NotFoundHttpException,即上述說到的404 NOT FOUND錯誤。

倘若走的是第2步,則跳轉文件的234行,可看到函數邏輯為:

    protected function getRouteForMethods($request, array $methods)
    {
        if ($request->method() == 'OPTIONS') {
            return (new Route('OPTIONS', $request->path(), function () use ($methods) {
                return new Response('', 200, ['Allow' => implode(',', $methods)]);
            }))->bind($request);
        }

        $this->methodNotAllowed($methods);
    }

判斷如果請求方式是OPTIONS,則返回狀態碼為200的正確響應(但是沒有添加任何header信息),否則返回一個methodNotAllowed狀態碼為405的錯誤(即請求方式不允許的情況)。

此處Laravel針對OPTIONS方式的HTTP請求處理方式已經固定了,這樣就有點頭疼,不知道在哪里添加代碼針對OPTIONS請求的header進行處理。最笨的方法是對跨域請求的每一個GETPOST請求都撰寫一個同名的OPTIONS類型的路由。

3. 解決辦法

解決方案有兩種,一種是添加中間件,一種是使用通配路由匹配方案。

總體思想都是在系統處理OPTIONS請求的過程中添加相關header信息。

3.1 中間件方案

在文件app/Http/Kernel.php中,有兩處可以定義中間件。

第一處是總中間件$middleware,任何請求都會通過這里;第二處是群組中間件middlewareGroups,只有路由匹配上對應群組模式的才會通過這部分。

這是總中間件$middleware的定義代碼:

    protected $middleware = [
        \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
        \App\Http\Middleware\TrustProxies::class,
    ];

這是群組中間件$middlewareGroups的定義代碼:

    /**
    * The application's route middleware groups.
    *
    * @var array
    */
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
        'api' => [
            'throttle:60,1',
            'bindings',
            \Illuminate\Session\Middleware\StartSession::class,
        ],
    ];

由于群組路由中間件是在路由匹配過程之后才進入,因此之前實驗中提及的OPTIONS請求尚未通過此處中間件的handle函數,就已經返回了。

因此我們添加的中間件,需要添加到$middleware數組中,不能添加到api群組路由中間件中。

app/Http/Middleware文件夾下新建PreflightResponse.php文件:

getMethod() === 'OPTIONS'){
            $origin = $request->header('ORIGIN', '*');
            header("Access-Control-Allow-Origin: $origin");
            header("Access-Control-Allow-Credentials: true");
            header('Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE');
            header('Access-Control-Allow-Headers: Origin, Access-Control-Request-Headers, SERVER_NAME, Access-Control-Allow-Headers, cache-control, token, X-Requested-With, Content-Type, Accept, Connection, User-Agent, Cookie, X-XSRF-TOKEN');
        }
        return $next($request);
    }
}

其中這里針對OPTIONS請求的處理內容是添加多個header內容,可根據實際需要修改相關處理邏輯:

$origin = $request->header('ORIGIN', '*');
header("Access-Control-Allow-Origin: $origin");
header("Access-Control-Allow-Credentials: true");
header('Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE');
header('Access-Control-Allow-Headers: Origin, Access-Control-Request-Headers, SERVER_NAME, Access-Control-Allow-Headers, cache-control, token, X-Requested-With, Content-Type, Accept, Connection, User-Agent, Cookie, X-XSRF-TOKEN');

至此,所有OPTIONS方式的HTTP請求都得到了相關處理。

3.2 通配路由匹配方案

如果不使用中間件,查詢Laravel官方文檔Routing,可知如何在路由中使用正則表達式進行模式匹配。

Route::get('user/{id}/{name}', function ($id, $name) {
    //
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);

類似的,可以撰寫針對OPTIONS類型請求的泛化處理路由條件:

Route::options('/{all}', function(Request $request) {
     return response('options here!');
})->where(['all' => '([a-zA-Z0-9-]|/)+']);

*注:這里正則表達式中不能使用符號*

因此,針對跨域問題,對于OPTIONS方式的請求可以撰寫如下路由響應:

Route::options('/{all}', function(Request $request) {
    $origin = $request->header('ORIGIN', '*');
    header("Access-Control-Allow-Origin: $origin");
    header("Access-Control-Allow-Credentials: true");
    header('Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE');
    header('Access-Control-Allow-Headers: Origin, Access-Control-Request-Headers, SERVER_NAME, Access-Control-Allow-Headers, cache-control, token, X-Requested-With, Content-Type, Accept, Connection, User-Agent, Cookie');
})->where(['all' => '([a-zA-Z0-9-]|/)+']);

關于Laravel中處理OPTIONS請求的原理是什么問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注創新互聯行業資訊頻道了解更多相關知識。


分享題目:Laravel中處理OPTIONS請求的原理是什么
文章分享:http://www.xueling.net.cn/article/jjjhpp.html

其他資訊

在線咨詢
服務熱線
服務熱線:028-86922220
TOP
主站蜘蛛池模板: 日躁夜躁狠狠躁2020 | 夫妻午夜视频 | 成人网站免费视频可能被黑 | 青草青在线 | 亚洲精品美女色诱在线播放 | 玩丰满高大邻居人妻无码 | 羞羞答答xxdd.tv| 日本妈妈黄色片 | 欧美成人免费观看视频 | 久久久久.com | 国产九九热视频 | 成人www | 国产视频一区二区在线播放 | 4438亚洲 | 亚洲免费成人在线 | 欧美激情国产日韩精品一区18 | 久久国产精品99久久久大便 | 在线精品国产一区二区三区 | 韩国日本在线观看 | 国产在线看片 | 久久艹天天艹 | 国产亚洲日韩在线一区二区三区 | 日本夜爽爽一二区 | 国产高清在线精品 | 好湿好紧太硬了我太爽了视频 | 国产日产欧美一区在线 | 中日韩亚洲人成无码网站 | 操久久久 | 亚洲香蕉伊综合在人在线观看 | 国产一区在线视频 | 免费久久人人爽人人爽AV | 欧美顶级毛片在线播放 | 69式精品视频免费观看 | 大地8在线观看免费影视大全 | 777婷婷天堂综合区色吧 | 少妇无内裤下蹲露大唇 | 久久久久无码精品国产H动漫 | 亚洲一区二区三区无码国产 | 四虎黄色 | 亚洲精品中文字幕无码A片老 | 特黄免费av |