Open egekorkan opened 7 months ago
I guess more generally we should suggest to always request the content type if more than 1 content type is available for a declared endpoint+verb. We should advise it even more strongly on the subprotocol specifications if they could be multiplexed.
I think this question:
{
"href": "properties/result",
"contentType": "text/event-stream", // should it be application/json ?
"op": "observeproperty",
"subprotocol": "sse"
}
It deserves its own issue.
To be noted:
Otherwise, if res's status is not 200, or if res's
[Content-Type](https://html.spec.whatwg.org/multipage/urls-and-fetching.html#content-type)
is not[text/event-stream](https://html.spec.whatwg.org/multipage/iana.html#text/event-stream)
, then fail the connection.
The contentType has to be text/event-stream. So it is implicit in subprotocol:sse
and it is an hard discriminant between http-subprotocols.
This is implemented in WebThings Gateway (Producer) and Krellian Cloud (Consumer).
WebThings Gateway always exposes readproperty
, writeproperty
and observeproperty
operations on a given Thing using the same endpoint URL. The server differentiates between requests based on HTTP method and Accept header (i.e. standard HTTP Content Negotiation). The Thing Descriptions expose separate Forms for ["readproperty", "writeproperty"]
and ["observeproperty", "unobserveproperty"]
operations, but it doesn't actually include a contentType
member in either Form because application/json
is the default and text/event-stream
is implied by the subprotocol
member being set to sse
.
The same approach can be used to differentiate between endpoints for readallproperties
/writeallproperties
and observeallproperties
/unobserveallproperties
. E.g. this example taken directly from the WoT Profiles specification:
"forms": [
{
"op": ["readallproperties", "writemultipleproperties"],
"href": "properties"
},
{
"op": ["observeallproperties", "unobserveallproperties"],
"href": "properties",
"subprotocol": "sse"
},
{
"op": "queryallactions",
"href": "actions"
},
{
"op": ["subscribeallevents", "unsubscribeallevents"],
"href": "events",
"subprotocol": "sse"
}
]
We are not very clear how one would differentiate different forms when there is the same HTTP endpoint but one form has
readproperty
and the other one hasobserveproperty
. It is not possible to have that in longpolling but it is possible in sse (more on it later). More specifically, we can have the following property:This is technically possible since the Consumer can set the Accept header to
"text/event-stream"
and the Thing can differentiate based on the header and deliver correct value or stream. In this case, we should probably have the second form looking like the following:I think that this header should be a default value when there is
subprotocol:sse
since the EventSource spec says that it is a MAY and not a MUST to send this header (see step 10 at https://html.spec.whatwg.org/multipage/server-sent-events.html#the-eventsource-interface under the green box). Also, it is not clear how this should look like in code. In node-wot, HTTP binding simply uses the event source library at https://github.com/eclipse-thingweb/node-wot/blob/master/packages/binding-http/src/subscription-protocols.ts#L112 . The library however allows headers to be passed at https://github.com/EventSource/eventsource/blob/master/lib/eventsource.js#L35 .Maybe this is an implicit knowledge (also see https://eclipse.dev/ditto/httpapi-sse.html), but I got into the details for the first time. We should at least document this but more behavior description would be nice in this case.