我需要使用HTTP重定向代码302还是307?

12
假设我有一个网页,用于显示当前月份的媒体发布信息。出于某些琐碎的原因,必须给这个页面添加一个查询字符串,以便生成该列表。因此,我需要将请求http://www.mysite.com/mediareleases.aspx 的客户端重定向到 http://www.mysite.com/mediareleases.aspx?prevDays=whateverDayOfTheMonthItIs。如果我想让Google索引不带查询参数的页面,那么我应该使用状态码302还是307执行重定向?这两种状态码都表示页面已经“临时”移动了,这正是我想要的,因为如果你明白我的意思,这个页面每天都会“移动”。

你需要执行一些操作才能从主页面跳转到此页面吗?例如,提交表单或其他什么吗? - kibibu
不,基本上所有的操作都将由服务器处理。如果有人进入一个没有查询字符串的页面,浏览器将被重定向到同一个页面,并包含查询字符串以提供正确的日期范围。 - Iain Fraser
3
无论你进行什么重定向,<link rel="canonical"> 标签在结果页面中都是一个不错的选择。它可以帮助优化搜索引擎对于该页面的理解和排名。 - TRiG
4个回答

18

Google的文档似乎表明302和307都被等同对待,并且"Googlebot将继续爬取和索引原始位置"。

但面对模糊不清的情况,您最好深入研究RFC并尝试做正确的事情,带着天真的希望,爬虫也会这样做。在这种情况下,RFC 2616 § 10.3 对每个响应代码都包含几乎相同的定义,只有一点例外:

302:由于重定向可能会偶尔更改,客户端应该继续使用 Request-URI 以供未来请求。

307:由于重定向可能会偶尔更改,客户端应该继续使用 Request-URI 以供未来请求。

这对我来说不是很重要的区别。我的理解是,302指示客户端网站管理员不值得信任,而307明确告诉网站管理员客户端不会信任他们,因此可以自由更改重定向。

我认为更有说服力的是302定义中的注释:

注意:RFC 1945和RFC 2068指定客户端不允许更改重定向请求的方法。但是,大多数现有用户代理实现将302视为303响应,并在Location字段值上执行GET,而不考虑原始请求方法。状态码303和307已添加到希望使客户端清楚了解需要哪种反应的服务器。

这对我来说表明302和307在很大程度上是等效的,但HTTP/1.0客户端第一次未能正确实现302。


11
简短回答:两个都不是。在大多数情况下,您真正想使用的代码是303。
长话短说,首先我们需要一些背景知识。当获取重定向代码时,客户端可以(A)使用相同的请求类型加载新位置或(B)覆盖它并使用GET。
HTTP 1.0规范没有303和307,只有302,它强制执行(A)行为。但实际上发现(A)导致了提交表单的问题。
假设您有一个联系表格,访问者填写并提交它,客户端得到一个302,显示“谢谢,我们会尽快回复您”的页面。该表单使用POST发送,因此感谢页面也使用POST加载。现在假设访问者点击重新加载;请求以与第一次获得它的方式相同重新发送,即使用POST(并且是相同的负载)。最终结果:表单被提交了两次(每次重新加载都会再提交一次)。即使客户端在这样做之前询问用户确认,对大多数情况来说仍然很烦人。
这个问题变得如此普遍,以至于客户端生产者决定覆盖规范并为重定向位置发出GET请求。基本上,这是HTTP 1.0规范中的一个疏漏。客户端最需要的是303(上述的行为B),但他们只得到了302(行为A)。
如果HTTP 1.0同时提供了302和303,那就不会有问题。但它没有,所以结果是一个没有人正确使用的302。因此,HTTP 1.1添加了303(非常需要),但还决定添加307,它在技术上与302相同,但是是一种“显式302”;它说“是的,我知道302周围的问题,我知道我在做什么,请给我(A)行为”。
现在回到我们的问题。您现在看到了为什么在大多数情况下您想要使用303。

需要保留请求类型的情况非常罕见。如果你确实遇到这种情况,答案很简单:使用302。如果客户端使用的是HTTP 1.0,则无法理解307;如果客户端使用的是HTTP 1.1,则无需保留旧版客户端的叛逆行为,即它正确实现了302,因此应该使用它!


4
当HTTP 1.0客户端看到303状态码时会发生什么? - Pacerier
2
这个答案提供了302和303/307开发的一些背景信息,但分析和建议是相当错误的。保留请求类型并不是“非常罕见”的,它是常见的;规范旨在解决移动资源的问题,这也是OP所问的问题。试图通过发出303来更改URL可能会破坏网站。对oldlocation/myform的POST将变为对newlocation/myform的GET,这不是期望的行为。在进行表单提交重定向的特殊情况下,可以使用303,但不应将其用于移动资源。 - Kevin Christopher Henry
如果你应该始终使用302来保留请求类型,那么为什么还要添加307呢? - nhooyr

7

五年过去了......需要注意的是,2014年6月RFC-7231#6.4.7更新了307的行为,并且现在与302有显著不同之处,即如果它执行自动重定向到该URI,则方法不得更改:

307(临时重定向)状态代码表示目标资源暂时驻留在不同的URI下,如果它执行自动重定向到该URI,则用户代理不得更改请求方法。

对于原始问题可能不是问题,但对于其他只是寻找区别的人可能会有所帮助。


0

我理解你的痛苦。至于解决方案,很难说搜索引擎会怎么做。似乎每个搜索引擎都有自己处理重定向的方式。这个链接建议使用302将重定向页面的内容索引,但仍使用主页面链接,但不清楚307会怎么做。

另一种方法是考虑使用javascript重定向和<noscript>标签来解释正在发生的事情。这也会影响非javascript浏览器,并且您必须小心谨慎地进行操作,以避免Google的诡秘网站检测程序,但我认为只要您的noscript包含与新URL匹配的超链接,就应该没问题。

无论如何,如果可能的话,我仍然会追求纯服务器端请求。 哎呀,如果您预期的流量很小,您甚至可以将主页视为代理(在没有查询字符串的情况下)。 使用后台线程向带有查询字符串的自身发出请求并输出结果。

编辑刚刚看到您正在使用.NET。也许考虑来自SO的此答案:C# Can i modify Request.Form's variables?


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