pi-engine / pi

Multi-tenant application development engine for cloud ready SaaS platform.
http://www.piengine.org
202 stars 115 forks source link

Different results ocurr when accept of request header is different #1344

Open linzongshu opened 9 years ago

linzongshu commented 9 years ago

This issue let us to discuss a question: is a page type (common/json/feed) decides by page itself or request.

These days we came accross with a problem: sometimes our pages showed something unexcepted, and after debug I found spider (do not know is good or bad) didn't send the correct accept parameter in its header, therefore the Pi generated unexcept result and wrote into cache.

For example, our homepage is a common page (neither json action or feed page), the following requests will cause different error results:

I used curl method to test, like this:

$headers = array(
    "Accept: application/atom+xml",
);
$ch = curl_init('...');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0");
$result = curl_exec($ch);

So whether do we need to throw exception if the sended type is mismatch with our page, or else someone may use this bug to make our page always look bad?

linzongshu commented 9 years ago

A simple way to fix this issue is to append request type parameter to the URL which uses for identifying cache file. Therefore different request type will generate different cache page, and content reviewed via browser will not influence by other request type. If the user want to get correct result via curl(), he must set the correct type.

The codes Added by Zongshu Lin at the bottom example will resolve this problem:

Pi\Application\Bootstrap\Resource\RenderCache::checkPage()

public function checkPage(MvcEvent $e)
{
    ...
    $renderCache    = $this->renderCache('page');
    # Added by Zongshu Lin
    $listeners      = Pi::engine()->application()->getEventManager()->getListeners(MvcEvent::EVENT_BOOTSTRAP);
    foreach ($listeners as $listener) {
        $listenerCallback = $listener->getCallback();
        if ('Pi\Mvc\View\Http\ViewStrategyListener' == get_class($listenerCallback[0])) {
            break;
        }
    }
    $cacheKey       = md5(sprintf('%s_%s', $e->getRequest()->getRequestUri(), $listenerCallback[0]->getType()));
    # End added
    //$cacheKey       = md5($e->getRequest()->getRequestUri());
    $namespace      = $e->getRouteMatch()->getParam('module');
    $renderCache->meta('key', $cacheKey)
                ->meta('namespace', $namespace)
                ->meta('ttl', $cacheMeta['ttl']);
     ...
}