6. CoAP URIs
CoAP uses the "coap" and "coaps" URI schemes for identifying CoAP resources and providing a means of locating the resource. Resources are organized hierarchically and governed by a potential CoAP origin server listening for CoAP requests ("coap") or DTLS-secured CoAP requests ("coaps") on a given UDP port. The CoAP server is identified via the generic syntax's authority component, which includes a host component and optional UDP port number. The remainder of the URI is considered to be identifying a resource that can be operated on by the methods defined by the CoAP protocol. The "coap" and "coaps" URI schemes can thus be compared to the "http" and "https" URI schemes, respectively.
The syntax of the "coap" and "coaps" URI schemes is specified in this section in Augmented Backus-Naur Form (ABNF) [RFC5234]. The definitions of "host", "port", "path-abempty", "query", "segment", "IP-literal", "IPv4address", and "reg-name" are adopted from [RFC3986].
Implementation Note: Unfortunately, over time, the URI format has acquired significant complexity. Implementers are encouraged to examine [RFC3986] closely. For example, the ABNF for IPv6 addresses is more complicated than maybe expected. Also, implementers should take care to perform the processing of percent-decoding or percent-encoding exactly once on the way from a URI to its decoded components or back. Percent-encoding is crucial for data transparency but may lead to unusual results such as a slash character in a path component.
6.1. coap URI Scheme
coap-URI = "coap:" "//" host [ ":" port ] path-abempty [ "?" query ]
If the host component is provided as an IP-literal or IPv4address, then the CoAP server can be reached at that IP address. If host is a registered name, then that name is considered an indirect identifier and the endpoint might use a name resolution service, such as DNS, to find the address of that host. The host MUST NOT be empty; if a URI
is received with a missing authority or an empty host, then it MUST be considered invalid. The port subcomponent indicates the UDP port at which the CoAP server is located. If it is empty or not given, then the default port 5683 is assumed.
The path identifies a resource within the scope of the host and port. It consists of a sequence of path segments separated by a slash character (U+002F SOLIDUS "/").
The query serves to further parameterize the resource. It consists of a sequence of arguments separated by an ampersand character (U+0026 AMPERSAND "&"). An argument is often in the form of a "key=value" pair.
The "coap" URI scheme supports the path prefix "/.well-known/" defined by [RFC5785] for "well-known locations" in the namespace of a host. This enables discovery of policy or other information about a host ("site-wide metadata"), such as hosted resources (see Section 7).
Application designers are encouraged to make use of short but descriptive URIs. As the environments that CoAP is used in are usually constrained for bandwidth and energy, the trade-off between these two qualities should lean towards the shortness, without ignoring descriptiveness.
6.2. coaps URI Scheme
coaps-URI = "coaps:" "//" host [ ":" port ] path-abempty [ "?" query ]
All of the requirements listed above for the "coap" scheme are also requirements for the "coaps" scheme, except that a default UDP port of 5684 is assumed if the port subcomponent is empty or not given, and the UDP datagrams MUST be secured through the use of DTLS as described in Section 9.1.
Considerations for caching of responses to "coaps" identified requests are discussed in Section 11.2.
Resources made available via the "coaps" scheme have no shared identity with the "coap" scheme even if their resource identifiers indicate the same authority (the same host listening to the same UDP port). They are distinct namespaces and are considered to be distinct origin servers.
6.3. Normalization and Comparison Rules
Since the "coap" and "coaps" schemes conform to the URI generic syntax, such URIs are normalized and compared according to the algorithm defined in [RFC3986], Section 6, using the defaults described above for each scheme.
If the port is equal to the default port for a scheme, the normal form is to elide the port subcomponent. Likewise, an empty path component is equivalent to an absolute path of "/", so the normal form is to provide a path of "/" instead. The scheme and host are case insensitive and normally provided in lowercase; IP-literals are in recommended form [RFC5952]; all other components are compared in a case-sensitive manner. Characters other than those in the "reserved" set are equivalent to their percent-encoded bytes (see [RFC3986], Section 2.1): the normal form is to not encode them.
For example, the following three URIs are equivalent and cause the same options and option values to appear in the CoAP messages:
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
The steps to parse a request's options from a string |url| are as follows. These steps either result in zero or more of the Uri-Host, Uri-Port, Uri-Path, and Uri-Query Options being included in the request or they fail.
-
If the |url| string is not an absolute URI ([RFC3986]), then fail this algorithm.
-
Resolve the |url| string using the process of reference resolution defined by [RFC3986]. At this stage, the URL is in ASCII encoding [RFC0020], even though the decoded components will be interpreted in UTF-8 [RFC3629] after steps 5, 8, and 9.
NOTE: It doesn't matter what it is resolved relative to, since we already know it is an absolute URL at this point.
-
If |url| does not have a
component whose value, when converted to ASCII lowercase, is "coap" or "coaps", then fail this algorithm. -
If |url| has a
component, then fail this algorithm. -
If the
component of |url| does not represent the request's destination IP address as an IP-literal or IPv4address, include a Uri-Host Option and let that option's value be the value of the component of |url|, converted to ASCII lowercase, and then convert all percent-encodings ("%" followed by two hexadecimal digits) to the corresponding characters. NOTE: In the usual case where the request's destination IP address is derived from the host part, this ensures that a Uri- Host Option is only used for a
component of the form reg- name. -
If |url| has a
component, then let |port| be that component's value interpreted as a decimal integer; otherwise, let |port| be the default port for the scheme. -
If |port| does not equal the request's destination UDP port, include a Uri-Port Option and let that option's value be |port|.
-
If the value of the
component of |url| is empty or consists of a single slash character (U+002F SOLIDUS "/"), then move to the next step. Otherwise, for each segment in the
component, include a Uri-Path Option and let that option's value be the segment (not including the delimiting slash characters) after converting each percent-encoding ("%" followed by two hexadecimal digits) to the corresponding byte. -
If |url| has a
component, then, for each argument in the component, include a Uri-Query Option and let that option's value be the argument (not including the question mark and the delimiting ampersand characters) after converting each percent-encoding to the corresponding byte.
Note that these rules completely resolve any percent-encoding.
6.5. Composing URIs from Options
The steps to construct a URI from a request's options are as follows. These steps either result in a URI or they fail. In these steps, percent-encoding a character means replacing each of its (UTF-8-encoded) bytes by a "%" character followed by two hexadecimal digits representing the byte, where the digits A-F are in uppercase (as defined in Section 2.1 of [RFC3986]; to reduce variability, the hexadecimal notation for percent-encoding in CoAP URIs MUST use uppercase letters). The definitions of "unreserved" and "sub-delims" are adopted from [RFC3986].
-
If the request is secured using DTLS, let |url| be the string "coaps://". Otherwise, let |url| be the string "coap://".
-
If the request includes a Uri-Host Option, let |host| be that option's value, where any non-ASCII characters are replaced by their corresponding percent-encoding. If |host| is not a valid reg-name or IP-literal or IPv4address, fail the algorithm. If the request does not include a Uri-Host Option, let |host| be the IP-literal (making use of the conventions of [RFC5952]) or IPv4address representing the request's destination IP address.
-
Append |host| to |url|.
-
If the request includes a Uri-Port Option, let |port| be that option's value. Otherwise, let |port| be the request's destination UDP port.
-
If |port| is not the default port for the scheme, then append a single U+003A COLON character (:) followed by the decimal representation of |port| to |url|.
-
Let |resource name| be the empty string. For each Uri-Path Option in the request, append a single character U+002F SOLIDUS (/) followed by the option's value to |resource name|, after converting any character that is not either in the "unreserved" set, in the "sub-delims" set, a U+003A COLON (:) character, or a U+0040 COMMERCIAL AT (@) character to its percent-encoded form.
-
If |resource name| is the empty string, set it to a single character U+002F SOLIDUS (/).
-
For each Uri-Query Option in the request, append a single character U+003F QUESTION MARK (?) (first option) or U+0026 AMPERSAND (&) (subsequent options) followed by the option's value to |resource name|, after converting any character that is not either in the "unreserved" set, in the "sub-delims" set (except U+0026 AMPERSAND (&)), a U+003A COLON (:), a U+0040 COMMERCIAL AT (@), a U+002F SOLIDUS (/), or a U+003F QUESTION MARK (?) character to its percent-encoded form.
-
Append |resource name| to |url|.
-
Return |url|.
Note that these steps have been designed to lead to a URI in normal form (see Section 6.3).