swoft2.0.x官方文档介绍的跨域处理demo以下:
这中方式在正常请求下看似没有问题,但若是$handler->handle($request)
步骤发生了异常,好比Validator拦截到请求参数不合法,抛出了ValidatorException,那么后续添加请求头的操做就没法获得执行.php
那么,可不能够在执行handle方法前先经过Context::get()->getResponse()
得到Response对象,而后先对Response对象进行header设置呢?
答案是:NO,由于HttpContext没有提供response属性的setter,想要输出修改后的Response只能在框架提供的各个环节中return给调用者.nginx
再看swoft源码Swoft\Http\Server\HttpDispatcher
:
不难发现:跨域
1.`$requestHandler->handle($request)`这一步若是发生异常,那么咱们天然也得不到对应的`$response`. 2.发生异常后,系统会经过`$errDispatcher = Swoft::getSingleton(HttpErrorDispatcher::class)`获得错误处理的调度者,最后经过错误处理调度者返回一个Response
结合源码,最终的解决思路有4个:服务器
1.在每一个中间件执行$handler->handle($request)步骤时加上try/catch,捕获执行中的异常,而后获取Response,设置好跨域后,正常return. 2.利用swoft的HttpErrorDispatcher,在对应的异常处理类里面设置跨域的请求头(关于如何设置异常处理,请参见swoft官网文档). 3.跳出在php中设置跨域请求header的思路,在好比nginx等代理服务器设置header. 4.修改源码,在以下时机加入header设置,此处的$this->configResponse($response)方法为自定义的header设置方法:
以上4中方法:框架
前2中方法须要在注册的每个中间件或者错误处理回调类里面添加header设置,比较繁琐.最可能是加个Common类来统一处理,但其它类仍然须要继承这个Common类. 第3种方式无需动php任何代码,推荐生产环境使用.可是在本地开发时须要Nginx等服务做为代理,略显繁琐. 第4种方式,好处是只需动一处代码,就能做用全局.坏处也很明显:动的那一处是框架提供的源码.建议测试环境使用.
总结:测试
测试环境第4种,生产环境第3种.