「新輪子」PHP CORS (Cross-origin resource sharing),解決 PHP 項目程序設置跨域需求。

clipboard.png

是的,可能瞭解 Laravel 的都知道,在 Laravel 中簡單的設置跨域,固然是選擇 barryvdh/laravel-cors 這個包。php

原由

是的,我確實是在重複造輪子,barryvdh/laravel-cors 包實現很優秀了,可是它也有不少問題。而個人新輪子 medz/cors 也並非專門解決它的問題的,而是順便解決而已。medz/cors 包的靈感來自公司項目,公司的項目使用 Laravel 框架進行開發,前端使用徹底分離的方式。因此須要設置跨域,而傳統 nginx 設置跨域雖然可信,可是程序設置跨域優勢不言而喻(能夠設置多個容許跨域域名等,動態處理信息)。前端

概述

medz/cors 這個包,支持在全部 PHP 的項目中使用。你只須要一些簡單的配置便可。而這裏主要先講在 Laravel 中的應用,由於目前內置支持暫時對 Laravel 作了很好的專屬處理。nginx

打算友好支持以下laravel

  • [x] PHP Native coding.
  • [x] Laravel
  • [x] PSR-7
  • [ ] Symfony
  • [ ] Yii2
  • [ ] Slim Framework

安裝

感謝 Composer 爲社區帶來的改變,如今咱們都喜歡它,因此你只須要在你的項目中使用:git

composer require medz/cors

好了,你已經安裝好了。若是你是 Laravel,那麼,如今你已經爲你的程序加上了跨域github

發佈配置文件

運行:web

php artisan vendor:publish --provider="Medz\Cors\Laravel\Providers\LaravelServiceProvider" --force

有興趣看配置的能夠看一下 config/cors.php 的配置。可是下面會專門講配置的。shell

配置

爲了方便一些配置,個別 boolintstring 類型的配置可使用 .env 進行環境變量設置:後端

Key 描述
CORS_ALLOW_CREDENTIAILS bool, 設置 Access-Control-Allow-Credentialstrue 仍是 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.phpprotected $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.phpprotected $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 默認的兩個路由中間件組有 webapi 兩個組,首先 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 。
相關文章
相關標籤/搜索