为什么Mage_Persistent打破/ api / wsdl?soap

时间:2012-04-05 18:34:23

标签: api session magento

我在Magento CE 1.6.1.0

中收到以下错误

Warning: session_start() [<a href='function.session-start'>function.session-start</a>]: Cannot send session cookie - headers already sent by (output started at /home/dev/env/var/www/user/dev/wdcastaging/lib/Zend/Controller/Response/Abstract.php:586) in /home/dev/env/var/www/user/dev/wdcastaging/app/code/core/Mage/Core/Model/Session/Abstract/Varien.php on line 119

访问/api/soap/?wsdl

显然,在输出WSDL文件的全部内容后,正在尝试session_start(),导致错误。

为什么magento在输出所有基准后尝试启动会话?我很高兴你问。因此,看起来controller_front_send_response_after被Mage_Persistent迷住了,以便调用synchronizePersistentInfo(),而session_start()最终会触发persistent/options/enable

有趣的是,这不是始终正在发生,最初WSDL加载对我来说很好,最初我绞尽脑汁试着看看我们的安装到了什么样的定制。引起这种情况,但我所做的追踪似乎表明这完全发生在核心内部。

我们也经历了与Mage_Persistent的一点点(完全不相关)的陌生感,这让我更愿意在这一点上举起手来这样做。

我已经对SO进行了一些搜索,并且发现了一些与整个“已经发送的标题”相关的问题,但不是这个具体情况。

有什么想法吗?

哦,我现有的临时解决方法就是通过{{1}}配置数据禁用Mage_Persistent。我还做了一些挖掘,是否有可能观察一个事件,以便为WSDL控制器禁用此模块 (因为这似乎是唯一有问题的模块),但看起来该模块完全依赖于此配置标志来确定它的启用状态。

更新:已报告错误:http://www.magentocommerce.com/bug-tracking/issue?issue=13370

2 个答案:

答案 0 :(得分:2)

我报告这是Magento团队的一个错误。 Magento API控制器都通过标准Magento动作控制器对象进行路由,所有这些对象都继承自Mage_Api_Controller_Action类。这个类有一个preDispatch方法

class Mage_Api_Controller_Action extends Mage_Core_Controller_Front_Action
{
    public function preDispatch()
    {
        $this->getLayout()->setArea('adminhtml');
        Mage::app()->setCurrentStore('admin');
        $this->setFlag('', self::FLAG_NO_START_SESSION, 1); // Do not start standart session
        parent::preDispatch();
        return $this;
    }
    //...
}

其中包括设置一个标志以确保API方法无法启动正常的会话处理。

$this->setFlag('', self::FLAG_NO_START_SESSION, 1);

因此,听起来synchronizePersistentInf中的代码假定存在会话对象,并且在使用它时会话被初始化,导致您看到的错误。通常,这不是问题,因为此时每个其他控制器都已初始化会话,但API控制器明确地将其关闭。

就修复问题而言,您最好的选择(可能是您从Magento支持获得的快速答案)将禁用默认配置设置的持久购物车功能,但随后为需要它的特定商店启用它。这将让购物车

自己想出一个解决方案将是一个未知的领域,我想不出一种方法可以做到这一点,不是非常hacky /不稳定。最直接的方法是在synchronizePersistentInf上调用它的父方法的类重写,除非您检测到这是一个API请求。

答案 1 :(得分:0)

这个答案并不是要取代现有的答案。但是我想在这里删除一些代码以防有人遇到这个问题,并且注释并不真正允许代码格式化。

我使用简单的local代码池覆盖Mage_Persistent_Model_Observer_Session来退出/api/*

内的任何网址路由的功能

不要期望这个修复需要非常长寿或升级友好,b / c我希望他们在下一个版本中解决这个问题。

public function synchronizePersistentInfo(Varien_Event_Observer $observer)
{
    ...

    if ($request->getRouteName() == 'api') {
        return;
    }

    ...
}