CakePHP RequestHandler returns RSS/JSON instead of HTML

你。 提交于 2020-01-15 10:14:31

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!