6. CoAP URIs
CoAP使用"coap"和"coaps" URI方案来标识CoAP资源并提供定位资源的方法. 资源以层次结构组织, 并由可能的CoAP源服务器管理, 该服务器在给定的UDP端口上侦听CoAP请求 ("coap") 或DTLS保护的CoAP请求 ("coaps"). CoAP服务器通过通用语法的授权组件标识, 该组件包括主机组件和可选的UDP端口号. URI的其余部分被认为是标识可以由CoAP协议定义的方法操作的资源. 因此, "coap"和"coaps" URI方案可以分别与"http"和"https" URI方案进行比较.
"coap"和"coaps" URI方案的语法在本节中以增强的巴科斯-诺尔范式 (ABNF, Augmented Backus-Naur Form) [RFC5234] 指定. "host", "port", "path-abempty", "query", "segment", "IP-literal", "IPv4address"和"reg-name"的定义从[RFC3986]采用.
实现注意: 不幸的是, 随着时间的推移, URI格式变得相当复杂. 鼓励实现者仔细阅读[RFC3986]. 例如, IPv6地址的ABNF比可能预期的更复杂. 此外, 实现者应注意在从URI到其解码组件或返回的过程中恰好执行一次百分号解码或百分号编码的处理. 百分号编码对于数据透明性至关重要, 但可能导致不寻常的结果, 例如路径组件中的斜杠字符.
6.1. coap URI Scheme (coap URI方案)
coap-URI = "coap:" "//" host [ ":" port ] path-abempty [ "?" query ]
如果主机组件作为IP-literal或IPv4address提供, 则可以通过该IP地址访问CoAP服务器. 如果主机是注册名称, 则该名称被视为间接标识符, 端点可能使用名称解析服务 (例如DNS) 来查找该主机的地址. 主机不得为空; 如果接收到具有缺失授权或空主机的URI, 则必须将其视为无效. 端口子组件指示CoAP服务器所在的UDP端口. 如果它为空或未给出, 则假定默认端口5683.
路径标识主机和端口范围内的资源. 它由斜杠字符 (U+002F SOLIDUS "/") 分隔的路径段序列组成.
查询用于进一步参数化资源. 它由与号字符 (U+0026 AMPERSAND "&") 分隔的参数序列组成. 参数通常采用"key=value"对的形式.
"coap" URI方案支持[RFC5785]为主机命名空间中的"众所周知的位置"定义的路径前缀"/.well-known/". 这使得能够发现有关主机 ("站点范围元数据") 的策略或其他信息, 例如托管的资源 (见第7节).
鼓励应用程序设计者使用简短但描述性的URI. 由于CoAP使用的环境通常在带宽和能量方面受到限制, 因此这两个品质之间的权衡应该偏向简洁性, 而不忽略描述性.
6.2. coaps URI Scheme (coaps URI方案)
coaps-URI = "coaps:" "//" host [ ":" port ] path-abempty [ "?" query ]
上述针对"coap"方案列出的所有要求也是"coaps"方案的要求, 除了如果端口子组件为空或未给出, 则假定默认UDP端口为5684, 并且UDP数据报必须通过使用DTLS进行保护, 如第9.1节中所述.
第11.2节讨论了对"coaps"标识请求的响应进行缓存的考虑.
通过"coaps"方案提供的资源与"coap"方案没有共享身份, 即使它们的资源标识符指示相同的授权 (侦听同一UDP端口的同一主机). 它们是不同的命名空间, 被认为是不同的源服务器.
6.3. Normalization and Comparison Rules (规范化和比较规则)
由于"coap"和"coaps"方案符合URI通用语法, 因此根据[RFC3986]第6节中定义的算法, 使用上述每个方案的默认值对此类URI进行规范化和比较.
如果端口等于方案的默认端口, 则正常形式是省略端口子组件. 同样, 空路径组件等效于绝对路径"/", 因此正常形式是提供"/"路径. 方案和主机不区分大小写, 通常以小写形式提供; IP-literal采用推荐形式[RFC5952]; 所有其他组件以区分大小写的方式进行比较. "reserved"集中以外的字符等效于其百分号编码的字节 (见[RFC3986], 第2.1节): 正常形式是不对它们进行编码.
例如, 以下三个URI是等效的, 并导致相同的选项和选项值出现在CoAP消息中:
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 (将URI分解为选项)
从字符串|url|解析请求选项的步骤如下. 这些步骤要么导致零个或多个Uri-Host, Uri-Port, Uri-Path和Uri-Query选项包含在请求中, 要么它们失败.
-
如果|url|字符串不是绝对URI ([RFC3986]), 则此算法失败.
-
使用[RFC3986]定义的引用解析过程解析|url|字符串. 在此阶段, URL采用ASCII编码[RFC0020], 即使解码的组件将在步骤5, 8和9之后以UTF-8 [RFC3629]解释.
注意: 在这一点上解析相对于什么并不重要, 因为我们已经知道它是绝对URL.
-
如果|url|没有
<scheme>组件, 其值转换为ASCII小写后不是"coap"或"coaps", 则此算法失败. -
如果|url|有
<fragment>组件, 则此算法失败. -
如果|url|的
<host>组件不将请求的目标IP地址表示为IP-literal或IPv4address, 则包括Uri-Host选项, 并让该选项的值为|url|的<host>组件的值, 转换为ASCII小写, 然后将所有百分号编码 ("%" 后跟两个十六进制数字) 转换为相应的字符.注意: 在通常情况下, 请求的目标IP地址是从主机部分派生的, 这确保Uri-Host选项仅用于reg-name形式的
<host>组件. -
如果|url|有
<port>组件, 则让|port|为该组件的值解释为十进制整数; 否则, 让|port|为方案的默认端口. -
如果|port|不等于请求的目标UDP端口, 则包括Uri-Port选项, 并让该选项的值为|port|.
-
如果|url|的
<path>组件的值为空或由单个斜杠字符 (U+002F SOLIDUS "/") 组成, 则移至下一步.否则, 对于
<path>组件中的每个段, 包括Uri-Path选项, 并让该选项的值为段 (不包括分隔斜杠字符) 在将每个百分号编码 ("%" 后跟两个十六进制数字) 转换为相应的字节后. -
如果|url|有
<query>组件, 则对于<query>组件中的每个参数, 包括Uri-Query选项, 并让该选项的值为参数 (不包括问号和分隔与号字符) 在将每个百分号编码转换为相应的字节后.
请注意, 这些规则完全解析任何百分号编码.
6.5. Composing URIs from Options (从选项组成URI)
从请求的选项构造URI的步骤如下. 这些步骤要么产生URI, 要么失败. 在这些步骤中, 百分号编码字符意味着用"%"字符后跟表示字节的两个十六进制数字替换其每个 (UTF-8编码的) 字节, 其中数字A-F为大写 (如[RFC3986]第2.1节中定义; 为了减少可变性, CoAP URI中的百分号编码的十六进制表示法必须使用大写字母). "unreserved"和"sub-delims"的定义从[RFC3986]采用.
-
如果请求使用DTLS进行保护, 则让|url|为字符串"coaps://". 否则, 让|url|为字符串"coap://".
-
如果请求包括Uri-Host选项, 则让|host|为该选项的值, 其中任何非ASCII字符都替换为其相应的百分号编码. 如果|host|不是有效的reg-name或IP-literal或IPv4address, 则算法失败. 如果请求不包括Uri-Host选项, 则让|host|为表示请求的目标IP地址的IP-literal (利用[RFC5952]的约定) 或IPv4address.
-
将|host|附加到|url|.
-
如果请求包括Uri-Port选项, 则让|port|为该选项的值. 否则, 让|port|为请求的目标UDP端口.
-
如果|port|不是方案的默认端口, 则将单个U+003A COLON字符 (:) 后跟|port|的十进制表示附加到|url|.
-
让|resource name|为空字符串. 对于请求中的每个Uri-Path选项, 将单个字符U+002F SOLIDUS (/) 后跟选项的值附加到|resource name|, 在将不在"unreserved"集中, 不在"sub-delims"集中, 不是U+003A COLON (:) 字符, 也不是U+0040 COMMERCIAL AT (@) 字符的任何字符转换为其百分号编码形式后.
-
如果|resource name|为空字符串, 则将其设置为单个字符U+002F SOLIDUS (/).
-
对于请求中的每个Uri-Query选项, 将单个字符U+003F QUESTION MARK (?) (第一个选项) 或U+0026 AMPERSAND (&) (后续选项) 后跟选项的值附加到|resource name|, 在将不在"unreserved"集中, 不在"sub-delims"集中 (除了U+0026 AMPERSAND (&)), 不是U+003A COLON (:), 不是U+0040 COMMERCIAL AT (@), 不是U+002F SOLIDUS (/), 也不是U+003F QUESTION MARK (?) 字符的任何字符转换为其百分号编码形式后.
-
将|resource name|附加到|url|.
-
返回|url|.
请注意, 这些步骤旨在导致正常形式的URI (见第6.3节).