Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specifying CoAP Response Codes #254

Open
JKRhb opened this issue Feb 27, 2023 · 7 comments
Open

Specifying CoAP Response Codes #254

JKRhb opened this issue Feb 27, 2023 · 7 comments
Labels
coap related to coap protocol binding Has Use Case Potential The use case can be extracted and explained

Comments

@JKRhb
Copy link
Member

JKRhb commented Feb 27, 2023

Using the HTTP binding, it is possible to specify a status code in a form with the term htv:statusCodeValue like so:

{
    "href": "/foo",
    "response": {
        "htv:statusCodeValue": 200,
        "contentType": "application/json"
    }
}

For the CoAP binding, a similar vocabulary term is currently missing. CoAP uses a specific encoding for its message codes, in this case three bits to encode the response class (3, 4, or 5) and five bits to encode the detail (00 to 31). The CoAP codes are documented in the specifications and the IANA registry using the format c.dd, e.g. 2.05 for the response code "Content". Therefore, I think there are a few options for specifying the response code in a TD form.

First, we could use a string-based value corresponding to the c.dd format, like so:

{
    "href": "/foo",
    "response": {
        "cov:responseCode": "2.05",
        "contentType": "application/cbor"
    }
}

This approach would be flexible for future additions, but creates some overhead for converting the string into the numerical representation.

A second possible approach would use two integers for expressing the response class and detail, respectively:

{
    "href": "/foo",
    "response": {
        "cov:responseCode": {
            "cov:responseClass": 2,
            "cov:responseDetail": 5
        },
        "contentType": "application/cbor"
    }
}

Here, deriving the response code is a little bit easier, I would say, since you only need to bit-shift once and perform a bitwise OR operation. However, this approach creates more overhead payload-wise, makes the form a bit more difficult to read (for humans), and is not as semantically clear. Therefore, I am leaning a bit more towards the first approach, but I am not fully decided yet.

What would be your preference? And do you see additional alternatives?

@JKRhb JKRhb added the coap related to coap protocol binding label Feb 27, 2023
@ektrah
Copy link
Member

ektrah commented Feb 27, 2023

Could you explain the purpose of htv:statusCodeValue in more detail? It's nowhere mentioned the TD specification or the HTTP protocol binding.

HTTP in RDF defines it as "The actual status code value sent by the server (Literal)." That's useful when representing an actual sent response in RDF, but I'm not sure what a client should do with this information when it's in a TD.

  • Should cov:responseCode take precedence over the response code returned by the CoAP server? That doesn't sound like a good idea.
  • Or should cov:responseCode be used as a fall-back when the server doesn't specify a response code in its response? That would never happen.
  • Or is the idea that cov:responseCode indicates the response code that the CoAP server will send in the success case? That doesn't seem to be very informative because in CoAP the success response code is always the same depending on the request method (GET → 2.05 Content, DELETE → 2.02 Deleted, etc.)
  • ...? 😕

In general, I believe a form in a TD should describe the server's capabilities and expected parameters so that the client can successfully perform the operation, not contain an RDF serialization of the messages that are exchanged in the process.

@JKRhb
Copy link
Member Author

JKRhb commented Feb 27, 2023

Thank you for your feedback, @ektrah! I stumbled upon the htv:statusCodeValue in the context of the Thing Model for the Thing Description Directory API (in section 7.3.2.4) and therefore wondered if an equivalent should also be specified for CoAP. You are right that a consumer would not actually need the vocabulary term, but maybe it could be useful to describe the API provided by a Thing? If not, maybe the use of the htv:statusCodeValue also requires some more discussion.

@JKRhb
Copy link
Member Author

JKRhb commented Mar 26, 2023

I think this issue will become relevant for the next version of the Discovery specification which is supposed to include a CoAP API for the Thing Description Directory (see here).

@ektrah
Copy link
Member

ektrah commented Mar 27, 2023

I see. So, the target audience for htv:statusCodeValue is not the client or the server but actually the developer who implements the API on the server. And the intention is to give the developer an API specification that tells them what HTTP status code and payload format to return in which case.

