You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Important part of RIG is creating event subscriptions. RIG is holding connections between clients and itself and forwarding events to proper clients. Currently the supported options are [Server-Sent Events](https://en.wikipedia.org/wiki/Server-sent_events)and [WebSocket](https://en.wikipedia.org/wiki/WebSocket). There is multiple ways how you can create subscription for given events.
7
+
There are **two ways to receive events**, either via [Server-Sent Events](https://en.wikipedia.org/wiki/Server-sent_events)(SSE) or via a [WebSocket](https://en.wikipedia.org/wiki/WebSocket) connection. We recommend SSE:
8
8
9
-
## Manual subscriptions
9
+
- With HTTP/2, there is no (practical) limit to the number of SSE connections/streams that can be created.
10
+
- SSE does not require dropping the HTTP protocol, which makes it firewall-friendly.
11
+
- SSE is a better fit to the architecture RIG implements (WebSocket is typically used for full-duplex connection).
10
12
11
-
Subscription is created by calling HTTP endpoint:
13
+
**Event subscriptions** allow both backend and frontend developers to select the events they want to have forwarded towards the UI:
- Frontend developers can set up **(manual) subscriptions** that refer to an event type and zero, one or more _named_ fields of an event. The fields that can be referred to have to be set up in advance using the so-called _extractor configuration_ (see below).
16
+
- Backend developers/administrators can set up **automatic subscriptions**, where events are subscribed to according to the JWT the UI sends with its request.
17
+
18
+
Both automatic and manual subscriptions can be used at the same time - they are simply merged into a single set of subscriptions. Below there are examples for both types, but first we introduce _constraints_ and _extractors_.
19
+
20
+
## Constraints & Extractors
18
21
19
-
`connectionToken` is provided by initial SSE/WS connection call, thus it's recommended to save it somewhere. In body you provide which event types to listen to (notice it's an array). After successful you'll get all events with given event type(s).
22
+
If subscribing to events by their event type is all you need, you can skip this.
20
23
21
-
## Constraints & extractors
24
+
For a larges example and more details take a look at [the source documentation of `EventFilter`](https://accenture.github.io/reactive-interaction-gateway/source_docs/Rig.EventFilter.html).
22
25
23
-
To be more restrictive in who should receive what event you can leverage from constraints and extractors. Extractors are set on RIG describing how to match events to clients -- to be more specific where to look for values. As an example _check `name` field in event_. This can be set as an environment variable (string or JSON file). Constraints are set on client side providing exact value to look for in filtering -- for example `John`. Combining with extractor example RIG will try to find `John` in event -- if found event is forwarded to client.
26
+
### Constraints
24
27
25
-
Extractor example:
28
+
Constraints allow you to subscribe to events based on the value of pre-defined fields. For example, this is a subscription for "greeting" events that have the "name" field set to "John":
26
29
27
30
```json
28
31
{
29
-
"greeting": {
30
-
"name": {
31
-
"stable_field_index": 1,
32
-
"event": {
33
-
"json_pointer": "/data/name"
34
-
}
32
+
"subscriptions": [
33
+
{
34
+
"eventType": "greeting",
35
+
"oneOf": [
36
+
{ "name": "John" }
37
+
]
35
38
}
36
-
}
39
+
]
37
40
}
38
41
```
39
42
40
-
Environment variable:
41
-
42
-
```
43
-
EXTRACTORS=my-extractor.json
44
-
```
45
-
46
-
Constraints example (in subscription call):
43
+
The "oneOf" property contains a list of objects. Each object may contain one or more fields and each of them must match the respective value in the event, but only one of those objects must match (that's the reason the property is called "oneOf"). This allows you to query for greeting event to either "John" or "Frank":
47
44
48
45
```json
49
46
{
50
47
"subscriptions": [
51
48
{
52
-
"eventType": "example",
49
+
"eventType": "greeting",
53
50
"oneOf": [
54
-
{
55
-
"name": "John"
56
-
}
51
+
{ "name": "John" },
52
+
{ "name": "Frank" }
57
53
]
58
54
}
59
55
]
60
56
}
61
57
```
62
58
63
-
##Auth
59
+
### Basic Extractor configuration
64
60
65
-
Authentication can be turned on by setting environment variables:
61
+
When referring to the "name" field in a subscription, we assume that RIG knows what "name" refers to in incoming events. In RIG, obtaining the value for a named field is called _extraction_ and the corresponding configuration is called _extractor configuration_. The latter can be set using the `EXTRACTORS` environment variable, which expects either a file path or a JSON encoded string.
66
62
63
+
Consider the following extractor configuration, `extractors.json`:
64
+
65
+
```json
66
+
{
67
+
"greeting": {
68
+
"name": {
69
+
"stable_field_index": 1,
70
+
"event": {
71
+
"json_pointer": "/data/name"
72
+
}
73
+
}
74
+
}
75
+
}
67
76
```
68
-
SUBSCRIPTION_CHECK=jwt_validation
69
-
JWT_SECRET_KEY=secret
70
-
```
71
77
72
-
JWT needs to be in form of `Bearer eyJh...`.
78
+
This sets up an extractor for events of type "greeting". It has one field called "name"; the value of "name" for any given event is extracted using the [JSON Pointer](https://tools.ietf.org/html/rfc6901)`/data/name`.
79
+
80
+
We can pass this configuration to RIG using the environment variable:
81
+
82
+
```bash
83
+
export EXTRACTORS=extractors.json
84
+
```
73
85
74
-
## Inferred subscriptions
86
+
Assuming the UI sets up a subscription like this:
75
87
76
-
There is also possibility to create subscription automatically (without calling subscription endpoint above) -- inferring from JWT. This behavior is triggered right away in first connection call. Event types to be subscribed to are inferred from extractors, thus it's needed to set them up.
Then RIG's greeting extractor would use the JSON pointer configured for "name" to extract the value "John" and match that against the subscription - this matches, so RIG forwards the event to the UI.
105
+
106
+
### Extractor configuration for automatic subscriptions
107
+
108
+
In order to support automatic, JWT-based subscriptions, the extractor also needs to know how to extract the value from JWT claims. Going back to the previous example, we extends the extractor configuration by an additional `jwt` property:
109
+
110
+
<pre><code>
81
111
{
82
112
"greeting": {
83
113
"name": {
84
114
"stable_field_index": 1,
85
-
"jwt": {
86
-
"json_pointer": "/username"
87
-
},
88
115
"event": {
89
116
"json_pointer": "/data/name"
90
-
}
91
-
}
92
-
},
93
-
"example": {
94
-
"fullname": {
95
-
"stable_field_index": 1,
96
-
"jwt": {
97
-
"json_pointer": "/fullname"
98
117
},
99
-
"event": {
100
-
"json_pointer": "/data/fullname"
101
-
}
118
+
<b>"jwt": {
119
+
"json_pointer": "/username"
120
+
}</b>
102
121
}
103
122
}
104
123
}
105
-
```
124
+
</code></pre>
125
+
126
+
With that configuration, a frontend receives all events of type "greeting" where the value of `/data/name` equals the value of `/username` in the JWT.
127
+
128
+
## Manual subscriptions
129
+
130
+
Manual subscriptions can be set up when establishing the connection. Additionally, RIG offers an endpoint to update a connection's subscriptions after the connection has already been established.
131
+
132
+
The following example works similarly for both SSE and WebSocket. We use HTTPie here to make the examples a bit shorter. See the [MDN web docs article on SSE](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) for an example on how to set up SSE in a browser.
133
+
134
+
Example for setting up initial subscriptions:
106
135
107
-
This would lead to subscription to event types - `greeting` and `example`.
Note that the `rig.subscriptions_set` event includes the passed subscription. Also, note that the `rig.connection.create` event includes a `connection_token`; this token can now be used to update the subscriptions after the connection has been established. Let's replace our initial subscription to "greeting" with a new one to "greeting2":
We see that the subscription to "greeting" has been replaced by a subscription to "greeting2".
168
+
169
+
Note that if you want to retain any automatic subscriptions you got along with setting up the connection, you need to make sure you _include the same HTTP Authorization header in both requests_.
170
+
171
+
## Subscription Authorization
172
+
173
+
RIG can either allow anyone to subscribe to any events, restrict subscriptions to clients that send a valid JWT, or forward subscription requests to an external endpoint and let that endpoint decide whether or not to allow a particular subscription. This can be configured using the environment variable `SUBSCRIPTION_CHECK` - please consult the [Operator's Guide](rig-ops-guide) for details.
0 commit comments