是的,可能瞭解 Laravel 的都知道,在 Laravel 中簡單的設置跨域,固然是選擇 barryvdh/laravel-cors
這個包。php
是的,我確實是在重複造輪子,barryvdh/laravel-cors
包實現很優秀了,可是它也有不少問題。而個人新輪子 medz/cors
也並非專門解決它的問題的,而是順便解決而已。medz/cors
包的靈感來自公司項目,公司的項目使用 Laravel 框架進行開發,前端使用徹底分離的方式。因此須要設置跨域,而傳統 nginx 設置跨域雖然可信,可是程序設置跨域優勢不言而喻(能夠設置多個容許跨域域名等,動態處理信息)。前端
medz/cors
這個包,支持在全部 PHP 的項目中使用。你只須要一些簡單的配置便可。而這裏主要先講在 Laravel 中的應用,由於目前內置支持暫時對 Laravel 作了很好的專屬處理。nginx
打算友好支持以下laravel
感謝 Composer
爲社區帶來的改變,如今咱們都喜歡它,因此你只須要在你的項目中使用:git
composer require medz/cors
好了,你已經安裝好了。若是你是 Laravel,那麼,如今你已經爲你的程序加上了跨域github
運行:web
php artisan vendor:publish --provider="Medz\Cors\Laravel\Providers\LaravelServiceProvider" --force
有興趣看配置的能夠看一下 config/cors.php
的配置。可是下面會專門講配置的。shell
爲了方便一些配置,個別 bool
、int
和 string
類型的配置可使用 .env
進行環境變量設置:後端
Key | 描述 |
---|---|
CORS_ALLOW_CREDENTIAILS | bool , 設置 Access-Control-Allow-Credentials 是 true 仍是 false |
CORS_ACCESS_CONTROL_MAX_AGE | int , 設置 Access-Control-Max-Age 的值,默認是 0 ,即關閉 |
CORS_LARAVEL_ALLOW_ROUTE_PERFIX | string ,路由匹配模式的匹配規則,由於使用 $request->is 進行檢查,因此你能夠參考 請求,默認是 * ,表明全部路由。 |
CORS_LARAVEL_ROUTE_GROUP_MODE | bool , 是否啓用「單一路由中間件」或者「路由中間件組」模式,默認是不啓用。 |
而後全部的配置以下(建議看一下 config/cors.php
文件每一個配置的註釋):api
Key | 描述 |
---|---|
allow-credentiails |
參考 CORS_ALLOW_CREDENTIAILS 配置 |
allow-headers |
列出容許的 header 字段列表,默認是 ['*'] 表明所有,你能夠設置例如「'[Content-Type', 'X-Requested-With'] 」只容許上面的兩個 header 字段,具體根據你的項目而定。一旦出現 * 成員,表明容許所有。 |
expose-headers |
列出了哪些首部能夠做爲響應的一部分暴露給外部。默認爲 [] 。 |
origins |
列出容許跨域的域名,默認是 ['*'] , 表明設置爲 * (只要出現 * 在列中都會返回 * ),例如設置 ['https://laravel-china.org'] ,能夠設置多個,程序會自動處理。 |
methods |
列出容許跨域請求的方法列表,默認是 ['*'] 表明全部方法。 |
max-age |
預檢請求返回的結果是否能夠被緩存,默認是 0 即表明不能夠被緩存,單位是「秒」你能夠設置容許預檢請求結果緩存多久。 |
laravel.allow-route-perfix |
參考 CORS_LARAVEL_ALLOW_ROUTE_PERFIX |
laravel.route-group-mode |
參考 CORS_LARAVEL_ROUTE_GROUP_MODE |
其實,你的 Laravel 程序依賴了這個medz/cors
你就不須要在進行任何代碼修改,就能夠直接使用了。由於 Laravel 有一個神奇的特色吧,就是發起 OPTIONS
預檢請求的時候,執行的中間件只有「全局中間件」,即 app/Http/Kernel.php
中 protected $middleware
所設置的中間件,因此針對 Laravel medz/cors
包自動在這裏添加了 Medz\Cors\Laravel\Middleware\Cors
中間件。你發現,這個中間件若是你進行了一些配置,他是不會執行其餘任何處理的。
若是你但願自定義全局中間件的執行順序,能夠手動把Medz\Cors\Laravel\Middleware\Cors
添加到$middleware
中。
這是解決 barryvdh/laravel-cors
的痛點之一吧,由於 barryvdh/laravel-cors
會給全部的路由都加上跨域信息設置,這真的不是在實際中須要的,咱們想要的是特定的路由組,或者特定的路由才支持跨域,其餘的路由沒法進行跨域請求。因此針對 Laravel 的開發中,有了這個模式。
而組模式須要用到的中間件叫作 Medz\Cors\Laravel\Middleware\ShouldGroup
,爲了方便使用,你能夠在 app/Http/Kernel.php
的 protected $routeMiddleware
中給它取一個簡短好記憶的別名,例如:
protected $routeMiddleware = [ 'cors-should' => \Medz\Cors\Laravel\Middleware\ShouldGroup::class, ];
我給它取了一個名字叫作 cors-should
,如今,你能夠在特定的路由中設置容許跨域:
Route::middleware('cors-should')->get('test-cors', function () {});
固然,你也能夠對一個路由組使用,和上面單個路由同樣,參考 Laravel 的 Route 文檔吧。
你還能夠直接設置到中間件組,這樣,只容許某寫中間件組的 URI 容許跨域,例如 Laravel 默認的兩個路由中間件組有 web
和 api
兩個組,首先 web
組確定不是咱們想要跨域的,而 api
咱們多是徹底的先後端分離開發,前端程序不在當前 API 服務器的域上,產生了跨域,咱們能夠直接給 api
組設置容許 api
組跨域:
protected $middlewareGroups = [ /// ... 'web' => [ // ... ], 'api' => [ \Medz\Cors\Laravel\Middleware\ShouldGroup::class, // ... ], ];
固然,你給 Medz\Cors\Laravel\Middleware\ShouldGroup::class
設置了路由中間價別名的話(例如:chors-should
),你能夠:
protected $middlewareGroups = [ /// ... 'web' => [ // ... ], 'api' => [ 'cors-should', // ... ], ];
注意,路由組模式是會和「路由匹配模式」混合使用的
在「配置中」講到了 ENV
常量 CORS_LARAVEL_ALLOW_ROUTE_PERFIX
或者配置文件中的 laravel.allow-route-perfix
是的,這就是路由匹配模式,默認是 *
即匹配全部。
路由匹配模式的匹配方法是使用 Laravel 中 Illumante\Http\Request::is
方法,文檔請參考 Laravel 請求文檔,因此設置的規則和 Laravel 請求問中 is
方法要求一致。例如,咱們但願 api
前綴的路由纔開啓跨域:那麼設置爲:
api/*
便可,⚠️注意,路由匹配模式就像在 「路由組模式」提到了,會和「路由組模式」進行一塊兒匹配。以 API 爲了,咱們使用「路由組模式」只容許 api
中間件組的路由容許跨域,同時咱們設置 api/v2/*
的「路由匹配模式」規則,那麼,容許跨於的只有 api/v2/*
的路由能夠,例如 api/v1/*
也是 api
中間件組的路由,雖然組模式匹配上了,可是「路由匹配模式」的規則沒有匹配上,因此 api/v1/*
的 路由是沒有跨域容許信息的。
其實 medz/cors
不僅是在 Laravel 項目中使用,你能夠用於任何 PHP 程序中,只是包只會內置幾個主流框架的預設支持代碼而已,你能夠用 Array
模式來讓全部的 PHP 程序都支持。
由於一些語法緣由,這個包只能用在 PHP >= 7.0
的版本之上,而且暫時不會進行語法妥協。
GitHub 地址:https://github.com/medz/cors
嗯,新輪子,求一波 ?Star 。