Let's take a concrete example:

        "retrieveThing": {
            "description": "Retrieve a Thing Description",
            ...
            "forms": [
                {
                    "href": "/things/{id}",
                    "htv:methodName": "GET",
                    "response": {
                        "description": "Success response",
                        "htv:statusCodeValue": 200,
                        "contentType": "application/td+json"
                    },
                    "additionalResponses": [
                        {
                            "description": "TD with the given id not found",
                            "contentType": "application/problem+json",
                            "htv:statusCodeValue": 404
                        }
                    ]
                }
            ]
        },

This tells the developer to implement an action that allows a client to retrieve a TD using a GET request to /things/{id}. In the success case, the developer should let the action return a 200 (OK) response with content type "application/td+json". In case the TD with the given ID was not found, the developer should let the action return a 404 (Not Found) response with content type "application/problem+json". Right?

From the client's point of view none of this matters. The client recognizes success or failure by the status code, and the reason for failure is specified in the Problem Details payload. If a client receives a 404 (Not found) response with content type "application/problem+json", it does not necessarily mean that a TD was not found; it could also simply be that the server no longer offers the API. So the conclusion is one-way only: If condition is met, then send status code and content type. But not: If status code and content type received, then condition is met.

If you do this consistently, you accumulate a whole series of error conditions that have to be repeated for each property, action and event: If the client is not authorized to retrieve the TD, then 403 Forbidden. If the TD cannot be delivered in the format requested by the client, then 406 Not Acceptable. If the client made too many TD retrieval requests too fast, then 429 Too Many Requests. And so on.

The problem is that here the HTTP API is described as an RPC interface. It would be better to describe it in a RESTful way: Specify that for the TD with ID {id} there is an HTTP resource at /things/{id}. Boom. Done.

In the success case, the GET request results in a 200 (OK) response with the representation of the resource. If the resource cannot be found, then 404 Not Found. If the client is not authorized to retrieve the resource representation, then 403 Forbidden. If the resource representation cannot be provided in the format requested by the client, then 406 Not Acceptable. This is already defined exactly like that by HTTP and it doesn't have to be repeated over and over again for every property, action and event.

The same applies to CoAP.

@JKRhb
Copy link
Member Author

JKRhb commented Feb 1, 2024

It's a bit late, but thank you for your detailed response, @ektrah! I think you have explained very well that the response and additionalResponses fields address a different use case that does not have to be covered by "regular" TD which should also be taken into account by the current use case discussion.

While the TD Directory API specification illustrates that there is in fact a use case for "server-side" vocabulary (e.g., HTTP status codes), I think one shortcoming of the current TM specification is that you always need to take over this information into TDs instantiated by the respective TM, even though – as you've shown – it is not needed by a consumer.1

So I think we would need, for instance, a way for TMs to label fields at the affordance level as optional or state that they should be excluded during the instantiation process. Furthermore, I think we could even consider moving response and additionalResponses out of the core vocabulary into extensions, as this concept probably does not make that much sense for a protocol like MQTT, for example.

Footnotes

  1. In the Scripting API, for example, both fields are not used at all (although response is mentioned in this example).

@JKRhb JKRhb added the Has Use Case Potential The use case can be extracted and explained label Feb 1, 2024
@JKRhb
Copy link
Member Author

JKRhb commented Aug 19, 2024

I've just opened w3c/wot-thing-description#2042 to discuss adding the possibility to make more fields optional in TMs (i.e., allowing for not taking them over into the resulting TD). This way, the implementor of a TM could choose to simply omit information like status codes if it is not necessary for the consumer to know. Do you think that with such a mechanism in place, it would make sense to add CoAP response codes to the CoAP Binding Template as well? Or could that even be considered a separate/additional vocabulary to the one we are currently defining?

Note that there is now a discussion on how to handle response and additionalResponses in the WoT Scripting API taskforce, so the general assumption is that a Consumer needs to take that information into account when interacting with a Thing. It seems to me as if we might also need to have a more general discussion about these two fields at some point in the TD task force.

@egekorkan
Copy link
Contributor

It seems to me as if we might also need to have a more general discussion about these two fields at some point in the TD task force.

This is one of the points to be tested in the plugfest as well since we seem to lack implementation experience for consumer applications that leverage scripting API like thinking

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
coap related to coap protocol binding Has Use Case Potential The use case can be extracted and explained
Projects
None yet
Development

No branches or pull requests

3 participants