5.7. Proxying
A proxy is a CoAP endpoint that can be tasked by CoAP clients to perform requests on their behalf. This may be useful, for example, when the request could otherwise not be made, or to service the response from a cache in order to reduce response time and network bandwidth or energy consumption. In an overall architecture for a Constrained RESTful Environment, proxies can serve quite different purposes. Proxies can be explicitly selected by clients, a role that we term "forward-proxy". Proxies can also be inserted to stand in for origin servers, a role that we term "reverse-proxy". Orthogonal to this distinction, a proxy can map from a CoAP request to a CoAP request (CoAP-to-CoAP proxy) or translate from or to a different protocol ("cross-proxy"). Full definitions of these terms are provided in Section 1.2. Notes: The terminology in this specification has been selected to be culturally compatible with the terminology used in the wider web application environments, without necessarily matching it in every detail (which may not even be relevant to Constrained RESTful Environments). Not too much semantics should be ascribed to the components of the terms (such as "forward", "reverse", or "cross"). HTTP proxies, besides acting as HTTP proxies, often offer a transport-protocol proxying function ("CONNECT") to enable end-to- end transport layer security through the proxy. No such function is defined for CoAP-to-CoAP proxies in this specification, as forwarding of UDP packets is unlikely to be of much value in Constrained RESTful Environments. See also Section 10.2.7 for the cross-proxy case. When a client uses a proxy to make a request that will use a secure URI scheme (e.g., "coaps" or "https"), the request towards the proxy SHOULD be sent using DTLS except where equivalent lower-layer security is used for the leg between the client and the proxy.5.7.1. Proxy Operation
A proxy generally needs a way to determine potential request parameters for a request it places to a destination, based on the request it received from its client. This way is fully specified for a forward-proxy but may depend on the specific configuration for a reverse-proxy. In particular, the client of a reverse-proxy generally does not indicate a locator for the destination,
necessitating some form of namespace translation in the reverse- proxy. However, some aspects of the operation of proxies are common to all its forms. If a proxy does not employ a cache, then it simply forwards the translated request to the determined destination. Otherwise, if it does employ a cache but does not have a stored response that matches the translated request and is considered fresh, then it needs to refresh its cache according to Section 5.6. For options in the request that the proxy recognizes, it knows whether the option is intended to act as part of the key used in looking up the cached value or not. For example, since requests for different Uri-Path values address different resources, Uri-Path values are always part of the Cache-Key, while, e.g., Token values are never part of the Cache-Key. For options that the proxy does not recognize but that are marked Safe-to-Forward in the option number, the option also indicates whether it is to be included in the Cache-Key (NoCacheKey is not all set) or not (NoCacheKey is all set). (Options that are unrecognized and marked Unsafe lead to 4.02 Bad Option.) If the request to the destination times out, then a 5.04 (Gateway Timeout) response MUST be returned. If the request to the destination returns a response that cannot be processed by the proxy (e.g, due to unrecognized critical options or message format errors), then a 5.02 (Bad Gateway) response MUST be returned. Otherwise, the proxy returns the response to the client. If a response is generated out of a cache, the generated (or implied) Max-Age Option MUST NOT extend the max-age originally set by the server, considering the time the resource representation spent in the cache. For example, the Max-Age Option could be adjusted by the proxy for each response using the formula: proxy-max-age = original-max-age - cache-age For example, if a request is made to a proxied resource that was refreshed 20 seconds ago and had an original Max-Age of 60 seconds, then that resource's proxied max-age is now 40 seconds. Considering potential network delays on the way from the origin server, a proxy should be conservative in the max-age values offered. All options present in a proxy request MUST be processed at the proxy. Unsafe options in a request that are not recognized by the proxy MUST lead to a 4.02 (Bad Option) response being returned by the proxy. A CoAP-to-CoAP proxy MUST forward to the origin server all Safe-to-Forward options that it does not recognize. Similarly,
Unsafe options in a response that are not recognized by the CoAP-to- CoAP proxy server MUST lead to a 5.02 (Bad Gateway) response. Again, Safe-to-Forward options that are not recognized MUST be forwarded. Additional considerations for cross-protocol proxying between CoAP and HTTP are discussed in Section 10.5.7.2. Forward-Proxies
CoAP distinguishes between requests made (as if) to an origin server and requests made through a forward-proxy. CoAP requests to a forward-proxy are made as normal Confirmable or Non-confirmable requests to the forward-proxy endpoint, but they specify the request URI in a different way: The request URI in a proxy request is specified as a string in the Proxy-Uri Option (see Section 5.10.2), while the request URI in a request to an origin server is split into the Uri-Host, Uri-Port, Uri-Path, and Uri-Query Options (see Section 5.10.1). Alternatively, the URI in a proxy request can be assembled from a Proxy-Scheme option and the split options mentioned. When a proxy request is made to an endpoint and the endpoint is unwilling or unable to act as proxy for the request URI, it MUST return a 5.05 (Proxying Not Supported) response. If the authority (host and port) is recognized as identifying the proxy endpoint itself (see Section 5.10.2), then the request MUST be treated as a local (non-proxied) request. Unless a proxy is configured to forward the proxy request to another proxy, it MUST translate the request as follows: the scheme of the request URI defines the outgoing protocol and its details (e.g., CoAP is used over UDP for the "coap" scheme and over DTLS for the "coaps" scheme.) For a CoAP-to-CoAP proxy, the origin server's IP address and port are determined by the authority component of the request URI, and the request URI is decoded and split into the Uri-Host, Uri- Port, Uri-Path and Uri-Query Options. This consumes the Proxy-Uri or Proxy-Scheme option, which is therefore not forwarded to the origin server.5.7.3. Reverse-Proxies
Reverse-proxies do not make use of the Proxy-Uri or Proxy-Scheme options but need to determine the destination (next hop) of a request from information in the request and information in their configuration. For example, a reverse-proxy might offer various resources as if they were its own resources, after having learned of their existence through resource discovery. The reverse-proxy is free to build a namespace for the URIs that identify these resources. A reverse-proxy may also build a namespace that gives the client more
control over where the request goes, e.g., by embedding host identifiers and port numbers into the URI path of the resources offered. In processing the response, a reverse-proxy has to be careful that ETag option values from different sources are not mixed up on one resource offered to its clients. In many cases, the ETag can be forwarded unchanged. If the mapping from a resource offered by the reverse-proxy to resources offered by its various origin servers is not unique, the reverse-proxy may need to generate a new ETag, making sure the semantics of this option are properly preserved.5.8. Method Definitions
In this section, each method is defined along with its behavior. A request with an unrecognized or unsupported Method Code MUST generate a 4.05 (Method Not Allowed) piggybacked response.5.8.1. GET
The GET method retrieves a representation for the information that currently corresponds to the resource identified by the request URI. If the request includes an Accept Option, that indicates the preferred content-format of a response. If the request includes an ETag Option, the GET method requests that ETag be validated and that the representation be transferred only if validation failed. Upon success, a 2.05 (Content) or 2.03 (Valid) Response Code SHOULD be present in the response. The GET method is safe and idempotent.5.8.2. POST
The POST method requests that the representation enclosed in the request be processed. The actual function performed by the POST method is determined by the origin server and dependent on the target resource. It usually results in a new resource being created or the target resource being updated. If a resource has been created on the server, the response returned by the server SHOULD have a 2.01 (Created) Response Code and SHOULD include the URI of the new resource in a sequence of one or more Location-Path and/or Location-Query Options (Section 5.10.7). If the POST succeeds but does not result in a new resource being created on the server, the response SHOULD have a 2.04 (Changed) Response Code. If the POST succeeds and results in the target resource being deleted, the response SHOULD have a 2.02 (Deleted) Response Code. POST is neither safe nor idempotent.
5.8.3. PUT
The PUT method requests that the resource identified by the request URI be updated or created with the enclosed representation. The representation format is specified by the media type and content coding given in the Content-Format Option, if provided. If a resource exists at the request URI, the enclosed representation SHOULD be considered a modified version of that resource, and a 2.04 (Changed) Response Code SHOULD be returned. If no resource exists, then the server MAY create a new resource with that URI, resulting in a 2.01 (Created) Response Code. If the resource could not be created or modified, then an appropriate error Response Code SHOULD be sent. Further restrictions to a PUT can be made by including the If-Match (see Section 5.10.8.1) or If-None-Match (see Section 5.10.8.2) options in the request. PUT is not safe but is idempotent.5.8.4. DELETE
The DELETE method requests that the resource identified by the request URI be deleted. A 2.02 (Deleted) Response Code SHOULD be used on success or in case the resource did not exist before the request. DELETE is not safe but is idempotent.5.9. Response Code Definitions
Each Response Code is described below, including any options required in the response. Where appropriate, some of the codes will be specified in regards to related Response Codes in HTTP [RFC2616]; this does not mean that any such relationship modifies the HTTP mapping specified in Section 10.5.9.1. Success 2.xx
This class of Response Code indicates that the clients request was successfully received, understood, and accepted.5.9.1.1. 2.01 Created
Like HTTP 201 "Created", but only used in response to POST and PUT requests. The payload returned with the response, if any, is a representation of the action result.
If the response includes one or more Location-Path and/or Location- Query Options, the values of these options specify the location at which the resource was created. Otherwise, the resource was created at the request URI. A cache receiving this response MUST mark any stored response for the created resource as not fresh. This response is not cacheable.5.9.1.2. 2.02 Deleted
This Response Code is like HTTP 204 "No Content" but only used in response to requests that cause the resource to cease being available, such as DELETE and, in certain circumstances, POST. The payload returned with the response, if any, is a representation of the action result. This response is not cacheable. However, a cache MUST mark any stored response for the deleted resource as not fresh.5.9.1.3. 2.03 Valid
This Response Code is related to HTTP 304 "Not Modified" but only used to indicate that the response identified by the entity-tag identified by the included ETag Option is valid. Accordingly, the response MUST include an ETag Option and MUST NOT include a payload. When a cache that recognizes and processes the ETag response option receives a 2.03 (Valid) response, it MUST update the stored response with the value of the Max-Age Option included in the response (explicitly, or implicitly as a default value; see also Section 5.6.2). For each type of Safe-to-Forward option present in the response, the (possibly empty) set of options of this type that are present in the stored response MUST be replaced with the set of options of this type in the response received. (Unsafe options may trigger similar option-specific processing as defined by the option.)5.9.1.4. 2.04 Changed
This Response Code is like HTTP 204 "No Content" but only used in response to POST and PUT requests. The payload returned with the response, if any, is a representation of the action result. This response is not cacheable. However, a cache MUST mark any stored response for the changed resource as not fresh.
5.9.1.5. 2.05 Content
This Response Code is like HTTP 200 "OK" but only used in response to GET requests. The payload returned with the response is a representation of the target resource. This response is cacheable: Caches can use the Max-Age Option to determine freshness (see Section 5.6.1) and (if present) the ETag Option for validation (see Section 5.6.2).5.9.2. Client Error 4.xx
This class of Response Code is intended for cases in which the client seems to have erred. These Response Codes are applicable to any request method. The server SHOULD include a diagnostic payload under the conditions detailed in Section 5.5.2. Responses of this class are cacheable: Caches can use the Max-Age Option to determine freshness (see Section 5.6.1). They cannot be validated.5.9.2.1. 4.00 Bad Request
This Response Code is Like HTTP 400 "Bad Request".5.9.2.2. 4.01 Unauthorized
The client is not authorized to perform the requested action. The client SHOULD NOT repeat the request without first improving its authentication status to the server. Which specific mechanism can be used for this is outside this document's scope; see also Section 9.5.9.2.3. 4.02 Bad Option
The request could not be understood by the server due to one or more unrecognized or malformed options. The client SHOULD NOT repeat the request without modification.5.9.2.4. 4.03 Forbidden
This Response Code is like HTTP 403 "Forbidden".
5.9.2.5. 4.04 Not Found
This Response Code is like HTTP 404 "Not Found".5.9.2.6. 4.05 Method Not Allowed
This Response Code is like HTTP 405 "Method Not Allowed" but with no parallel to the "Allow" header field.5.9.2.7. 4.06 Not Acceptable
This Response Code is like HTTP 406 "Not Acceptable", but with no response entity.5.9.2.8. 4.12 Precondition Failed
This Response Code is like HTTP 412 "Precondition Failed".5.9.2.9. 4.13 Request Entity Too Large
This Response Code is like HTTP 413 "Request Entity Too Large". The response SHOULD include a Size1 Option (Section 5.10.9) to indicate the maximum size of request entity the server is able and willing to handle, unless the server is not in a position to make this information available.5.9.2.10. 4.15 Unsupported Content-Format
This Response Code is like HTTP 415 "Unsupported Media Type".5.9.3. Server Error 5.xx
This class of Response Code indicates cases in which the server is aware that it has erred or is incapable of performing the request. These Response Codes are applicable to any request method. The server SHOULD include a diagnostic payload under the conditions detailed in Section 5.5.2. Responses of this class are cacheable: Caches can use the Max-Age Option to determine freshness (see Section 5.6.1). They cannot be validated.5.9.3.1. 5.00 Internal Server Error
This Response Code is like HTTP 500 "Internal Server Error".
5.9.3.2. 5.01 Not Implemented
This Response Code is like HTTP 501 "Not Implemented".5.9.3.3. 5.02 Bad Gateway
This Response Code is like HTTP 502 "Bad Gateway".5.9.3.4. 5.03 Service Unavailable
This Response Code is like HTTP 503 "Service Unavailable" but uses the Max-Age Option in place of the "Retry-After" header field to indicate the number of seconds after which to retry.5.9.3.5. 5.04 Gateway Timeout
This Response Code is like HTTP 504 "Gateway Timeout".5.9.3.6. 5.05 Proxying Not Supported
The server is unable or unwilling to act as a forward-proxy for the URI specified in the Proxy-Uri Option or using Proxy-Scheme (see Section 5.10.2).5.10. Option Definitions
The individual CoAP options are summarized in Table 4 and explained in the subsections of this section. In this table, the C, U, and N columns indicate the properties Critical, UnSafe, and NoCacheKey, respectively. Since NoCacheKey only has a meaning for options that are Safe-to-Forward (not marked Unsafe), the column is filled with a dash for UnSafe options.
+-----+---+---+---+---+----------------+--------+--------+----------+ | No. | C | U | N | R | Name | Format | Length | Default | +-----+---+---+---+---+----------------+--------+--------+----------+ | 1 | x | | | x | If-Match | opaque | 0-8 | (none) | | 3 | x | x | - | | Uri-Host | string | 1-255 | (see | | | | | | | | | | below) | | 4 | | | | x | ETag | opaque | 1-8 | (none) | | 5 | x | | | | If-None-Match | empty | 0 | (none) | | 7 | x | x | - | | Uri-Port | uint | 0-2 | (see | | | | | | | | | | below) | | 8 | | | | x | Location-Path | string | 0-255 | (none) | | 11 | x | x | - | x | Uri-Path | string | 0-255 | (none) | | 12 | | | | | Content-Format | uint | 0-2 | (none) | | 14 | | x | - | | Max-Age | uint | 0-4 | 60 | | 15 | x | x | - | x | Uri-Query | string | 0-255 | (none) | | 17 | x | | | | Accept | uint | 0-2 | (none) | | 20 | | | | x | Location-Query | string | 0-255 | (none) | | 35 | x | x | - | | Proxy-Uri | string | 1-1034 | (none) | | 39 | x | x | - | | Proxy-Scheme | string | 1-255 | (none) | | 60 | | | x | | Size1 | uint | 0-4 | (none) | +-----+---+---+---+---+----------------+--------+--------+----------+ C=Critical, U=Unsafe, N=NoCacheKey, R=Repeatable Table 4: Options5.10.1. Uri-Host, Uri-Port, Uri-Path, and Uri-Query
The Uri-Host, Uri-Port, Uri-Path, and Uri-Query Options are used to specify the target resource of a request to a CoAP origin server. The options encode the different components of the request URI in a way that no percent-encoding is visible in the option values and that the full URI can be reconstructed at any involved endpoint. The syntax of CoAP URIs is defined in Section 6. The steps for parsing URIs into options is defined in Section 6.4. These steps result in zero or more Uri-Host, Uri-Port, Uri-Path, and Uri-Query Options being included in a request, where each option holds the following values: o the Uri-Host Option specifies the Internet host of the resource being requested, o the Uri-Port Option specifies the transport-layer port number of the resource, o each Uri-Path Option specifies one segment of the absolute path to the resource, and
o each Uri-Query Option specifies one argument parameterizing the resource. Note: Fragments ([RFC3986], Section 3.5) are not part of the request URI and thus will not be transmitted in a CoAP request. The default value of the Uri-Host Option is the IP literal representing the destination IP address of the request message. Likewise, the default value of the Uri-Port Option is the destination UDP port. The default values for the Uri-Host and Uri-Port Options are sufficient for requests to most servers. Explicit Uri-Host and Uri-Port Options are typically used when an endpoint hosts multiple virtual servers. The Uri-Path and Uri-Query Option can contain any character sequence. No percent-encoding is performed. The value of a Uri-Path Option MUST NOT be "." or ".." (as the request URI must be resolved before parsing it into options). The steps for constructing the request URI from the options are defined in Section 6.5. Note that an implementation does not necessarily have to construct the URI; it can simply look up the target resource by examining the individual options. Examples can be found in Appendix B.5.10.2. Proxy-Uri and Proxy-Scheme
The Proxy-Uri Option is used to make a request to a forward-proxy (see Section 5.7). The forward-proxy is requested to forward the request or service it from a valid cache and return the response. The option value is an absolute-URI ([RFC3986], Section 4.3). Note that the forward-proxy MAY forward the request on to another proxy or directly to the server specified by the absolute-URI. In order to avoid request loops, a proxy MUST be able to recognize all of its server names, including any aliases, local variations, and the numeric IP addresses. An endpoint receiving a request with a Proxy-Uri Option that is unable or unwilling to act as a forward-proxy for the request MUST cause the return of a 5.05 (Proxying Not Supported) response. The Proxy-Uri Option MUST take precedence over any of the Uri-Host, Uri-Port, Uri-Path or Uri-Query options (each of which MUST NOT be included in a request containing the Proxy-Uri Option).
As a special case to simplify many proxy clients, the absolute-URI can be constructed from the Uri-* options. When a Proxy-Scheme Option is present, the absolute-URI is constructed as follows: a CoAP URI is constructed from the Uri-* options as defined in Section 6.5. In the resulting URI, the initial scheme up to, but not including, the following colon is then replaced by the content of the Proxy- Scheme Option. Note that this case is only applicable if the components of the desired URI other than the scheme component actually can be expressed using Uri-* options; for example, to represent a URI with a userinfo component in the authority, only Proxy-Uri can be used.5.10.3. Content-Format
The Content-Format Option indicates the representation format of the message payload. The representation format is given as a numeric Content-Format identifier that is defined in the "CoAP Content- Formats" registry (Section 12.3). In the absence of the option, no default value is assumed, i.e., the representation format of any representation message payload is indeterminate (Section 5.5).5.10.4. Accept
The CoAP Accept option can be used to indicate which Content-Format is acceptable to the client. The representation format is given as a numeric Content-Format identifier that is defined in the "CoAP Content-Formats" registry (Section 12.3). If no Accept option is given, the client does not express a preference (thus no default value is assumed). The client prefers the representation returned by the server to be in the Content-Format indicated. The server returns the preferred Content-Format if available. If the preferred Content- Format cannot be returned, then a 4.06 "Not Acceptable" MUST be sent as a response, unless another error code takes precedence for this response.5.10.5. Max-Age
The Max-Age Option indicates the maximum time a response may be cached before it is considered not fresh (see Section 5.6.1). The option value is an integer number of seconds between 0 and 2**32-1 inclusive (about 136.1 years). A default value of 60 seconds is assumed in the absence of the option in a response. The value is intended to be current at the time of transmission. Servers that provide resources with strict tolerances on the value of Max-Age SHOULD update the value before each retransmission. (See also Section 5.7.1.)
5.10.6. ETag
An entity-tag is intended for use as a resource-local identifier for differentiating between representations of the same resource that vary over time. It is generated by the server providing the resource, which may generate it in any number of ways including a version, checksum, hash, or time. An endpoint receiving an entity- tag MUST treat it as opaque and make no assumptions about its content or structure. (Endpoints that generate an entity-tag are encouraged to use the most compact representation possible, in particular in regards to clients and intermediaries that may want to store multiple ETag values.)5.10.6.1. ETag as a Response Option
The ETag Option in a response provides the current value (i.e., after the request was processed) of the entity-tag for the "tagged representation". If no Location-* options are present, the tagged representation is the selected representation (Section 5.5.3) of the target resource. If one or more Location-* options are present and thus a location URI is indicated (Section 5.10.7), the tagged representation is the representation that would be retrieved by a GET request to the location URI. An ETag response option can be included with any response for which there is a tagged representation (e.g., it would not be meaningful in a 4.04 or 4.00 response). The ETag Option MUST NOT occur more than once in a response. There is no default value for the ETag Option; if it is not present in a response, the server makes no statement about the entity-tag for the tagged representation.5.10.6.2. ETag as a Request Option
In a GET request, an endpoint that has one or more representations previously obtained from the resource, and has obtained ETag response options with these, can specify an instance of the ETag Option for one or more of these stored responses. A server can issue a 2.03 Valid response (Section 5.9.1.3) in place of a 2.05 Content response if one of the ETags given is the entity- tag for the current representation, i.e., is valid; the 2.03 Valid response then echoes this specific ETag in a response option. In effect, a client can determine if any of the stored representations is current (see Section 5.6.2) without needing to transfer them again.
The ETag Option MAY occur zero, one, or multiple times in a request.5.10.7. Location-Path and Location-Query
The Location-Path and Location-Query Options together indicate a relative URI that consists either of an absolute path, a query string, or both. A combination of these options is included in a 2.01 (Created) response to indicate the location of the resource created as the result of a POST request (see Section 5.8.2). The location is resolved relative to the request URI. If a response with one or more Location-Path and/or Location-Query Options passes through a cache that interprets these options and the implied URI identifies one or more currently stored responses, those entries MUST be marked as not fresh. Each Location-Path Option specifies one segment of the absolute path to the resource, and each Location-Query Option specifies one argument parameterizing the resource. The Location-Path and Location-Query Option can contain any character sequence. No percent-encoding is performed. The value of a Location-Path Option MUST NOT be "." or "..". The steps for constructing the location URI from the options are analogous to Section 6.5, except that the first five steps are skipped and the result is a relative URI-reference, which is then interpreted relative to the request URI. Note that the relative URI- reference constructed this way always includes an absolute path (e.g., leaving out Location-Path but supplying Location-Query means the path component in the URI is "/"). The options that are used to compute the relative URI-reference are collectively called Location-* options. Beyond Location-Path and Location-Query, more Location-* options may be defined in the future and have been reserved option numbers 128, 132, 136, and 140. If any of these reserved option numbers occurs in addition to Location-Path and/or Location-Query and are not supported, then a 4.02 (Bad Option) error MUST be returned.5.10.8. Conditional Request Options
Conditional request options enable a client to ask the server to perform the request only if certain conditions specified by the option are fulfilled.
For each of these options, if the condition given is not fulfilled, then the server MUST NOT perform the requested method. Instead, the server MUST respond with the 4.12 (Precondition Failed) Response Code. If the condition is fulfilled, the server performs the request method as if the conditional request options were not present. If the request would, without the conditional request options, result in anything other than a 2.xx or 4.12 Response Code, then any conditional request options MAY be ignored.5.10.8.1. If-Match
The If-Match Option MAY be used to make a request conditional on the current existence or value of an ETag for one or more representations of the target resource. If-Match is generally useful for resource update requests, such as PUT requests, as a means for protecting against accidental overwrites when multiple clients are acting in parallel on the same resource (i.e., the "lost update" problem). The value of an If-Match option is either an ETag or the empty string. An If-Match option with an ETag matches a representation with that exact ETag. An If-Match option with an empty value matches any existing representation (i.e., it places the precondition on the existence of any current representation for the target resource). The If-Match Option can occur multiple times. If any of the options match, then the condition is fulfilled. If there is one or more If-Match Options, but none of the options match, then the condition is not fulfilled.5.10.8.2. If-None-Match
The If-None-Match Option MAY be used to make a request conditional on the nonexistence of the target resource. If-None-Match is useful for resource creation requests, such as PUT requests, as a means for protecting against accidental overwrites when multiple clients are acting in parallel on the same resource. The If-None-Match Option carries no value. If the target resource does exist, then the condition is not fulfilled. (It is not very useful to combine If-Match and If-None-Match options in one request, because the condition will then never be fulfilled.)
5.10.9. Size1 Option
The Size1 option provides size information about the resource representation in a request. The option value is an integer number of bytes. Its main use is with block-wise transfers [BLOCK]. In the present specification, it is used in 4.13 responses (Section 5.9.2.9) to indicate the maximum size of request entity that the server is able and willing to handle.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.xml6.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. 1. If the |url| string is not an absolute URI ([RFC3986]), then fail this algorithm. 2. 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. 3. If |url| does not have a <scheme> component whose value, when converted to ASCII lowercase, is "coap" or "coaps", then fail this algorithm. 4. If |url| has a <fragment> component, then fail this algorithm.
5. If the <host> 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 <host> 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 <host> component of the form reg- name. 6. If |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. 7. If |port| does not equal the request's destination UDP port, include a Uri-Port Option and let that option's value be |port|. 8. If the value of the <path> 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 <path> 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. 9. If |url| has a <query> component, then, for each argument in the <query> 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].
1. If the request is secured using DTLS, let |url| be the string "coaps://". Otherwise, let |url| be the string "coap://". 2. 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. 3. Append |host| to |url|. 4. 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. 5. 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|. 6. 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. 7. If |resource name| is the empty string, set it to a single character U+002F SOLIDUS (/). 8. 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. 9. Append |resource name| to |url|. 10. Return |url|. Note that these steps have been designed to lead to a URI in normal form (see Section 6.3).