Swoft中间件跨域问题

swoft2.0.x官方文档介绍的跨域处理demo以下:
image
这中方式在正常请求下看似没有问题,但若是
$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:
image
不难发现:跨域

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设置方法:

image

以上4中方法:框架

前2中方法须要在注册的每个中间件或者错误处理回调类里面添加header设置,比较繁琐.最可能是加个Common类来统一处理,但其它类仍然须要继承这个Common类.
第3种方式无需动php任何代码,推荐生产环境使用.可是在本地开发时须要Nginx等服务做为代理,略显繁琐.
第4种方式,好处是只需动一处代码,就能做用全局.坏处也很明显:动的那一处是框架提供的源码.建议测试环境使用.

总结:测试

测试环境第4种,生产环境第3种.
相关文章
相关标签/搜索