跳到主要内容

6. CoAP URIs

CoAP 使用 "coap" 和 "coaps" URI scheme 来标识 CoAP resource, 并提供定位 resource 的方法. resource 按层次组织, 并由潜在的 CoAP origin server 管理, 该 server 在给定 UDP port 上监听 CoAP request ("coap") 或 DTLS-secured CoAP request ("coaps"). CoAP server 通过 generic syntax 的 authority component 标识, 其中包括 host component 和可选 UDP port number. URI 的其余部分被视为标识一个 resource, 可由 CoAP 协议定义的 method 对其操作. 因此, "coap" 和 "coaps" URI scheme 可分别与 "http" 和 "https" URI scheme 类比.

本节以 Augmented Backus-Naur Form (ABNF) [RFC5234] 规定 "coap" 和 "coaps" URI scheme 的语法. "host", "port", "path-abempty", "query", "segment", "IP-literal", "IPv4address" 和 "reg-name" 的定义采用 [RFC3986].

Implementation Note: 遗憾的是, 随时间推移, URI format 已经获得了相当大的复杂性. 鼓励实现者仔细研读 [RFC3986]. 例如, IPv6 address 的 ABNF 比可能预期的更复杂. 此外, 实现者应注意, 在从 URI 到其 decoded component 或反向转换的过程中, percent-decoding 或 percent-encoding 处理必须恰好执行一次. Percent-encoding 对数据透明性至关重要, 但可能导致不寻常结果, 例如 path component 中出现 slash character.

6.1. coap URI Scheme​

coap-URI = "coap:" "//" host [ ":" port ] path-abempty [ "?" query ]

如果 host component 以 IP-literal 或 IPv4address 给出, 则可在该 IP address 访问 CoAP server. 如果 host 是 registered name, 则该 name 被视为 indirect identifier, endpoint 可使用 DNS 等 name resolution service 查找该 host 的地址. host MUST NOT 为空; 如果收到的 URI 缺少 authority 或 host 为空, 则 MUST 认为其无效. port subcomponent 指示 CoAP server 所在的 UDP port. 如果为空或未给出, 则假定默认 port 5683.

path 在 host 和 port 的作用域内标识 resource. 它由一系列 path segment 组成, 各 segment 由 slash character (U+002F SOLIDUS "/") 分隔.

query 用于进一步参数化 resource. 它由一系列 argument 组成, 各 argument 由 ampersand character (U+0026 AMPERSAND "&") 分隔. argument 通常采用 "key=value" pair 的形式.

"coap" URI scheme 支持 [RFC5785] 为 host namespace 中的 "well-known locations" 定义的 path prefix "/.well-known/". 这使得可以发现关于 host 的 policy 或其他信息 ("site-wide metadata"), 例如托管的 resource (见 Section 7).

鼓励应用设计者使用短而有描述性的 URI. 由于 CoAP 所用于的环境通常在 bandwidth 和 energy 上受限, 这两种品质之间的权衡应偏向简短, 但不忽略描述性.

6.2. coaps URI Scheme​

coaps-URI = "coaps:" "//" host [ ":" port ] path-abempty [ "?" query ]

上文针对 "coap" scheme 列出的所有要求也适用于 "coaps" scheme, 但有两点例外: 如果 port subcomponent 为空或未给出, 则假定默认 UDP port 为 5684; 并且 UDP datagram MUST 按 Section 9.1 所述使用 DTLS 保护.

对 "coaps" 标识的 request 的 response 进行缓存的注意事项在 Section 11.2 中讨论.

即便 resource identifier 指示相同 authority (同一个 host 监听同一个 UDP port), 通过 "coaps" scheme 可用的 resource 与 "coap" scheme 也没有共享 identity. 它们是不同 namespace, 并被视为不同 origin server.

6.3. Normalization and Comparison Rules​

由于 "coap" 和 "coaps" scheme 符合 URI generic syntax, 此类 URI 按 [RFC3986] Section 6 定义的算法进行 normalization 和 comparison, 并使用上文针对每个 scheme 描述的默认值.

如果 port 等于某 scheme 的默认 port, normal form 是省略 port subcomponent. 同样, 空 path component 等价于 absolute path "/", 因此 normal form 是提供 path "/". scheme 和 host 大小写不敏感, 通常以小写给出; IP-literal 采用推荐形式 [RFC5952]; 所有其他 component 以大小写敏感方式比较. "reserved" set 之外的字符与其 percent-encoded byte 等价 (见 [RFC3986], Section 2.1): normal form 是不对它们编码.

例如, 以下三个 URI 等价, 并会使相同 option 和 option value 出现在 CoAP message 中:

coap://example.com:5683/~sensors/temp.xml coap://EXAMPLE.com/%7Esensors/temp.xml coap://EXAMPLE.com:/%7esensors/temp.xml

6.4. Decomposing URIs into Options​

