RESTful API 在 URI 模板中使用 # 片段扩展 (RFC 6570)

RESTful API with # fragment expansion in URI Template (RFC 6570)

我有一个来自另一家公司的新项目的 RESTful API 规范,它参考了 RFC6570 和在向 URI 模板发出请求时使用片段扩展 {#var}他们的 API.

URI 模板如下所示:

PUT https://api.acme.com/order{#meta*}{?order_number}GET https://api.acme.com/orders{#meta*}(注意与order/orders的区别)。

他们提到'if the metadata stored on your system looks like this:'

{
  "meta": {
    "customer": "1234",
    "state": "open"
  },
  "order_number": "0003"
}

然后将其转换为 PUT https://api.acme.com/order#customer=1234,state=open?order_number=0003GET https://api.acme.com/orders#customer=1234,state=open 等请求。

URL 个片段,例如#customer=1234,state=open 旨在用作某种元数据过滤或请求的上下文?

Postman、curl 和浏览器请求在发送到服务器之前似乎删除了 # 之后的所有内容。这是预期的行为并在某处的 RFC 中进行了描述吗?这是否意味着这些 RESTful URL 无效?

URL 模板中 {#var} 片段扩展的正确用例是什么?

Postman, curl and browser requests appear to strip out everything after the # before sending to the server. Is that expected behaviour and described in an RFC somewhere?

是的,在RFC 3896

中有描述

the fragment identifier is not used in the scheme-specific processing of a URI; instead, the fragment identifier is separated from the rest of the URI prior to a dereference, and thus the identifying information within the fragment itself is dereferenced solely by the user agent, regardless of the URI scheme.

相同的想法,如 RFC 7230 所述


Does that mean these RESTful URLs are invalid?

有点。

https://api.acme.com/orders#customer=1234,state=open

这是完全有效的 URL(参见 RFC 3986 appendix A 中的产生式规则)。

让我们回顾一下 fragments 的规范:

The fragment identifier component of a URI allows indirect identification of a secondary resource by reference to a primary resource and additional identifying information. The identified secondary resource may be some portion or subset of the primary resource, some view on representations of the primary resource, or some other resource defined or described by those representations.

HTTP definition更清楚一点:

The optional fragment component allows for indirect identification of a secondary resource

为了练习,让我们看一下片段规范本身的标识符

https://www.rfc-editor.org/rfc/rfc3986#section-3.5

我们这里有两个资源的标识符:“主要资源”是网页本身,它由片段分隔符之前的字符序列标识 -- https://www.rfc-editor.org/rfc/rfc3986 ;然后我们在 那个主要资源中有了次要资源, section-3.5 告诉我们要在主要资源中寻找什么。因此浏览器知道 (a) 下载主要资源,然后 (b) 在发现主要资源具有 text/html 表示时,知道如何挖掘 html 标签以找到包含匹配片段。然后浏览器可以直接跳转到文档中的正确位置。

在您的示例中,https://api.acme.com/orders 是主要资源,customer=1234,state=open 是用于识别主要资源表示中的某些资源的片段。

但是

RFC 7230 定义了 HTTP

request line
method SP request-target SP HTTP-version CRLF

其中 request-target 又定义为

     request-target = origin-form
                    / absolute-form
                    / authority-form
                    / asterisk-form

我们感兴趣的两个是 origin-form and absolute-form。两者均由 RFC 7230

定义
origin-form    = absolute-path [ "?" query ]
absolute-form  = absolute-URI

其中 absolute-URI 在 RFC 3986

中定义

Some protocol elements allow only the absolute form of a URI without a fragment identifier.

absolute-URI  = scheme ":" hier-part [ "?" query ]

这都符合target-uri

的限制

The target URI excludes the reference's fragment component, if any, since fragment identifiers are reserved for client-side processing


What is the proper use case for the {#var} fragment expansion in URL Templates?

试图构建一个 link 到辅助资源,特别是作为两段代码的协作;一段代码知道模板变量的值但不知道它们应该去哪里(特别是,哪些变量属于片段),另一段代码知道每个不同变量在 URI 中的位置出现,但不知道值是什么。

换句话说,这与我们在创建 URI 模板时所做的事情完全相同,以允许生成主要资源的标识符,但也允许在片段元素中进行变量扩展。

http://example.org/people/bob
http://example.org/people#bob