-
Notifications
You must be signed in to change notification settings - Fork 3
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
Requirement: Proposal (2) for standardized message envelope for requests, responses and notifications #34
Comments
I suggest renaming requestID to correlationID. This would enhance functionality, especially for subscriptions to property changes or events. Including a For instance, in a WebSocket client, you might return an individual reactive stream for each (property change or event) subscription. For example a stream could be implemented with a reactive programming library like ReactiveX. And the websocket client does not return a single stream of notifications, but could separate notifications into multiple individual streams. |
Yes, good feedback and the streaming use-case is really nice. I'll change it in the hiveot documentation and code and add it to notifications as well. I just completed implementing this proposal in hiveot as an application layer. The http/wss/mqtt transports maps from the three message types to the specified message types for that transport. On the hub the mapping is reversed and further processing uses the three message types again (so-far only implemented http/sse). I love the simplicity of the approach! Some observations sofar:
It looks to me that the protocol bindings got overly complicated for what is essentially a transport problem. This brings it back to what it essentially is. Next steps:
|
But from a protocol level, I still miss acknowledgements. |
sorry to crash in, I have been chewing on how to implement something like this for Iot via WoT with webRTC + webSocket(for any messaging that needs more reliability than webRTC). I would like to contribute here too eventually. @RobWin, you mentioned the use of libraries like ReactiveX, would you happen to be aware on any wc3 standards for similar functionality?
would you happen to be aware on any wc3 standards for similar functionality? @hspaay, about the following response message fields:
shouldn't the sender of a request be able to determine the operation from the correlationID in a response only. I am under the impression the correlationID is being tracked/stored by the sender along with the operation. so why send "operation" again? i ask because i am interested in using minimal payloads for webRTC's MediaStreamTrack & data channels. |
This is solved by making subscription,observations,and writeproperty operations a request. All requests are acknowledged using their correlation ID. |
Yes you are correct. operation in response can be optional. The reason it was included is that I found it useful to assist in testing and debugging. You are right though, the protocol doesn't need it. I'll change it to optional in the proposal. (ps: the media stream track looks very interesting. I'll experiment with support for it in hiveot once I have some more time) |
@unit9a I'm using Kotlin Flows on client and server side, not ReativeX. But the concepts are quite similar to RX or Project Reactor. There is something like https://developer.mozilla.org/en-US/docs/Web/API/WebSocketStream |
@hspaay the media stream track API is something i am exploring for industrial Iot applications. it closely related to the draft standard for WebCodecs. it would would encourage the use of WoT and other web standards in a lot of applications. However, i don't think webCodecs will be ratified any time soon. @RobWin I'm a excited about rRocket.io, THANKS SO MUCH!!!. Fyi, the RSocket Protocol Specification Community Group seems dead and i could not find a wc3 draft or standards page. And I hope WebSocketStream is combined with rRocket.io at some point |
@hspaay this reminds me of json-rpc 2.0. do you mind if I explore what a Json rpc version of this looks like via protobufs? do you even think json rpc is relevant at all? |
@unit9a please go ahead and explore. Always interesting to gain more perspectives. On the application side I found it helpful if the protocol matches the vocabulary and meaning of the application as minimalistic as possible. This is why the proposed message envelopes uses fields like operation, thingID, and (affordance) name, with the message types for request, response and notification. On the transport layer below this, the more the merrier. Encodings like json-rpc, bson, protobuf, capn'proto with matching transports like websockets, gRPC, mqtt, and so on, are all good to support. This is at least my thinking with this proposal. Looking forward to see what you have in mind. (ps: lets also not lose sight of what @benfrancis has in mind for the websocket proposal. This issue is merely my own 2c's based on insights gained implementing the http, sse and proposed wss bindings) |
@unit9a Yes, seems there was no big interest into a reactive streams capable application protocol at w3c.
Means for every request (subscribe, unsubscribe, observe, unobserve, writeproperty) there is a response without output as a acknowledgement? What would be the status? |
That is correct. The status can be completed on success, or failed if the request isn't accepted for whatever reason. The error field in the response can contain the error message on failure while output optionally contains any further details. Btw, if no acknowledgement is desired (can't think of a good reason) then the correlationID can be left empty. The part I'm still unclear about is how to include 'alternative results' that can be specified in Forms for actions, but that is a different topic. |
@hspaay & @benfrancis, the use webRTC data channels should be the same as or similar to websockets per: https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel#instance_properties
regardless, i will prioritize using webSockets. |
w3c#34 for comment w3c#34 (comment)
@hspaay my idea so far. transport layer concept: equivalent json rpcassumption: this proposed web-thing-protocol (WoTP) is an application goals
my other assumptions/ideas conversion of json-rpc member name
syntax
Request messages fields
example 1:
Notification messages fieldssame as a Request except "id" is moved to "params" as "messageID"
Response messages fields
example 2:
|
@hspaay when using webSockets,
@RobWin, i will start with WebSocketStream but will eventually support use both rsocket.io |
@benfrancis sequenceDiagram
autonumber
participant wot1 as thing1
participant wot2 as thing2
critical Negotiate "@context for rpc session"
wot1->> wot2: { wotp:"0.1",<br>params = <@context value in example 1>}
alt success
wot2->> wot1: { wotp:"0.1", result = {wotpSessionID: <short uuid>, contextInfo:{<selected context>}}}
Note right of wot1: both WoT entities map the <wotpSessionID> to @context value for the session
par thing1 messages
wot1->> wot2: { @wotp: "<wotpSessionID>"... }
and thing2 messages
wot2->> wot1: { @wotp: "<wotpSessionID>"... }
end
else fail
wot2->> wot1: { wotp:"0.1", result :{error: "no supported rpc context...", output: ...}}
end
end
|
Yes there is a difference between a connectionID and senderID:
Hope that explains it. |
@unit9a I'm unclear on what WoTP is and what problem it is intended to solve. For example, what is the thinking behind using "corrID" instead of "correlationID". That aside I don't see a problem with the mapping you describe other than it looks like doing the same thing with different names. Doing the same thing is good as it makes mapping easy btw. |
"WoTP" was meant as an acronym for this"Web of Things Protocol" draft. i just wanted something short to type.
Good catch, they are supposed to mean the same thing but i did not make that clear. so i guess more clear & updated mappings are:
yeah, that is what I wanted to convey |
follow up, #34 (comment) for some simplification, I realized that from the perspective of json-LD: "@context" functionally does the same thing as "type", "json-rpc" and "wotp".
so the purpose of Negotiating "@context for rpc session" just amounts to establishing a short string identifier for the schema of response, request, and notifications to be used for subsequent messages. so rather that deviate from the json-rpc spec, all the "WoTP" stuff i proposed.
could be simplified down to:
@hspaay do you think this makes it even more clear the same thing is being done? Also what do you think of "@context" being use to establish the schema of all possible WoT interactions for the remainder of the connection session between consumers, Thing agents, hubs, and gateways. kind of like a json-LD version of an openAPi spec. |
more simplification of my json-rpc transport layer
so using rpc extensions, the Request method/operation names gain a prefix of: "rpc."
becomes:
|
Somehow I have the feeling that this issue was hijacked :) |
I like this version much better than the previous/existing strawman proposal of webthing protocol. There must be a separation between the "type" and the "operation". |
I would appreciate if somebody here also starts accounting pre-encoded binary payloads into the message. In JSON, I heard its easier to encode base64 strings, but I think the use of a generic binary payload in a broader sense would be very useful. This is similar to extracting the buffer value from |
@RobWin how? this is just a transport concept with json-Rpc. complying with:
@RobWin are you talking about inserting @hspaay web thing protocol proposal's fields/datums in into the websocket message event class and life cycle? if so, then I apologize for not understanding and raising the json-rpc-stuff here. my json-rpc idea is only meant to be a transport layer for this web thing protocol proposal's data, One that is encoded as the raw binary payload of the websocket message while still being compatible with current json-rpc use. @RobWin & @hspaay should i move the json-rpc/json-LD transport idea to its own issue? Also, what do you all think of a pure json-LD representation of this web thing protocol proposal's request, reponse, and notification messages?
agreed! @RobWin pointed me to https://rsocket.io/ and its use of binary payloads is webSockets. this approach is was i want to pass my json-rpc/json-LD objects into. Also, I came across this in a stackoverflow comment: this, tracks with my experiences, so i dont think binary offers any significant advantage outside of IoT embedded systems constraints. But that still makes it a useful option to have.
i think @hspaay already addressed with:
or am I* not understanding you mean? in json-rpc the separation is done the objects structure. |
@unit9a I think that the JSON-RPC discussion should be moved out of this issue. Perhaps it could continue in the WoT Discord channel until someone expresses interest in creating a dedicated Sub-Protocol Community Group. The scope of this Community Group is outlined in the Web Thing Protocol Charter and includes:
Out of scope are:
I believe we should maintain a narrow focus within this Community Group's scope and discussions. While I also see the appeal of reusing the Web Thing Protocol as a sub-protocol for AMQP or MQTT bindings, this is beyond the current scope of this community group. @benfrancis It might be worth clarifying in the charter document what is meant by "internet protocols" to set clearer boundaries. As for the HTTP Profile, it is detailed in the HTTP Basic Profile. It follows a RESTful design and does not utilize JSON-RPC. In my understanding, JSON-RPC would constitute a distinct sub-protocol (or profile?) within the HTTP protocol binding. That said, we should aim to limit the number of profiles or sub-protocols for HTTP to preserve interoperability. Looking forward to further discussions on this topic in the appropriate channels! |
This is a great discussion. It highlights there are concerns on messaging, transport and encoding levels. Thank you all for your insights. However, for the sake of keeping this specific discussion on track it is probably good to split the transport and encoding from the messaging issue as @RobWin pointed out. @unit9a. This issue was originally intended as part of feedback to the websocket strawman proposal by @benfrancis . It offers a simpler alternative to the current message formats that are in the proposal. The idea is that it can evolve to an application level protocol with various transports and encodings, as your examples show, requires though that the message format is adopted as a stand-alone application protocol. This is definitely out of scope for the strawman proposal which is a subprotocol of the WoT http binding. I don't want to lose this discussion though as it is valuable but it should probably move to another issue, outside of the strawman proposal. @benfrancis is an application protocol with transport protocols and encodings like discussed here in-scope for the web thing protocol discussion group? If so, should it be considered a separate proposal? What is the process for this? |
On the issue of generalising the message payload format across message types I can certainly see the argument. As a Software Engineer I understand the instinct to abstract away similar features into a common parent class/schema, which is something we are literally trained to do (e.g. through object oriented programming). However, I want to state that the Web Thing Protocol is not intended as a general purpose request/response or publish/subscribe protocol. It is designed for the very specific purpose of communicating with Things on the Web of Things, using the set of WoT operations and WoT native terminology. It was therefore a conscious design decision to directly map WoT operations onto message types and not to try to design another general purpose protocol. If that's what someone is looking for then there is a very long list of existing WebSocket sub-protocols which try to achieve just that https://www.iana.org/assignments/websocket/websocket.xhtml I have more to say on this topic and will work my way through all of the responses because I think this is an interesting discussion with some specific points I would like to respond to, but I wanted to reply to your top level post first of all. To some specific points in your initial post: @hspaay wrote:
If that is what your proposal is about then I would suggest this is the wrong place for it, it should be proposed in https://github.com/w3c/wot-binding-templates/. However, I don't personally think this payload format can or should be adopted by all protocol bindings. Many protocols have existing fields for many of these members, which is the reason that the vocabularies in protocol binding templates exist - to map WoT concepts onto fields in messages in existing protocols.
I think this is the wrong abstraction. The Web of Things models interactions in terms of "properties", "actions" and "events". Some protocols use a request/response pattern, some protocols use a pub/sub pattern, and some use a combination of both or something entirely different. Protocol bindings map WoT operations onto messages in a given protocol.
I think you're going to have a very hard time pushing this "application protocol" onto all the other protocol bindings. Whilst you could argue the payload format makes sense for a raw TCP socket like WebSockets, it doesn't make sense for most of the other protocols used by WoT because it duplicates a lot of the features of existing protocols. For some protocols it would add a redundant extra wrapper around messages and for others it wouldn't be possible to implement at all.
This is not strictly true. The HTTP Webhook Profile assumes that Things are clients and Consumers are servers for example. The terms Consumer and Producer were used in the WoT specifications instead of client and server for this very reason. However, it is true that Thing Descriptions describe how to interact with a Thing using Forms which require URLs for endpoints. This does make it very tricky to describe Things which clients rather than servers.
This is really a wider issue for the Web of Things (the Thing Description specification in particular), rather than the Web Thing Protocol. Defining a Web Thing Protocol which can flip the client/server roles does not solve the fundamental problem of how to describe devices in a WoT Thing Description.
See w3c/wot-thing-description#892 FYI There is some work under the new WoT Working Group charter around querying time-series data.
An API for managing a collection of Web Things is explicitly out of scope for the Web Thing Protocol and is already covered by the Directory Service API in the WoT Discovery specification. |
Thank you for a very well thought out response @benfrancis. While I might not share the same perspective about this as you do, it is clear that you know exactly what you want to achieve. It looks like this issue has no chance of being adopted in the Strawman proposal, so I won't persue it here any further. This issue did provide very useful and insightful feedback for which I'm grateful to all commentors. It would be nice IMHO to keep it open as a useful discussion until it is addressed elsewhere. I will look into defining a separate proposal elsewhere for a WoT application protocol with this message format and the mentioned multiple underlying transports. Let others decide whether they find it useful to them. I'll post the link once it becomes clear where this should go instead. Maybe @egekorkan can point in the right direction. In the meantime @benfrancis I'll continue with full support for the strawman proposal as it evolves and attempt to provide an implementation in hiveot. |
@RobWin wrote:
Just curious, why would changing the name enhance the functionality? I think we have a general consensus so far that some kind of requestID/correlationID would be a good idea, but I do have some open questions about how that should work when subscribing to events and observing properties. See #31
I don't have experience with ReactiveX and I'm not exactly sure what you mean by multiple individual streams. Is your intention that a Consumer should be able to have multiple subscriptions to the same event at any one time, with each subscription identified by a unique ID and individually unsubscribable? If so what benefit would that bring which justifies the added implementation complexity of managing multiple subscriptions per Consumer? See #29 @hspaay wrote:
What do you mean by "mapping" to a "transport"? How do you map a notification to SSE for example? Are you sending the whole message envelope defined above inside the
I've mentioned before that I started out with the approach of using operation names to differentiate message types but found the need for other message types (like
Would a
Surely you still have to map operations onto messages and back, the format of the messages is just different...
Why did you need multiple form entries for each operation before? Have you seen the example Thing Description in the strawman proposal which has one form per interaction affordance? That is actually one of the benefits of the WebSocket sub-protocol compared with a declarative HTTP binding for example.
Are you aware that in a Thing Description the forms member of an @RobWin wrote:
See #29 @unit9a wrote:
I can definitely see the similarity with @hspaay's proposal (except that in JSON-RPC notifications usually work in the opposite direction). I can certainly imagine something that looks like the WoT Scripting API implemented over JSON-RPC, but I'm not personally interested in that as a design for similar reasons to those given above. I would rather not abstract everything as a method. @VigneshVSV wrote:
Why?
This is one of the limitations of JSON, and yes base64 encoding values as strings is a common solution to that problem. There are alternatives like BSON, CBOR and Protocol Buffers which don't have this problem. However:
I'm not inclined to switch away from JSON for this reason alone, since its ubiquitous support brings a lot of benefits and it being the default serialisation assumed in Thing Descriptions makes it the obvious choice. That said, the charter does allow for the "Evaluation of other potential Web of Things sub-protocols (e.g. for CoAP)". I can imagine a future variant of the Web Thing Protocol using CoAP + CBOR for constrained devices that would struggle with WebSockets + JSON, but that is not the current focus. @RobWin wrote:
I think it's clear that an "internet protocol" is anything that works over IP. Much trickier to define is a "web protocol". A broad definition would be anything with a URI scheme registered with IANA, but I tend to have a much stricter view and haven't yet come across anything other than HTTP and CoAP that I would describe as a web protocol. Even WebSockets is stretching the definition of "web" for me, but that's another story. JSON-RPC can be used used as a sub-protocol of both HTTP and WebSockets so arguably does fall within that scope, it's just not something I'm personally interested in. It could make an interesting protocol binding template though.
I strongly agree with this. @hspaay wrote:
👍 |
@hspaay wrote:
No. But let me explain why because I think it's important. The Web of Things is basically designed to be everything-agnostic. Protocol agnostic, serialisation format agnostic and programming language agnostic. If you wanted to you could create a valid "Web Thing" which communicates entirely using animated GIFs over the IRC protocol! Depending on who you listen to this is either its biggest strength or its biggest weakness. The benefit of this approach is that it theoretically makes it possible to describe any brownfield device using any existing IoT protocol and have it be a valid Web Thing. The downside of this approach is that any given WoT Consumer can only communicate with a tiny subset of all the possible Web Things in the world. Imagine a 2-dimensional matrix of all the possible protocols and payload formats and the proportion of combinations supported by a given Consumer implementation will be tiny. Now expand this by n dimensions to allow for the other WoT extension points like security mechanisms, discovery mechanisms, link relation types and semantic contexts. Now you have a serious interoperability problem. The mission of this community group is to "define a common protocol for communicating with connected devices over the web, to enable ad-hoc interoperability on the Web of Things." The ideal outcome would be a single protocol that all greenfield WoT implementations can opt into using in order to benefit from complete out-of-the-box interoperability. As soon as you start abstracting things into layers and talk about alternative transport protocols and encodings you have immediately fragmented that landscape again, which is counter to the mission of the group. The charter takes a slightly more pragmatic view than this by allowing for both an HTTP sub-protocol and WebSocket sub-protocol (because HTTP has some significant limitations for IoT use cases), and for the exploration of other potential WoT sub-protocols "e.g. for CoAP" for use cases where the other two options are simply not possible to use. Apart from that, the main thing that concerns me about your proposal in this issue is that by generalising into requests, responses and notifications you are basically re-inventing HTTP+SSE (or CoAP+Observe) over WebSockets. The Web Thing Protocol WebSocket sub-protocol is intended for the very specific purpose of communicating with connected devices over the Web [of Things], not a general purpose application protocol for the web, which is why my strawman proposal directly maps WoT concepts onto messages. Genuine suggestion: Rather than try to re-invent HTTP+SSE over WebSockets, how about you (or we) take the underlying features we need to the IETF task force that works on the HTTP protocol and propose them for the next version of HTTP? If the next version of HTTP supported persistent connections, multiple requests and responses over the same socket and messages pushed from the server to the client then we arguably wouldn't need a WebSocket subprotocol. We could just define a default HTTP/4 (?) protocol binding instead. I would actually prefer that to having separate HTTP and WebSocket sub-protocols. HTTP/2 has a push feature but which doesn't really support our use cases, and HTTP/3 supports multiplexing over QUIC. But as far as I can tell not even HTTP/3 does everything that we need. In the meantime, we have JSON and WebSockets. |
I think the the term This distinction is particularly relevant for scenarios like subscriptions and property observations, where a single request may lead to multiple or continuous responses over time. For instance, event messages in a subscription or propertyReading messages in an observation context are not one-time responses but part of an ongoing stream, making correlationId a more accurate descriptor. Moreover, the name correlationId is versatile and can support diverse communication patterns:
But this implies that "request" messages would also have a dedicated correlationId field, distinguishing it from the messageId, which is used to uniquely identify individual messages. The correlationId serves to group related messages together, providing a clear link across different messages, while the messageId identifies each individual message within that group. AMQP it is called
No, my intention is that a Consumer can have subscriptions to multiple events (or observations to multiple properties), each subscription resulting in a dedicated (reactive) event stream that can be individually canceled (unsubscribed from). |
Thank you for elaboration Ben. You've mentioned this before and unfortunately I don't agree whether this is true and whether this is even relevant. The proposed messages are clearly application level as they are tailored for messaging related to things with properties, events and action affordances. This is not a general purpose message format. The websocket messages defined in the original proposal are very similar to this approach. Instead of defining a message per operation (and sometimes a separate message for its response), this proposal groups messages by their intention (request, response, notification). The payload is also similar but instead of changing the member names to match the affordance (event, property, action) it uses 'name'. In both cases you have to decode the message to determine further processing. I don't see how this even gets close to reinventing http/sse or coap/observe over websockets. The application should not be driven by the underlying protocol but the use of the protocol should be driven by the need of the application. Top down, not bottom up. It really doesn't matter what features the underlying protocol support and it whether they are all used. What matters is that a WoT application can invoke an action, write a property, get a response and receive notifications. These application level concerns are expressed in the proposed messages. I hope this kinda helps explain my perspective. I'll continue exploring both points of view. |
@RobWin wrote:
Just checking, should "request" read "response" here? Is the idea that request messages only contain a |
No, I meant that some messaging protocols allow both a unique message ID and a correlation ID even in request messages. Not only in response messages. These fields serve distinct purposes:
For example, in a "multiple requests, single response" pattern, the correlation ID could be used to group multiple request messages under a shared context, while each request retains its own unique message ID. In such messaging protocols, the consumer of the request typically copies the correlation ID from the request into the correlation ID field of the response, instead of using the message ID. This ensures the responder maintains the context established by the requester, enabling the requester to match responses to the original requests. |
@hspaay wrote:
OK fair enough, that is probably an exaggeration and you are right that there are lots of application specific members in your proposed message format. I think what I'm trying to get at is that what I set out to do was to create a protocol with a very direct representation of WoT operations as messages, without needing a binding to map those operations onto the terminology and concepts of an existing protocol. The generalisation of "requests", "responses" and "notifications" proposed in this issue feels like an additional layer of abstraction above WoT concepts. In particular, although "response" is a term used in the WoT specifications (e.g. the E.g. is the Having said all of the above, I do like the idea of having an "operation" member which directly takes an operation name from a Thing Description, and a consistent "name" member across interaction affordances (although that one is a bit less clear). I don't like property values being referred to as "input" and "output" though, because those terms are only used in relation to actions in the WoT specifications. I will give it some more thought. |
@RobWin wrote:
Ah OK. I think in all current WoT use cases the I see the rationale, but I am also reluctant to require three different ID members in every message if they are not needed. |
Why 3? You meant the thingId as well? |
Yep |
@benfrancis wrote:
I'm honored that you think I can be of any help there. My skills at the bit level have deteriorated over time unfortunately and my focus is on hiveot. @RobWin seems to be much better at this though so maybe he would be able to help 😄 @benfrancis wrote:
Yes, I don't see a use-case to always require the messageID, so IMHO it can be optional in requests. @RobWin has done an excellent job describing use-cases in #35. We can probably continue the messageID discussion over there.
Chuckle 😄
Yes, and the strawman proposal does exactly that. Can't argue on that. This hiveot proposal doesn't deviate that much on the request/notification side other than a minor generalization.
The lack of a clear specification on action acknowledgement is true, but to me that is more of an omission than intent. The same goes for acknowledgement of subscriptions and property write request as discussed elsewhere. Hiveot needs these to function properly so I have no choice other than support it somehow. My choice is to incorporate in the messaging in the hope that WoT 2.0 will take notice and adopt some of these ideas. This doesn't take away from the use of these messages for things that are defined in the TD, so nothing lost. It opens the door to standardization of these improvements in the future. Hence this proposal. Bottom line is that I can't just say, sorry no ack because the spec doesn't mention it. I'm also looking at the gateway/hub use-case which is quite a bit more demanding than simply consumer->Thing. Wrt terminology overloading. 'Response' is widely used in many protocols so I wasnt thinking it to be a problem. I'm open to renaming though if it helps make things clearer.
In this proposal the action status message is replaced with a response message, which has a status field. There is no need for an actionStatus message or propertyReading message, which can be considered unnecesary artifacts. The combination of message type 'ResponseMessage' and the original operation is all that is needed. I haven't run into a problem with this. The hiveot http binding (golang) implementation in hiveot supports both an immediate response from the http and async responses via SSE. In golang this is easily done using channels. Direct response is posted on the result channel as are asynchronously received responses. The application waits for a response by listening on the channel and therefore doesnt care how it gets there. The 'status' field indicates if more responses are to be expected. Once status is completed the last response has been received. Clearly this needs much better documentation that I've provided thus far. Sequence diagrams for various use-cases should clarify the simplicity of this approach. This is in the works. Anyways, I hope this helps explaining this can actually work. If a little demo down the road would help, along with documentation, I'd be happy to present. In the meantime, I'm giving the full support to the strawman proposal. This hiveot proposal is in my eyes an evolution, which can be included or be a separate protocol. Its all good. Thanks for the feedback and comments Ben and Rob. |
@hspaay why is there no dedicated Error message type? I am not opposed to how it is now. can you give an example of how a response object with both error, output fields can be handled? my assumption is that:
having a dedicated error response is more explicit but might not be as efficient. does it make for a better developer/debugging experience? just curious and learning. |
I’m not referring to this specific proposal here, but just to inform you, the Web Thing Protocol Strawman Proposal adopts dedicated error messages aligned with the Problem Details for HTTP APIs specification, a widely used standard for HTTP APIs. The WoT HTTP Profile also utilizes this approach, as detailed in Error Responses in WoT HTTP Profile. One could argue that the RFC is too complex for most use cases. |
@unit9a wrote:
The motivation is that an error is also a response. The response has a status field with predefined values, one of them is 'failed'. If the status field holds failed then the error field holds the error title and the 'output' can hold additional detail. I'm on the fence whether the 'error' field is even needed and whether the output field should contain the error if status is failed. The only reason that wasn't done is that the http error handling recommends a separate details field, so there are use cases where more information is useful. It is not the intent to implement RFC9457 btw. It is of course possible to define a separate error message as the strawman proposal does here. Nothing wrong with that. For the proposed minimalistic application protocol this isn't needed though as explained. |
[Update 2025-01-02: changed requestID to correlationID as per @RobWin feedback]
[Update 2025-01-02: changed operation in ResponseMessage to be optional as per @unit9a feedback]
This is proposal 2 draft for standardizing the message envelopes for all protocol bindings, including the websocket binding. Adopting this approach would make the websocket protocol binding a trailblazer and would serve as an example for all future protocol bindings.
HiveOT is in the process of implementing this proposal at the application level and currently maps to existing protocol bindings as the transport.
Note, I realize this is a rather different approach to constructing messages so I don't really expect it to be adopted unless it garners a lot of support. I've documented it here in case there is an actual interest or otherwise for future prosperity.
Rational
Protocol bindings in WoT serve two different purposes. Provide a transport and act as a (partial) application protocol for handling properties, events and actions. These are different concerns that can be separated. Separating the application protocol from the transport enables defining a single application protocol that can be used on any transport. This in turn would simplify adoption and improve interoperability.
The WoT protocol bindings does not describe how Thing agents connect as a client to a hub or gateway. Instead the assumption is that all Things run a server. This is too limited of a view. Hiveot is a Hub where Thing agents are clients to the Hub just like consumers. WoT does not describe the interaction for these agents.
This proposal describes a messaging format and behavior for protocol bindings that address the above issues.
Message Types
There are three message types: Request, Response and Notification with corresponding message envelopes. All WoT interaction that takes place between consumers, Thing agents, hubs, and gateways can be described using just these three messages.
Messages are identified by their type and operation. Operations are those defined in the WoT TD 1.1 specification and are open to extensions using @context. Response messages include the operation of the request they are a response to and thus identify the response payload.
Underlying transport protocols such as HTTP, SSE, Websocket, MQTT, etc mere act as pipes to deliver these messages in the most efficient way possible.
Request messages
The purpose of the request message is for a client to send a request for an operation on a thing. Thing agents are required to send a response when a request is received.
The following operations are considered to be requests:
The request message defines the following fields:
Response messages
Responses serve to notify a single client of the result of a request.
Response message payload is determined by the request operation. Therefore the request operation is included in the response:
Notification messages
Notifications serve to notify subscribers of a change as identified by the operation, thingID and affordance name. Notifications are not targeted to a single receiver but intended for subscribers (or observers).
All notifications use the same message format as implemented in NotificationMessage struct (golang, JS, Python). Protocol bindings can use this envelope directly or map from their protocol equivalent to this message format.
The following operations are considered notifications:
Behavior
Any client can publish a request. They can choose to wait for a response message or handle the response asynchronously. This is dependent on the client implementation.
The server can be an agent for a thing or a hub or gateway.
Hub or gateways will forward requests to the Thing agent. If the agent is not reachable at this point they return the error response or a pending response if there is support for queuing requests.
Thing agents will process the request. They SHOULD send a response with one of three statuses: running, completed or failed. If a request is received without a request ID then no response is sent.
If a 'running' response is send, agents MUST also send a completed or failed response once the operation has finished.
If a hub or gateway is used then the response is received by the hub/gateway, which in turn forwards it to the client that sent the request. If the client is no longer reachable then the response can be queued or discarded, depending on the capabilities of the hub or gateway.
Clients will receive a response message containing the original correlationID, the payload an any error information. Client implementations can choose to wait for a response (with timeout) or handle it as a separate callback.
Agents can sent notifications to subscribers. The notification message includes an operation that identifies the type of notification. A hub or gateway can implement their own subscription mechanism for consumers and ask agents to send all notifications.
The text was updated successfully, but these errors were encountered: