feat: Add support for StreamingHTTPChannel2023 notifications

* feat: initial StremingHTTPChannel2023 notifications

Co-authored-by: Maciej Samoraj <maciej.samoraj@gmail.com>

* test: unit for StremingHTTPChannel2023 notifications

Co-authored-by: Maciej Samoraj <maciej.samoraj@gmail.com>

* test: integration for StremingHTTPChannel2023 notifications

Co-authored-by: Maciej Samoraj <maciej.samoraj@gmail.com>

* emit initial notification on streaming http channel

* fix linting erros

* ensure canceling fetch body in integration tests

* extract defaultChannel for topic into util

* add documentation

* Apply suggestions from code review

Co-authored-by: Ted Thibodeau Jr <tthibodeau@openlinksw.com>

* only generate notifications when needed

Co-authored-by: Maciej Samoraj <maciej.samoraj@gmail.com>

* test: set body timeout to pass on node >21

Co-authored-by: Maciej Samoraj <maciej.samoraj@gmail.com>

* address review feedback

* remove node 21 workaround

* add architecture documentation

* Apply suggestions from code review

Co-authored-by: Joachim Van Herwegen <joachimvh@gmail.com>

---------

Co-authored-by: Maciej Samoraj <maciej.samoraj@gmail.com>
Co-authored-by: Ted Thibodeau Jr <tthibodeau@openlinksw.com>
Co-authored-by: Joachim Van Herwegen <joachimvh@gmail.com>
This commit is contained in:
elf Pavlik
2024-05-22 00:58:26 -06:00
committed by GitHub
parent 203f80020c
commit cb38613b4c
22 changed files with 1121 additions and 1 deletions

View File

@@ -184,3 +184,45 @@ are quite similar to those needed for WebSocketChannel2023:
* The `WebhookChannel2023Type` class contains all the necessary typing information.
* `WebhookEmitter` is the `NotificationEmitter` that sends the request.
* `WebhookUnsubscriber` and `WebhookWebId` are additional utility classes to support the spec requirements.
## StreamingHTTPChannel2023
Currently, support for [StreamingHTTPChannel2023](https://solid.github.io/notifications/streaming-http-channel-2023)
only covers default, pre-established channels made available for every resource. Those channels output `text/turtle`.
Support for custom, subscription-based channels can be added in the future.
* For discovery, there is a `StreamingHttpMetadataWriter`, which adds `Link` to every `HTTP` response header
using `rel="http://www.w3.org/ns/solid/terms#updatesViaStreamingHttp2023"`. It links directly to the `receiveFrom`
endpoint of the default, pre-established channel for that topic resource.
* Requests to `receiveFrom` endpoints are handled by a `StreamingHttpRequestHandler`.
* It performs an authorization check.
* It creates a new response stream and adds it to the `StreamingHttpMap`, indexed by the topic resource.
* It sends an initial notification, similar to notification channels using a `state` feature.
* `StreamingHttp2023Emitter` is the `NotificationEmitter` that writes notifications to matching response streams.
* `StreamingHttpListeningActivityHandler` is responsible for observing the `MonitoringStore`
and emitting notifications when needed.
It doesn't use a `NotificationChannelStorage` since the default, pre-established channels are not
subscription-based. Instead, it uses a `StreamingHttpMap` to check for active receivers.
```mermaid
flowchart TB
StreamingHttpListeningActivityHandler("<strong>StreamingHttpListeningActivityHandler</strong><br>StreamingHttpListeningActivityHandler")
StreamingHttpListeningActivityHandler --> StreamingHttpListeningActivityHandlerArgs
subgraph StreamingHttpListeningActivityHandlerArgs[" "]
StreamingHttpMap("<strong>StreamingHttpMap</strong><br><i>StreamingHttpMap</i>")
ResourceStore("<strong>ResourceStore</strong><br><i>ActivityEmitter</i>")
StreamingHttpNotificationHandler("<strong>StreamingHttpNotificationHandler</strong><br><i>ComposedNotificationHandler</i>")
end
StreamingHttpNotificationHandler --> StreamingHttpNotificationHandlerArgs
subgraph StreamingHttpNotificationHandlerArgs[" "]
direction TB
Generator("<strong>BaseNotificationGenerator</strong>")
Serializer("<strong>BaseNotificationSerializer</strong>")
Emitter("<strong>StreamingHttp2023Emitter</strong><br><i>StreamingHttp2023Emitter</i>")
ETagHandler("<strong>ETagHandler</strong>")
end
```

View File

@@ -127,6 +127,31 @@ The response would then be something like this:
}
```
### Streaming HTTP
Currently, Streaming HTTP channels are only available as pre-established channels on each resource.
This means that subscribing and unsubscribing are not supported, and no subscription services are advertised.
Instead, each resource advertises the `receiveFrom` of its pre-established notification channel using HTTP Link header,
using `rel="http://www.w3.org/ns/solid/terms#updatesViaStreamingHttp2023"`.
For example, this —
```shell
curl --head 'http://localhost:3000/foo/'
```
```http
HTTP/1.1 200 OK
Link: <http://localhost:3000/.notifications/StreamingHTTPChannel2023/foo/>; rel="http://www.w3.org/ns/solid/terms#updatesViaStreamingHttp2023"
```
It is essential to remember that any HTTP request to that `receiveFrom` endpoint requires the same authorization
as a `GET` request on the resource which advertises it.
Currently, all pre-established Streaming HTTP channels have `Content-Type: text/turtle`.
Information on how to consume Streaming HTTP responses [is available on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Using_readable_streams#consuming_a_fetch_as_a_stream)
## Unsubscribing from a notification channel
!!! note