Building CORS APIs with Lumen
PHP:7.2
Lumen:6.3
Lumen 是一個基於 Laravel
的微型框架,最常應用在建立 API Service 上面。
隨著軟體技術的演進,越來越多網站專案都是走 SPA(Single Page Application) 架構,因此建立 CORS(Cross-Origin Resource Sharing)API 也漸漸地變成很常見的需求。
但是考量到安全性的問題,跨來源資源共用(CORS) 就會多出了許多規範,因此在 API 設計上就必須再特別處理 request
的部份。
Preflighted(預檢請求)
在開始之前,有一些 HTTP 的運作方式需要先瞭解。
由於跨站請求可能會攜帶使用者資料,所以要先進行預檢請求,因此在 CORS 的狀況之下,只要滿足 PUT
、DELETE
、POST
等請求,會先以 OPTIONS
向另一個 domain 送出 預檢請求(Preflighted)
,以確認後續請求是否可安全送出。
因此在設計 API 時,就必須多考量到這個部份。
Set up a CORS middleware
為了針對所有的 request
進行調整,因此我們可以在 app\Http\Middleware
建立一個 Middleware
,讓所有的 request
都可以套用。
app/Http/Middleware/CorsMiddleware.php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Response;
class CorsMiddleware
{
// 允許要求的 Origin
protected $allowOrigin = [
'http://localhost'
];
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$origin = $request->header('Origin');
// 判斷是否為合法來源
$isAllowOrigin = in_array($origin, $this->allowOrigin);
// 判斷是否為 HTTP OPTIONS method
$isOptions = $request->isMethod('OPTIONS');
if (!$isAllowOrigin && $isOptions) {
// 非法來源
return new Response('', Response::HTTP_FORBIDDEN);
}
if ($isOptions) {
// 合法來源的預檢請求
$response = new Response('', Response::HTTP_OK);
} else {
$response = $next($request);
}
// 設定 Header
return $response->withHeaders([
'Access-Control-Allow-Origin' => $origin,
'Access-Control-Allow-Methods' => '*',
'Access-Control-Allow-Headers' => 'Content-Type, X-Requested-With, Authorization',
]);
}
}
Set up routes
在設定好 Middleware
以後,要再設定 route
才能套用到所有的 endpoint
。
route/web.php
// 由於 HTTP 會送出 OPTIONS 的請求,因此還是需要 handle OPTIONS 的 request
$router->options('{any:.*}', ['middleware' => 'cors']);
// 綁定 CORS Middleware
$router->group(['middleware' => 'cors'], function () use ($router) {
$router->get('info', 'TestController@getInfo');
$router->post('update', 'TestController@updateInfo');
});
這樣就大功告成了。