问题
I've been moving merrily along with my site until this week when we've started to see some errors crop up that have turned out to be related to my misunderstanding the way Cake's RequestHandler works, but I have yet to find a good workaround.
I am using one method to lookup and return content in various formats, so that they all live on the same URL (maybe this is my error and I need to split them up?). So, in my controller I have:
if ($this->RequestHandler->ext == 'rss') {
to pick up on RSS feeds. I also tried using isRss()
but changed it, figuring that was the source of my problem. My problem is this:
When hitting this url (let's call it /blog
) from a browser, I will normally get an HTML response. If I hit it at /blog.rss
I get the RSS response. Great so far. But if I hit the /blog
address with my header set as Accepts: application/rss+xml;
it will return RSS regardless of the fact that there is no literal .rss extension. These pages are cached, so now my browser users end up seeing a cached version of the RSS feed when requesting the /blog
address instead of the HTML version.
I checked into RequestHandler and it turns out that it uses _setExtension() to set the ext
value based on the Accepts header, even if no 'real' extension exists. There seems to be no override for this, so it looks like I'm either forced to parse the URL myself to see if there really is an extension or to separate out these URLs altogether and not allow rss/json from the /blog
address space (eg, /blog/feed
, /blog/json
).
Is there a better/easier way to get around this or something that I'm missing with the way this is set up? I had figured ext
was a reliable indication of there being an actual extension but maybe there is another way to look for it?
回答1:
You're partially right. The _setExtension
function is called if there's no extension explicitely set, so a url like /blog
will be requesting that function, but if you do /blog.rss
, _setExtension
won't be called.
Anyway, that was just to make that point clear. Moving on.
Reading the _setExtension() docs
If html is one of the preferred types, no content type will be set, this is to avoid issues with browsers that prefer html and several other content types.
So, what I understand here is: if you pass html
to your Router::parseExtensions
, then the content type won't be set according to the accepted headers. Checking out the code (line 149) for your version of cake, there´s an if
that skips the content type override of the extension if you have html
or xhtml
on you preferred types.
if (count($similarTypes) === 1 && !in_array('xhtml', $preferredTypes) && !in_array('html', $preferredTypes)) {
$this->ext = array_shift($similarTypes);
}
Try and do
Router::parseExtensions('html', 'rss' /*and other extensions if you want*/)
and see if that solves your problem.
来源:https://stackoverflow.com/questions/16066365/cakephp-requesthandler-returns-rss-json-instead-of-html