<commit_before>---
layout: post
title: Lumen CORS
description: php, lumen, lumen cors
categories: [Web]
tags: [PHP, Lumen]
shortinfo: 使用Lumen框架如何解决跨域问题
---

### **使用Lumen框架如何解决跨域问题**
跨域问题想必是每个从事web相关开发的同学经常遇到的问题，特别是现在越来越多的应用采用的前后端分离的开发模式，所以解决跨域问题成了大家必不可少的一项技能。最近在使用Lumen框架开发时也遇到了这个问题。

进入主题之前我们先来个铺垫，首先我们来了解一下什么是跨域，以及一些解决方案 [这是铺垫](http://www.cnblogs.com/davidwang456/p/3977627.html)

有兴趣的同学可以仔细看看，其实W3C标准的解决方案是只要在服务器response的头部带上```Access-Control-Allow-Origin：DOMAIN```(允许跨域访问的域名，```*```代表所有)，不过需要一提的是该方案只支持IE8及以上，以及一些现代浏览器(Fire Fox,Chrome,etc.)。解决跨域比较常见的还有使用jsonp，但这不是本文重点，这里就不具体展开了。

好了，上面啰嗦了那么多，下面进入主题，那么在Lumen框架中，我们怎么解决跨域问题呢?
这边主要参考了[这里](https://gist.github.com/danharper/06d2386f0b826b669552)该大神的方案。
通过运用框架的Middleware和ServiceProvider来解决跨域问题。

新增中间件，```LUMEN/app/Http/Middleware/CorsMiddleware.php```

```
namespace App\Http\Middleware;

use Closure;

class CorsMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $response = $next($request);

        $response->header('Access-Control-Allow-Methods', 'HEAD, GET, POST, PUT, PATCH, DELETE');
        $response->header('Access-Control-Allow-Headers', $request->header('Access-Control-Request-Headers'));
        $response->header('Access-Control-Allow-Origin', '*');

        return $response;
    }
}
```

定义ServiceProvider，```LUMEN/app/Providers/CatchAllOptionsRequestsProvider.php```

```
namespace App\Providers;

use Illuminate\Support\ServiceProvider;

/**
 * If the incoming request is an OPTIONS request
 * we will register a handler for the requested route
 */
class CatchAllOptionsRequestsProvider extends ServiceProvider
{
	public function register()
	{
	    $request = app('request');

	    if ($request->isMethod('OPTIONS'))
	    {
	    	app()->options($request->path(), function() {
	    		return response('', 200)->header('Access-Control-Allow-Origin', '*');
	    	});
	    }
  	}
}
```

在```LUMEN/bootstrap/app.php```中加载对应的中间件，注册ServiceProvider。

```
$app->routeMiddleware([
    'cors' => App\Http\Middleware\CorsMiddleware::class,
]);
...
$app->register(App\Providers\CatchAllOptionsRequestsProvider::class);
```

看到这里，问题是已经解决了。但有一个问题我开始一直想不明白，CatchAllOptionsRequestsProvider存在的意义是什么，为什么需要单独处理OPTIONS的请求？不是一个中间件就可以全部处理了吗？
github上也有人跟我有同样的疑问
![lumen-bootstrap-app]({{ site.BASE_PATH }}/assets/images/lumen-cors-1.jpg){:data-action="zoom"}

直到前段时间再去看时才看到下面这位大神的评论<commit_msg>add code style<commit_after>---
layout: post
title: Lumen CORS
description: php, lumen, lumen cors
categories: [Web]
tags: [PHP, Lumen]
shortinfo: 使用Lumen框架如何解决跨域问题
---

### **使用Lumen框架如何解决跨域问题**
跨域问题想必是每个从事web相关开发的同学经常遇到的问题，特别是现在越来越多的应用采用的前后端分离的开发模式，所以解决跨域问题成了大家必不可少的一项技能。最近在使用Lumen框架开发时也遇到了这个问题。

进入主题之前我们先来个铺垫，首先我们来了解一下什么是跨域，以及一些解决方案 [这是铺垫](http://www.cnblogs.com/davidwang456/p/3977627.html)

有兴趣的同学可以仔细看看，其实W3C标准的解决方案是只要在服务器response的头部带上```Access-Control-Allow-Origin：DOMAIN```(允许跨域访问的域名，```*```代表所有)，不过需要一提的是该方案只支持IE8及以上，以及一些现代浏览器(Fire Fox,Chrome,etc.)。解决跨域比较常见的还有使用jsonp，但这不是本文重点，这里就不具体展开了。

好了，上面啰嗦了那么多，下面进入主题，那么在Lumen框架中，我们怎么解决跨域问题呢?
这边主要参考了[这里](https://gist.github.com/danharper/06d2386f0b826b669552)该大神的方案。
通过运用框架的Middleware和ServiceProvider来解决跨域问题。

新增中间件，```LUMEN/app/Http/Middleware/CorsMiddleware.php```

```php
namespace App\Http\Middleware;

use Closure;

class CorsMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $response = $next($request);

        $response->header('Access-Control-Allow-Methods', 'HEAD, GET, POST, PUT, PATCH, DELETE');
        $response->header('Access-Control-Allow-Headers', $request->header('Access-Control-Request-Headers'));
        $response->header('Access-Control-Allow-Origin', '*');

        return $response;
    }
}
```

定义ServiceProvider，```LUMEN/app/Providers/CatchAllOptionsRequestsProvider.php```

```php
namespace App\Providers;

use Illuminate\Support\ServiceProvider;

/**
 * If the incoming request is an OPTIONS request
 * we will register a handler for the requested route
 */
class CatchAllOptionsRequestsProvider extends ServiceProvider
{
	public function register()
	{
	    $request = app('request');

	    if ($request->isMethod('OPTIONS'))
	    {
	    	app()->options($request->path(), function() {
	    		return response('', 200)->header('Access-Control-Allow-Origin', '*');
	    	});
	    }
  	}
}
```

在```LUMEN/bootstrap/app.php```中加载对应的中间件，注册ServiceProvider。

```php
$app->routeMiddleware([
    'cors' => App\Http\Middleware\CorsMiddleware::class,
]);
...
$app->register(App\Providers\CatchAllOptionsRequestsProvider::class);
```

看到这里，问题是已经解决了。但有一个问题我开始一直想不明白，CatchAllOptionsRequestsProvider存在的意义是什么，为什么需要单独处理OPTIONS的请求？不是一个中间件就可以全部处理了吗？
github上也有人跟我有同样的疑问
![lumen-bootstrap-app]({{ site.BASE_PATH }}/assets/images/lumen-cors-1.jpg){:data-action="zoom"}

直到前段时间再去看时才看到下面这位大神的评论
{'fraction_non_alphanumeric': 0.15069033530571993, 'fraction_numerical': 0.0126232741617357, 'mean_word_length': 5.252774352651048, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 25, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1983332', 'n_tokens_mistral': 2394, 'n_tokens_neox': 2505, 'n_words': 232}