/** * Handle OPTIONS calls and add Access-Control headers. * * @param FilterResponseEvent $event Filter response event */ public function onKernelResponse(FilterResponseEvent $event) { // Don't do anything if it's not the master request. if (!$event->isMasterRequest()) { return; } $request = $event->getRequest(); if ($request->getRealMethod() == Request::METHOD_OPTIONS) { $response = new Response(); $response->headers->set('Access-Control-Allow-Origin','*'); $response->headers->set('Access-Control-Allow-Headers','Origin,X-Requested-With,X-Auth-Token,X-App-Version,Content-Type,Accept,Authorization'); $response->headers->set('Access-Control-Allow-Methods','POST,GET,PUT'); $event->setResponse($response); } else { $response = $event->getResponse(); $response->headers->set('Access-Control-Allow-Origin','*'); $response->headers->set('Access-Control-Allow-Credentials',true); $response->headers->set('Access-Control-Allow-Headers',PUT'); } }
这只是在浏览器中开发Ionic应用程序的一个解决方案,并处理来自应用程序的OPTIONS调用,而不会在那里出现错误.但这只是一个例子,我与使用ResponseListener的其他Symfony应用程序有同样的问题.
如果在prod环境中或在dev环境中运行它(如果没有发生错误),上述示例可以很好地工作.但是一旦我收到一个PHP错误,就会产生以下结果:
Internal Server Error The server encountered an internal error or misconfiguration and was unable to complete your request. Please contact the server administrator,you@example.com and inform them of the time the error occurred,and anything you might have done that may have caused the error. More information about this error may be available in the server error log. Additionally,a 500 Internal Server Error error was encountered while trying to use an ErrorDocument to handle the request.
如果我查看apache_error.log它说:
FastCGI: comm with server "/Applications/MAMP/fcgi-bin/PHP7.0.13.fcgi" aborted: error parsing headers: duplicate header 'Content-Type',referer: http://app.domain/app_dev.PHP/my-route
这似乎只发生在PHP错误.如果我例如抛出一个NotFoundHttpException
throw new NotFoundHttpException("Test exception");
如果我做类似的事情
new ClassDoesNotExist();
它会导致内部服务器错误.
我知道这是由于ResponseListener,因为在我出现退出时,会出现Symfony错误页面;顶部的功能就像这样:
public function onKernelResponse(FilterResponseEvent $event) { exit; // Don't do anything if it's not the master request. if (!$event->isMasterRequest()) { return; } ...
ResponseListener有什么问题吗?有没有一些配置可以在apache上完成,这个错误不会被抛出?
编辑:
这是MAMP PRO vhost配置:
<VirtualHost *:80> ServerName project.localhost DocumentRoot "/Users/MyUser/Projekte/MyProject/web" <IfModule xsendfile_module> XSendFilePath "/Users/MyUser/Projekte/MyProject/web" </IfModule> <Directory "/Users/MyUser/Projekte/MyProject/web"> Options Includes FollowSymLinks ExecCGI AllowOverride All <IfModule authz_host_module> Order allow,deny Allow from all </IfModule> </Directory> WSGIDaemonProcess project.localhost processes=2 threads=15 WSGIProcessGroup project.localhost WSGIScriptAlias /project.localhostWsgiApp "/Users/MyUser/Projekte/MyProject/web/wsgiapp.py" AddHandler PHP-fastcgi .PHP Action PHP-fastcgi "/fcgi-bin/PHP7.0.13.fcgi"
编辑2:
根据@mickadoo的建议,另一个监听器可能会添加重复的头Content-Type.如果我停止传播,我得到我想要的Symfony错误消息.但是我的听众也是第一个被调用的,所以这将阻止任何其他监听器被触发.执行debug:event-dispatcher会导致以下结果:
"kernel.response" event ----------------------- ------- -------------------------------------------------------------------------------------------- ---------- Order Callable Priority ------- -------------------------------------------------------------------------------------------- ---------- #1 MyCompany\Bundle\AppBundle\EventListener\ResponseListener::onKernelResponse() 0 #2 Sonata\BlockBundle\Cache\HttpCacheHandler::onKernelResponse() 0 #3 Symfony\Component\HttpKernel\EventListener\ResponseListener::onKernelResponse() 0 #4 Symfony\Bundle\FrameworkBundle\DataCollector\RequestDataCollector::onKernelResponse() 0 #5 Symfony\Component\Security\Http\RememberMe\ResponseListener::onKernelResponse() 0 #6 Sensio\Bundle\FrameworkExtraBundle\EventListener\HttpCacheListener::onKernelResponse() 0 #7 Symfony\Component\HttpKernel\EventListener\ProfilerListener::onKernelResponse() -100 #8 Symfony\Bundle\WebProfilerBundle\EventListener\WebDebugToolbarListener::onKernelResponse() -128 #9 Symfony\Component\HttpKernel\EventListener\SaveSessionListener::onKernelResponse() -1000 #10 Symfony\Component\HttpKernel\EventListener\StreamedResponseListener::onKernelResponse() -1024 ------- -------------------------------------------------------------------------------------------- --------
当我添加另一个响应侦听器,优先级为-2048,使他成为最后一个触发,并使用以下方法:
/** * @param FilterResponseEvent $event Filter response event */ public function onKernelResponse(FilterResponseEvent $event) { // Don't do anything if it's not the master request. if (!$event->isMasterRequest()) { return; } $response = $event->getResponse(); echo "<pre>"; print_r($response->headers->all()); exit; }
它返回:
Array ( [cache-control] => Array ( [0] => no-cache,private ) [access-control-allow-origin] => Array ( [0] => * ) [access-control-allow-credentials] => Array ( [0] => 1 ) [access-control-allow-headers] => Array ( [0] => Origin,Authorization ) [access-control-allow-methods] => Array ( [0] => POST,PUT ) [content-type] => Array ( [0] => text/html; charset=UTF-8 ) [x-debug-token] => Array ( [0] => 2f5dbb ) [x-debug-token-link] => Array ( [0] => http://app.project.localhost/app_dev.PHP/_profiler/2f5dbb ) )
但是还没有其他的Content-Type.有任何想法吗?
编辑3:
另一个奇怪的事情是:
如果我使用我的方法结尾处的$event-> stopPropagation(),并添加优先级为0的侦听器,所有的工作(意味着显示Symfony错误页面),如果我将其设置为优先级为-2048我得到了Apache错误信息.但是即使我输出的所有头都没有重复的头.我真的不知道这是怎么可能的.只需一个请求就可以将多个相同的标题返回给apache,而在结尾的所有标题在输出中是唯一的?