后退按钮(Chrome)在Play框架中获取Json而不是HTML

后退按钮(Chrome)在Play框架中获取Json而不是HTML,json,google-chrome,playframework-2.0,Json,Google Chrome,Playframework 2.0,各位, 我有一个web应用程序,其中我对同一资源的JSON和HTML表示重复使用了相同的路由,现在我们称它为/foo/details。此页面链接自,我们称之为/bar/details。(因此,请查看/bar/details,您可以看到->/foo/details的链接) 当我从第一页转到第二页时,一切正常。当我在Chrome中单击back按钮时,原始页面呈现为JSON而不是HTML。如果我在浏览器中点击refresh,我得到的是HTML表示,而不是JSON 下面是我用来检测JSON与HTML的代

各位, 我有一个web应用程序,其中我对同一资源的JSON和HTML表示重复使用了相同的路由,现在我们称它为/foo/details。此页面链接自,我们称之为/bar/details。(因此,请查看/bar/details,您可以看到->/foo/details的链接)

当我从第一页转到第二页时,一切正常。当我在Chrome中单击back按钮时,原始页面呈现为JSON而不是HTML。如果我在浏览器中点击refresh,我得到的是HTML表示,而不是JSON

下面是我用来检测JSON与HTML的代码:

res.result.map { group =>
  render {
    case Accepts.Html() => Ok(views.html.groups.details(group))
    case Accepts.Json() => Ok(Json.toJson(group))
  }
}.getOrElse(NotFound)
这是这个模式的标准实现,它在任何地方都有效,除了在某些情况下我在Chrome中使用后退按钮

是否有一些我没有清除的值,或者我的页面正在使用Ajax进行的某些操作会混淆播放,使其以Json呈现,或者可能Chrome正在缓存页面,但缓存了错误的头部

我可以通过使用两种不同的途径来解决这个问题,一种是Json,另一种是Html,但我不喜欢这样,因为我觉得我要放弃了


有人知道是什么原因导致这种行为只出现在后退按钮上吗?

这肯定是Chrome的浏览器缓存。它不区分使用“Accept”->“application/json”对/foo/bar发出的请求和使用常规HTML Accept头发出的请求。因此,我将加载HTML页面,该页面上的JavaScript将命中原始JSON数据的相同URL,然后下次我回击时,Chrome将提供缓存的JSON而不是缓存的HTML


因此,我不得不修改我的路由,让我的JSON/RESTAPI都通过不同的URL,这样Chrome(和Safari)就不会缓存JSON了。

Kevin你说得对。然而,还有另一个解决办法

如果在响应头中添加“Vary:Accept”,这将使chrome和其他有此问题的浏览器(例如firefoxv21)区分json和html缓存。注意:Vary:Accept-Encoding头不起作用,就我所测试的而言

如果使用nginx,可以设置:

proxy\u set\u头变化接受

但是,nginx存在一个问题,即有时不会发送vary-accept头,这与缓存有关。请参阅以处理此问题,您可以为nginx启用gzip_vary,但这将发送vary:Accept编码头。此标题无法解决此问题

我使用rails,并且使用了一个before_过滤器,在这里我修改了
response.headers[“Vary”]=“Accept”

我相信在其他服务器/框架上也有其他方法可以做到这一点


更多信息:

可能是一些浏览器缓存。您在不同的浏览器上试用过吗?这肯定是Chrome的浏览器缓存。不确定它是否有效,但您可以在JSON响应上设置一个标题,告诉浏览器不要缓存它。@estmatic如果您感兴趣,请参阅我的答案,如果您在响应中发送一个“Vary:Accept”标题,这将解决问题。这应该是公认的答案,对我来说绝对是个好办法。