使用浏览器后退按钮时忽略内容协商。

6

以下是情况:

我有一个Web应用程序,响应请求资源列表,例如:

/items

这最初是通过直接导航到该路径由Web浏览器请求的。浏览器使用其标准的“Accept”头,其中包括“text / html”,我的应用程序注意到这一点并返回项目列表的HTML内容。

在返回的HTML中有一些JavaScript(jQuery),它然后执行一个ajax请求来检索实际数据:

/items

这次,"Accept"头部被明确设置为"application/json"。我的应用程序注意到了这一点,并正确返回了JSON数据以响应请求,数据被插入到页面中,一切都很顺利。
问题来了:用户导航到另一个页面,稍后按下"返回"按钮。然后他们会被提示保存一个文件,结果是项目列表的JSON数据。
到目前为止,我已经确认在Google Chrome和Firefox 3.5中都会出现这种情况。
这里有两种可能的答案:
1. 如何解决问题?是否有一些神奇的Cache-Control头部组合或其他巫术可以使浏览器在这里做正确的事情? 2. 如果您认为我在这里做错了什么,请告诉我该如何做?我正在寻求正确性,但也试图不牺牲灵活性。
如果有帮助的话,该应用程序是一个JAX-RS Web应用程序,使用Restlet 2.0m4。如果需要,我可以提供示例请求/响应头部,但我相信该问题是完全可重现的。

这似乎是我在弄清楚(https://dev59.com/sFXTa4cB1Zd3GeqPyA87)之后将要面临的未来问题。好奇一下,您最终是坚持使用此解决方案还是为不同的URL放弃了它?单个RESTful URL的整洁性对于表示相同资源的不同表现形式确实是理想的。 - mckamey
3个回答

6

有没有一些神奇的Cache-Control头部组合,或其他的巫术可以使浏览器在这里做正确的事情?

如果你向不同的Accept头部提供不同的响应,你必须包含此头部:

Vary: Accept

在您的响应中,Vary头还应包含影响响应的任何其他请求头,因此例如,如果您进行gzip/deflate压缩,则必须包括Accept-Encoding。
不幸的是,IE处理许多Vary值时效果很差,完全破坏了缓存,这可能或可能不重要。

如果您认为我在这里做错了什么,请问我该怎么办?

我不认为在同一URL上为不同类型提供不同的内容的想法是非常错误的,但是您将自己置于比您实际需要更多的兼容性问题中。依靠通过JSON工作的头部实际上并不是一个好主意;您最好只有一个不同的URL,例如/items/json/items?format=json

在同一URL上提供不同的资源是错误的;提供相同资源的不同表示是HTTP应该做的事情。您想在XML、JSON、漂亮格式的可读HTML还是纯文本中查看它?它始终是相同的内容,只是以不同的格式呈现。不幸的是,某些浏览器会破坏这种机制,因此您必须像响应中所示使用某种技巧。如果您的服务同时提供"application/json"和"text/html",Internet Explorer将获取JSON版本,因为其有缺陷的Accept标头。 - Mark Lutton

1

我知道这个问题很旧了,但以防万一其他人也遇到了这个问题:

我在使用jQuery的Rails应用程序中遇到了同样的问题,通过使用此处提供的解决方案告诉浏览器不要缓存JSON响应来解决了这个问题:

jQuery $.getJSON works only once for each control. Doesn't reach the server again

这个问题似乎只出现在Chrome和Firefox中。Safari可以在没有明确告诉它不要缓存的情况下处理后退行为。


这个答案对我有用,如果你在jQuery.ajax()请求中将“cache”选项设置为“false”,你可以返回并按预期工作。 - Scott Harvey

0

虽然这是一个老问题,但对于任何看到这个问题的人来说,提问者使用 Accept header 是没有问题的。

这是 Chrome 中已确认的 bug。(之前也出现在 Firefox 中,但已经修复。)

http://code.google.com/p/chromium/issues/detail?id=94369


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接