【问题标题】:Redirect an HTTP request only if specific media type is preferred仅在首选特定媒体类型时才重定向 HTTP 请求
【发布时间】:2017-04-17 07:57:54
【问题描述】:

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

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

同时,如果客户端请求了一种媒体类型,其中存在可用于资源的表示,则该表示将被传递。

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

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

例子:

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

【问题讨论】:

    标签: rest http redirect representation media-type


    【解决方案1】:

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

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

    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 也明确允许自动选择服务器可接受的其他资源和/或媒体类型:

    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”资源的链接,并指示可以使用 application/json-home 媒体类型检索它。 (它还可以包含指向同一资源的链接,表明可以使用一种或多种其他媒体类型来检索它。)

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

    303(见其他)

    您还可以使用300 (Multiple Choices)303 (See Other),两者都明确指定用户代理可用于检索备用URI 的Location 标头。如果您确实需要自动重定向,并且您的客户端是一个普通的网络浏览器(Chrome、Firefox 等),那么最实际的响应可能是让您的服务器返回一个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 标头中提供首选 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.
    

    虽然根据客户端支持的媒体类型有选择地返回 300 似乎并不违反规范,但 406 会更直观。

    Vary: accept标头

    无论您返回什么状态代码,您都应该在此 URI 的所有响应中包含 Vary: accept 标头,包括客户端使用此资源的可接受媒体类型发出请求时发送的 200(或任何其他)响应. Vary 标头明确设计用于响应式内容协商,它将防止(兼容的)中介或客户端对具有不同 Accept 标头的请求提供“错误”响应。详情请见section 7.1.4

    【讨论】:

    • 你的反应很棒。非常感谢。
    • 我是否正确理解 300 (Multiple Choices) 的描述假设同一资源的不同表示可以通过不同的 URI 选择?因为否则 Location 标头部分将与请求的 URI 相同,对吧?
    • 从技术上讲,300 仅表示资源有不同的“表示形式”,而不是有不同的 URI。这些“表示”可能在不同的 URI 上可用,也可能不可用。例如,300 响应可以包含指向相同 URI 的链接,但会向客户端指示应该/可以使用不同的媒体类型。 Location 标头仅表示服务器在说“我'更喜欢'您使用此 URI,如果您愿意,您可以再次使用此 URI 尝试您的请求,而无需询问用户。”
    猜你喜欢
    • 1970-01-01
    • 2010-10-10
    • 2014-12-28
    • 1970-01-01
    • 2018-05-28
    • 1970-01-01
    • 2021-10-01
    • 2019-12-16
    • 2018-12-29
    相关资源
    最近更新 更多