-
Notifications
You must be signed in to change notification settings - Fork 1
CoAP FAQ
Collection of questions that tend to come up around CoAP. Answers are provided by various editors, can be conflicting, and do not necessarily reflect any working group consensus.
Q: How can I do redirects in CoAP?
A: Protocol-level redirects are considered by some to be a flaw of HTTP, which is not repeated in CoAP. Instead, applications can use links inside the payload:
- 2.05 Content response with a link-format: The response can provide a link from the requested resource to the "redirection target" using a suitable relation type. That can be
alternate
orcanonical
, for example. This can get a bit tricky when the client uses the Accept option to indicate a different expected format. - 2.05 Content response with an application-specific media type: If the application's format already caters for deferring to an actual source.
- 4.04 Not Found with link-format payload: Should only be used if the link the application followed to this resource was erroneous (but the server still has a good idea of how to help the client).
In any case, it is up to the application to decide whether it trusts the origin server enough to follow the redirection, and whether the target server can provide suitable credentials for the operation.
Q: Diagnostic payloads are human readable error messages. Isn't that wasting resources in constrained environments?
A: They are large but not mandatory;
per RFC7252 they SHOULD be empty if there is no further information than already indicated in the status code
(ie. no Code: 4.04, Payload: "Not Found"
)
Where short application specific errors are necessary, applications can define a media type
that maps numeric codes to messages;
for example, the type application/vnd.my-database-access+cbor
(registerable as a content format in the 10000-64999 range)
can be described for the application
to have 1
mean "Query complexity exceeded", 2
to mean "Query for nonexistant column" and so on.
With the work-in-progress CoRAL format,
specifying a suitable content type is even easier,
as it only needs an application-specific dictionary.
In an application/coral+cbor;dictionary="http://example.com/dbaccess/dict"
content type,
an error message can contain a statement like
"The cause of this error is described by the 'Query complexity exceeded' section of the application documentation"
encoded in a four-byte payload
which is still usable by non-application-specific tools.
Discussion on this is also being had around a constrained version of RFC7807.
Q: Can I send query parameters in binary form?
A: There is currently not any option that are equivalent to Uri-Query: time=256
and contains the number 256 in a binary form.
(Such an option could be established that becomes a pressing issue).
For the common case of GET requests, using FETCH with a CBOR payload is a viable alternative.
Q: Do I have to send a Uri-Host option?
A1: Sending the Uri-Host option is only necessary when talking to a forward proxy (unless Proxy-Uri is used), or when name-based virtual hosting happens on the server.
A2: Not sending a Uri-Host option sets the host part of the URI to the server's IP address, changing the request URI. There is no specified mechanism that allows the server to claim that the IP-only version of its URIs are aliases of the named version, so the client can not obtain a license to elide the Uri-Host option in an application-independent way. This is even true for OSCORE servers, where there are rules against the server relying on the Uri-Host, as intermediaries could rely on the Uri-Host to deliver the message, or the server can need it to find its OSCORE context.
Q: When should I send Proxy-Uri, when Proxy-Scheme?
A: Use Proxy-Scheme whenever you can.
Proxy-Uri is useful for cross-proxying where URIs can occur that can not be expressed in CoAP otherwise, like http://user@example.com/
, or http://example.com/server;hello%3Bworld
. Those examples are rare in practice, even in the protocols that support them. You should expect that a proxy that does not do any cross-proxying might not even support the Proxy-Scheme option, and requires the use of Proxy-Scheme.
Q: Can I send incremental updates over observation?
A: Not directly. One of the reasons for this is that a proxy may serve non-observe requests for the resource from cached observation entries.
Mechanisms to achieve the goal (eg. by observing a change log of the resource) are being discussed on the mailing list.
Q: My application does not process the responses, even though I see them arrive in a network sniffer. Why is that?
A: One typical cause of such errors are servers that send responses from a different IP address and/or port than the request was received on; such behavior happens because it is hard to do right with some network stacks, and often goes unnoticed because other client libraries are overly lenient about accepted source addresses.
As a user, you can verify that this is the case by comparing IP address, port and token of the request and apparent response; all of them must be the same.
As a server author, the CoAP Lightweight Implementation Guidance draft provides useful pointers on responding from the right address.
Q: I'd like to run my lock-step protocol over CoAP (where one device sends a message, then the other sends a message, until some sequence is completed), and need a reliable way to not lose messages or get duplicate ones. How do I do that?
A: In a typical and idiomatic solution, there is an entry point URI to which the client POSTs the first message.
The server then sends the response in a 2.01 Created response as a payload, and indicates in Location-Path options where the next POST request should go. The client then POSTs the next message there, receives a new Location-Path.
A typical (easy-to-debug) pattern of URIs for a given "service" would be /service/
as an entry point, with a random identifier (eg. 0f4ef9bc) used for the individual exchange, and a message counter. Thus, the first POST would go to /service/ containing the first message, the response would contain the second message and a Uri-Location of /service/0f4ef9bc/3
. The third message would be sent to /service/0f4ef9bc/3
, and the response would contain the fourth message and /service/0f4ef9bc/5
et cetera. This is never a rule, though -- in any such protocol, any server can pick completely arbitrary paths, and while the protocol may place constraints on the maximum length of the path, the client may not place assumptions on the path or read anything into it.
The server can correlate and sort the messages by structuring the addresses used for them, and the client can correlate and sort the messages by the request-response matching (through the token) as it knows to which of its own messages it is the successor.
The document draft-ietf-ace-wg-coap-eap provides an example of such an exchange.
As many constrained servers do not implement message deduplication, such a scheme (relying on POST which is not on by default idempotent) can be difficult. These implementations can be accommodated for by specifying that the client may only send a request once to each received URI, and that duplicate messages are responded to with the latest sent message. Thus, the server can forego message deduplication on the CoAP layer for these resources, and the implementation would just need to check whether the message number encoded in the request URI is the expected next (in which case it's processed normally), or whether it's the one before (in which case the request payload is discarded, and the exchange's last state is used to send the last response again). (Even earlier messages can be discarded, and answered e.g. with a 4.04 Not Found).
Q: My CoAP server is running inside a firewalled network. How can I still reach it?
Q: When should my CoAP server send an unprotected Response to an OSCORE-protected Request?
A: In its Section 8.3, RFC 8613 defines whether responses are protected or not, assuming that the OSCORE request actually underwent the OSCORE processing in the first place. In that case:
- An error in the OSCORE processing results in an unprotected CoAP error response.
- A successful OSCORE processing will result in some success/error response reflecting a successful/unsuccessful processing at the application. In either case, the response is OSCORE protected, with outer code 2.04/2.05 depending on the request having POST or FETCH as outer code.
But if the OSCORE request never enters the OSCORE processing, any processing at the server that produces a reply would in fact produce an unprotected CoAP response. This can be a success or error response, depending on the outcome of such processing.
Examples of such processing are:
-
The first-stage processing of a combined EDHOC+OSCORE request as defined in draft-ietf-core-oscore-edhoc.
If the EDHOC processing of the rebuilt EDHOC message_3 fails, the request does not proceed to the OSCORE processing (there would not even be a Security Context to process it), and the server replies with an unprotected EDHOC Error Message. This reflects an error in the EDHOC processing (not in any OSCORE processing), and should convey an error code.
-
The recognition of a deterministic phantom request used as ticket request, as in draft-ietf-core-observe-multicast-notifications when using deterministic requests to achieve cacheability of OSCORE-protected responses as defined in draft-amsuess-core-cachable-oscore.
As a case in point, see the Appendix "Example with a Proxy and Deterministic Requests" in https://datatracker.ietf.org/doc/draft-ietf-core-observe-multicast-notifications/. If the byte-by-byte matching against a stored deterministic phantom request is positive, the request does not proceed to the OSCORE processing. Instead, the server replies with an unprotected 5.03 informative response, to provide the proxy with accessible information for starting to listen to multicast notifications bound to the phantom request.
Due to the above, a client that sends an OSCORE-protected request must be ready to correctly handle the following cases:
- An unprotected success response (2.xx) is returned.
- An unprotected error response (4.xx or 5.xx) is returned, although not due to an OSCORE-processing error. Here it would be useful that the server provides good information in the diagnostic payload (even though unprotected).
Q: I'm cross-proxying to an HTTP service that uses the HTTP Authorization header, eg. with Basic authentication (user/password) or a Bearer token. How would those be transported in CoAP? Why isn't there an option number for them?
None of these is complete yet, and there should be further discussion.
A1: Don't use bearer tokens, use client certificates or CWTs instead and transport them in EDHOC (WIP) or DTLS (WIP).
A2: The credentials, no matter whether a bearer, a signed or an encrypted token, are not a property of the request, but should be set for the security context. Thus, they are established when the security context is established, or added to it later.
Q: When decomposing URIs into CoAP Options, should one simply omit a trailing slash character in the URI path?
A: No. With reference to Section 6.4 of RFC 7252, a trailing slash character in the component represents a separate, zero-character path segment (see [RFC3986] Section 3.3 ABNF) and therefore it is encoded using a Uri-Path Option of zero length. See also the filed errata at https://www.rfc-editor.org/errata/eid4895
Q: The "CoAP Content-Formats" IANA registry has a column "Encoding". Shouldn't it be "Content coding"?
A: Yes, since a CoAP Content-Format expresses the combination of a Media Type and a Content-Coding. See also the filed errata at https://www.rfc-editor.org/errata/eid4954
Q: Should't Message IDs strictly ascend to help implementations of CoAP deduplication?
A: This deviates from the original design choices, for which servers have to be ready to receive random Message IDs. See also the filed errata at https://www.rfc-editor.org/errata/eid5429 and the related mail thread at https://mailarchive.ietf.org/arch/msg/core/xNnPJKCQJnFDj64H13d_AljuB50/