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 的部份。

可以先參考 Getting Started with HTTP CORS

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');
});

這樣就大功告成了。

Categories: Lumen