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 by the authority component of the generic syntax, which includes a host component and optional UDP port number. The remainder of the URI identifies 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, URI formatting has become quite complicated. Implementers are encouraged to read [RFC3986] carefully. For example, the ABNF for IPv6 addresses is more complex than might be expected. Also, implementers should take care to perform exactly one percent-decoding or percent-encoding pass in the process from a URI to its decoded components or back. Percent-encoding is paramount to 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 an address for that host. The host MUST NOT be empty; if a URI is received with an absent 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 slash characters (U+002F SOLIDUS "/").
The query serves to further parametrize the resource. It consists of a sequence of parameters separated by ampersand characters (U+0026 AMPERSAND "&"). Parameters are typically in the form of "key=value" pairs.
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 use short but descriptive URIs. As the environments that CoAP is used in are usually constrained in terms of bandwidth and energy, the tradeoff between these two qualities should lean towards conciseness 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.
Caching considerations for 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" URI 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 omit 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 "/". 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 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 at this point, since we already know it is an absolute URL.
-
If the |url| does not have a
<scheme>component whose value, after conversion to ASCII lowercase, is "coap" or "coaps", then fail this algorithm. -
If the |url| has a
<fragment>component, then fail this algorithm. -
If the
<host>component of the |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<host>component of the |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 the Uri-Host Option is elective for the reg-name form of the
<host>component. -
If the |url| has a
<port>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
<path>component of the |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
<path>component, include a Uri-Path Option and let that Option's value be the segment (not including the separating slash characters) after converting each percent-encoding ("%" followed by two hexadecimal digits) to the corresponding byte. -
If the |url| has a
<query>component, then, for each parameter in the<query>component, include a Uri-Query Option and let that Option's value be the parameter (not including the question mark and the separating 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 [RFC3986], Section 2.1; to reduce variability, the hexadecimal notation in percent-encodings 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, append a single character U+003A COLON (":") 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 in the "unreserved" set, or is not in the "sub-delims" set, or is not a U+003A COLON (":") character, or is not 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 ("?") (for the first option) or U+0026 AMPERSAND ("&") (for subsequent options) followed by the option's value to |resource name|, after converting any character that is not in the "unreserved" set, or is not in the "sub-delims" set (except U+0026 AMPERSAND ("&")), or is not a U+003A COLON (":"), or is not a U+0040 COMMERCIAL AT ("@"), or is not a U+002F SOLIDUS ("/"), or is not 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).