从字符串 |url| 解析 request option 的步骤如下. 这些步骤要么导致 request 中包含零个或多个 Uri-Host, Uri-Port, Uri-Path 和 Uri-Query Option, 要么失败.

  1. 如果 |url| 字符串不是 absolute URI ([RFC3986]), 则该算法失败.

  2. 使用 [RFC3986] 定义的 reference resolution 过程解析 |url| 字符串. 在此阶段, URL 使用 ASCII encoding [RFC0020], 即使 decoded component 在步骤 5, 8 和 9 之后会按 UTF-8 [RFC3629] 解释.

    NOTE: 它相对于什么解析并不重要, 因为此时我们已经知道它是 absolute URL.

  3. 如果 |url| 没有 component, 或该 component 转换为 ASCII lowercase 后的值不是 "coap" 或 "coaps", 则该算法失败.

  4. 如果 |url| 有 component, 则该算法失败.

  5. 如果 |url| 的 component 不以 IP-literal 或 IPv4address 表示 request 的 destination IP address, 则包含一个 Uri-Host Option, 并令该 option 的值为 |url| 的 component 的值, 先转换为 ASCII lowercase, 再将所有 percent-encoding ("%" 后跟两个 hexadecimal digit) 转换为对应 character.

    NOTE: 在常见情况下, request 的 destination IP address 派生自 host 部分, 这确保 Uri-Host Option 只用于 reg-name 形式的 component.

  6. 如果 |url| 有 component, 则令 |port| 为该 component 的值按 decimal integer 解释; 否则, 令 |port| 为该 scheme 的默认 port.

  7. 如果 |port| 不等于 request 的 destination UDP port, 则包含一个 Uri-Port Option, 并令该 option 的值为 |port|.

  8. 如果 |url| 的 component 的值为空, 或只包含一个 slash character (U+002F SOLIDUS "/"), 则进入下一步.

    否则, 对 component 中的每个 segment, 包含一个 Uri-Path Option, 并令该 option 的值为该 segment (不包括分隔 slash character), 且在将每个 percent-encoding ("%" 后跟两个 hexadecimal digit) 转换为对应 byte 之后得到.

  9. 如果 |url| 有 component, 则对 component 中的每个 argument, 包含一个 Uri-Query Option, 并令该 option 的值为该 argument (不包括 question mark 和分隔 ampersand character), 且在将每个 percent-encoding 转换为对应 byte 之后得到.

注意, 这些规则会完全解析所有 percent-encoding.

6.5. Composing URIs from Options​

从 request option 构造 URI 的步骤如下. 这些步骤要么产生一个 URI, 要么失败. 在这些步骤中, 对字符进行 percent-encoding 是指将其每个 (UTF-8-encoded) byte 替换为一个 "%" character 后跟两个表示该 byte 的 hexadecimal digit, 其中 digit A-F 使用大写 (如 [RFC3986] Section 2.1 所定义; 为减少变化, CoAP URI 中 percent-encoding 的 hexadecimal notation MUST 使用大写字母). "unreserved" 和 "sub-delims" 的定义采用 [RFC3986].

  1. 如果 request 使用 DTLS 保护, 令 |url| 为字符串 "coaps://". 否则, 令 |url| 为字符串 "coap://".

  2. 如果 request 包含 Uri-Host Option, 令 |host| 为该 option 的值, 其中任何 non-ASCII character 都替换为对应 percent-encoding. 如果 |host| 不是有效的 reg-name, IP-literal 或 IPv4address, 则算法失败. 如果 request 不包含 Uri-Host Option, 令 |host| 为表示 request destination IP address 的 IP-literal (使用 [RFC5952] 的约定) 或 IPv4address.

  3. 将 |host| 附加到 |url|.

  4. 如果 request 包含 Uri-Port Option, 令 |port| 为该 option 的值. 否则, 令 |port| 为 request 的 destination UDP port.

  5. 如果 |port| 不是该 scheme 的默认 port, 则向 |url| 附加单个 U+003A COLON character (:) 以及 |port| 的 decimal representation.

  6. 令 |resource name| 为空字符串. 对 request 中每个 Uri-Path Option, 向 |resource name| 附加一个 U+002F SOLIDUS (/) character 后跟该 option 的值, 并在此之前将任何不属于 "unreserved" set, "sub-delims" set, U+003A COLON (:) character 或 U+0040 COMMERCIAL AT (@) character 的字符转换为其 percent-encoded form.

  7. 如果 |resource name| 为空字符串, 将其设置为单个 U+002F SOLIDUS (/) character.

  8. 对 request 中每个 Uri-Query Option, 向 |resource name| 附加一个 U+003F QUESTION MARK (?) character (第一个 option) 或 U+0026 AMPERSAND (&) character (后续 option), 后跟该 option 的值, 并在此之前将任何不属于 "unreserved" set, "sub-delims" set (U+0026 AMPERSAND (&) 除外), U+003A COLON (:), U+0040 COMMERCIAL AT (@), U+002F SOLIDUS (/), 或 U+003F QUESTION MARK (?) character 的字符转换为其 percent-encoded form.

  9. 将 |resource name| 附加到 |url|.

  10. 返回 |url|.

注意, 这些步骤被设计为产生 normal form 的 URI (见 Section 6.3).