当前位置: 首页 > 后端技术 > PHP

Swoft中间件跨域问题

时间:2023-03-30 00:40:21 PHP

swoft2.0.x官方文档中介绍的跨域处理demo如下:这种方法在正常请求下貌似没问题,但是如果在$handler->handle($request)这一步出现异常,对于例如,如果验证器拦截请求参数。合法的,如果抛出ValidatorException,则后续添加请求头的操作将无法执行。那么,能不能在执行handle方法之前先通过Context::get()->getResponse()获取到Response对象,然后再对Response对象进行header设置呢?答案是:不,因为HttpContext没有为response属性提供setter。如果要输出修改后的Response,只能在框架提供的各个链接中返回给调用者。查看swoft源码Swoft\Http\Server\HttpDispatcher:不难发现:1.如果在`$requestHandler->handle($request)`这一步出现异常,那我们自然是得不到对应的`$响应`。2、异常发生后,系统会通过`$errDispatcher=Swoft::getSingleton(HttpErrorDispatcher::class)`获取dispatcher进行错误处理,最后通过错误处理dispatcher返回一个结合源代码的Response。最终解决方案有四种:1、在每个中间件中执行$handler,在->handle($request)步骤中加入try/catch,捕获执行过程中的异常,然后获取Response,设置跨域后正常返回。2.使用swoft的HttpErrorDispatcher在对应的异常处理类Domain请求头中设置cross(如何设置异常处理请参考swoft官网文档)。3.跳出在php中设置跨域请求头的思路,在nginx等代理服务器中设置headers。4.修改源码,在如下定时添加Header设置,这里的$this->configResponse($response)方法是自定义header设置方法:以上4种方法:前2种方法需要在中添加header设置分别注册中间件或错误处理回调类,比较繁琐。顶多增加一个Common类进行统一处理,但是其他类还是需要继承这个Common类。第3部分第一种方法不需要在php中动任何代码,推荐在生产环境中使用。但是需要Nginx等服务作为本地开发的代理,有点繁琐。第四种方法的好处是只需要移动一个代码就可以影响全局。缺点也很明显:动的是框架提供的源码。建议在测试环境中使用。总结:第四类测试环境和第三类生产环境。