仅在首选特定媒体类型时重定向 HTTP 请求

Redirect an HTTP request only if specific media type is preferred

在 HTTP 中,如果客户端在发送特定媒体类型首选项时请求资源(通过主动内容协商也称为 Accept header)并且此资源的表示在首选媒体类型中不可用.

现在是否可以接受将客户端重定向到可以提供该表示的不同 URI(因此语义上可能是不同的资源)?

同时,如果客户端请求了一种媒体类型,其中有可用于资源的表示,则将交付该表示。

显然,这仅在请求的媒体类型本身带有某种语义且不是通用格式的情况下才有意义。

我怀疑这不是预期的行为,因为语义应该由请求的资源定义。但我想知道是否有定义或标准明确允许或禁止这种服务器行为。

示例:

资源在语义上表示文章列表,并且它的表示形式可用作通用 text/html。现在客户端请求它时偏好 application/json-home。服务器可以知道这种媒体类型只对语义 home 资源有意义,并将客户端重定向到同一站点(home 资源所在的位置)的 / 路径。另一方面,如果没有给出首选项媒体类型,或者客户端要求 text/html 表示,这可以作为响应。

对您的问题的简短回答是肯定的,根据客户端发送的 Accept header 将客户端重定向到不同的 URI 是可以接受的,并且 HTTP 规范明确设想了这种情况。

如何以 spec-compliant 方式执行此操作,包括您 return 的状态代码,取决于您的资源的性质和您所服务的客户。这里有几个选项:

406(不可接受)

在这种情况下,

RFC 7231 似乎更喜欢 406 (Not Acceptable) 状态代码。来自 section 5.3.2:

If the [Accept] header field is
present in a request and none of the available representations for
the response have a media type that is listed as acceptable, the
origin server can either honor the header field by sending a 406 (Not
Acceptable) response or disregard the header field by treating the
response as if it is not subject to content negotiation.

即使响应是 4xx 客户端错误,section 6.5.6 明确允许自动选择服务器可接受的其他资源 and/or 媒体类型:

The server SHOULD generate a payload containing a list of available
representation characteristics and corresponding resource identifiers
from which the user or user agent can choose the one most
appropriate.  A user agent MAY automatically select the most
appropriate choice from that list.  However, this specification does
not define any standard for such automatic selection, as described in
Section 6.4.1.

在您的示例场景中,您响应的有效负载可能包含指向“home”资源的 link,并表明可以使用 application/json-home 媒体类型对其进行检索。 (它还可以包含指向同一资源的 link,表示可以使用一种或多种其他媒体类型对其进行检索。)

虽然 406 不是重定向(在 3xx 意义上),但规范明确允许客户端自动遵循 406 响应中的 link(s)。但是,Web 浏览器不会自动执行此操作。

303(见其他)

您还可以使用 300 (Multiple Choices)303 (See Other),它们都明确指定了 Location header,用户代理可以使用它来检索备用 URI .如果您确实需要 自动 重定向,并且您的客户端是普通的网络浏览器(Chrome、Firefox 等),那么最实际的响应可能是让您的服务器 return一个303 (See Other)。来自 RFC 7231, section 6.4.4:

The 303 (See Other) status code indicates that the server is
redirecting the user agent to a different resource, as indicated by a
URI in the Location header field, which is intended to provide an
indirect response to the original request.  A user agent can perform
a retrieval request targeting that URI (a GET or HEAD request if
using HTTP), which might also be redirected, and present the eventual
result as an answer to the original request.  Note that the new URI
in the Location header field is not considered equivalent to the
effective request URI.
[...]
A 303 response to a GET request indicates that the origin server does
not have a representation of the target resource that can be
transferred by the server over HTTP.  However, the Location field
value refers to a resource that is descriptive of the target
resource, such that making a retrieval request on that other resource
might result in a representation that is useful to recipients without
implying that it represents the original target resource.

对于 303,服务器明确表示,“我将您重定向到的这个 URI 不等同于您想要的 URI,但我认为它可能很接近。”这似乎与您的要求非常接近,只要您在 Location header 中提供首选 URI,浏览器(和许多其他 HTTP 客户端)就会自动遵循重定向。

300(多选)

300 (Multiple Choices)也是一个选项。它更多地设计用于将用户重定向到资源的多个替代 URI 之一,作为反应性内容协商的一部分(请参阅 section 3.4.2)。

RFC 7231, section 6.4.1:

The 300 (Multiple Choices) status code indicates that the target
resource has more than one representation, each with its own more
specific identifier, and information about the alternatives is being
provided so that the user (or user agent) can select a preferred
representation by redirecting its request to one or more of those
identifiers.  In other words, the server desires that the user agent
engage in reactive negotiation to select the most appropriate
representation(s) for its needs (Section 3.4).

If the server has a preferred choice, the server SHOULD generate a
Location header field containing a preferred choice's URI reference.
The user agent MAY use the Location field value for automatic
redirection.

尽管根据客户端支持的媒体类型有选择地 return 300 似乎没有违反规范,但 406 会更直观。

Vary: accept header

无论您 return 的状态代码是什么,您都应该在该 URI 的所有响应中包含 Vary: accept header,包括发送时发送的 200(或任何其他)响应客户端使用此资源可接受的媒体类型发出请求。 Vary header 明确设计用于反应式内容协商,它将防止(合规的)中介或客户端对具有不同 Accept [= 的请求提供“错误”响应70=]。有关详细信息,请参阅 section 7.1.4