續昨天,先來列一下 Http Kernel 預設有哪些 middleware:
protected $middleware = [ \App\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, ];
protected $middlewareGroups = [ 'web' => [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, ], ];
|
但查過原始碼,雖然有的 middleware 有調整過 response 內容,但並沒有任何一個 middleware 去改過 header,理論上是不會受影響的。但我們應該用驗證來證實程式是如我們所預期的,因此跟朋友確認程式內容,並實際做了一點實驗。
測試驗證
首先得知版本為 Laravel v5.7.0,我們先打開專案,來寫個 Feature 測試如下:
public function testBasicTest() { $routeMiddleware = function ($request, $next) { return $next($request) ->header('Access-Control-Allow-Origin', '*') ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); };
$router = $this->app->make('router'); $router->middleware(['web', $routeMiddleware])->get('/foo', function () { return ''; });
$this->get('/foo') ->assertStatus(200) ->assertHeader('Access-Control-Allow-Origin', '*') ->assertHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); }
|
對於設定 Router 的方法有疑問的話,可以參考之前分析 Routing 文章。
這個測試是通過的,但畢竟這只是程式上運行,跟啟用 web 服務或許會有落差,所以實際照著朋友的做法做一次:
建立 Cors middleware:
<?php
namespace App\Http\Middleware;
class Cors { public function handle($request, $next) { return $next($request) ->header('Access-Control-Allow-Origin', '*') ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); } }
|
Kernel 加上 alias:
protected $routeMiddleware = [ 'cors' => \App\Http\Middleware\Cors::class, ];
|
routes/api.php 加上測試用 route:
Route::middleware(['api', 'cors'])->group(function() { Route::get('/foo', function () { return ''; }); });
|
接著使用 Artisan 指令啟動服務:
php artisan serve
然後打開 http://localhost/api/foo 即可看到剛剛建立的測試 route。
驗證一切正常,該有的 header 是有的,所以可以推測是使用或測試的方法出錯導致錯誤的。
這篇記錄並不是責怪朋友,主要是想分享:這是從發現問題,到確認問題在或不在某個範圍內的過程。可以看到我們一開始從原始碼開始說明,但原始碼畢竟只是紙上談兵,所以也使用單元測試驗證,也做了實際整合程式的驗證。
開發程式的過程中,也會遇到許多奇怪的問題,我們可以像一開始一樣,直接翻原始碼確認,但時間容易拖很長,而且最後的結果依然不是可靠的;或許直接寫單元測試會是個可行的做法,寫測試即可馬上驗證想法是否正確,而且真的是一翻兩瞪眼啊!