platform/packages/websocket/README.md

166 lines
4.4 KiB
Markdown
Raw Normal View History

2021-05-15 07:19:35 +00:00
# angel3_websocket
[![version](https://img.shields.io/badge/pub-v4.0.0-brightgreen)](https://pub.dartlang.org/packages/angel3_websocket)
[![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety)
[![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion)
[![License](https://img.shields.io/github/license/dukefirehawk/angel)](https://github.com/dukefirehawk/angel/tree/angel3/packages/websocket/LICENSE)
2016-12-24 01:45:52 +00:00
2016-09-17 20:00:17 +00:00
WebSocket plugin for Angel.
This plugin broadcasts events from hooked services via WebSockets.
2016-12-24 01:45:52 +00:00
In addition, it adds itself to the app's IoC container as `AngelWebSocket`, so that it can be used
2016-09-17 20:00:17 +00:00
in controllers as well.
2016-12-24 01:45:52 +00:00
WebSocket contexts are add to `req.properties` as `'socket'`.
2016-09-03 12:34:01 +00:00
# Usage
**Server-side**
```dart
2021-05-15 07:19:35 +00:00
import "package:angel3_framework/angel3_framework.dart";
import "package:angel3_websocket/server.dart";
2016-09-03 12:34:01 +00:00
main() async {
2021-05-15 07:19:35 +00:00
var app = Angel();
2017-02-22 22:34:35 +00:00
2021-05-15 07:19:35 +00:00
var ws = AngelWebSocket();
2017-09-24 04:37:58 +00:00
2017-11-18 05:15:29 +00:00
// This is a plug-in. It hooks all your services,
// to automatically broadcast events.
2017-09-24 04:37:58 +00:00
await app.configure(ws.configureServer);
// Listen for requests at `/ws`.
app.all('/ws', ws.handleRequest);
2016-09-03 12:34:01 +00:00
}
```
2017-04-10 01:45:45 +00:00
Filtering events is easy with hooked services. Just return a `bool`, whether
2017-01-29 20:02:19 +00:00
synchronously or asynchronously.
```dart
2017-04-10 01:45:45 +00:00
myService.properties['ws:filter'] = (HookedServiceEvent e, WebSocketContext socket) async {
2017-01-29 20:02:19 +00:00
return true;
}
2017-06-30 23:09:03 +00:00
myService.index({
'ws:filter': (e, socket) => ...;
});
2017-01-29 20:02:19 +00:00
```
2016-09-18 01:35:16 +00:00
**Adding Handlers within a Controller**
2016-09-18 02:53:58 +00:00
`WebSocketController` extends a normal `Controller`, but also listens to WebSockets.
2016-09-18 01:35:16 +00:00
```dart
import 'dart:async';
import "package:angel_framework/angel_framework.dart";
import "package:angel_websocket/server.dart";
@Expose("/")
2016-09-18 02:53:58 +00:00
class MyController extends WebSocketController {
2017-11-18 05:15:29 +00:00
// A reference to the WebSocket plug-in is required.
MyController(AngelWebSocket ws):super(ws);
2016-09-18 01:35:16 +00:00
@override
2016-09-18 02:53:58 +00:00
void onConnect(WebSocketContext socket) {
// On connect...
}
// Dependency injection works, too..
@ExposeWs("read_message")
2017-04-17 18:19:27 +00:00
void sendMessage(WebSocketContext socket, WebSocketAction action, Db db) async {
2017-04-17 12:37:17 +00:00
socket.send(
"found_message",
db.collection("messages").findOne(where.id(action.data['message_id'])));
2016-09-18 01:35:16 +00:00
}
2017-01-29 20:02:19 +00:00
// Event filtering
@ExposeWs("foo")
void foo() {
2021-05-15 07:19:35 +00:00
broadcast( WebSocketEvent(...), filter: (socket) async => ...);
2017-01-29 20:02:19 +00:00
}
2016-09-18 01:35:16 +00:00
}
```
2017-04-17 12:37:17 +00:00
**Client Use**
2017-04-17 18:20:32 +00:00
2017-04-17 12:37:17 +00:00
This repo also provides two client libraries `browser` and `io` that extend the base
2021-05-15 07:19:35 +00:00
`angel3_client` interface, and allow you to use a very similar API on the client to that of
2017-04-17 12:37:17 +00:00
the server.
The provided clients also automatically try to reconnect their WebSockets when disconnected,
which means you can restart your development server without having to reload browser windows.
They also provide streams of data that pump out filtered data as it comes in from the server.
Clients can even perform authentication over WebSockets.
2016-09-03 12:34:01 +00:00
**In the Browser**
```dart
2021-05-15 07:19:35 +00:00
import "package:angel3_websocket/browser.dart";
2016-09-03 12:34:01 +00:00
main() async {
2021-05-15 07:19:35 +00:00
Angel app = WebSockets("/ws");
2016-12-24 01:45:52 +00:00
await app.connect();
2016-09-03 12:34:01 +00:00
var Cars = app.service("api/cars");
2017-12-21 20:15:47 +00:00
Cars.onCreated.listen((car) => print("New car: $car"));
2016-09-03 12:34:01 +00:00
// Happens asynchronously
Cars.create({"brand": "Toyota"});
2016-12-24 01:45:52 +00:00
2017-02-28 14:15:34 +00:00
// Authenticate a WebSocket, if you were not already authenticated...
app.authenticateViaJwt('<some-jwt>');
2016-12-24 01:45:52 +00:00
// Listen for arbitrary events
app.on['custom_event'].listen((event) {
// For example, this might be sent by a
// WebSocketController.
print('Hi!');
});
2016-09-03 12:34:01 +00:00
}
```
**CLI Client**
```dart
2021-05-15 07:19:35 +00:00
import "package:angel3_framework/common.dart";
import "package:angel3_websocket/io.dart";
2016-09-03 12:34:01 +00:00
// You can include these in a shared file and access on both client and server
2017-04-17 12:37:17 +00:00
class Car extends Model {
2016-09-03 12:34:01 +00:00
int year;
String brand, make;
Car({this.year, this.brand, this.make});
@override String toString() => "$year $brand $make";
}
main() async {
2021-05-15 07:19:35 +00:00
Angel app = WebSockets("/ws");
2016-12-24 01:45:52 +00:00
2016-09-17 20:00:17 +00:00
// Wait for WebSocket connection...
await app.connect();
2016-12-24 01:45:52 +00:00
2016-09-03 12:34:01 +00:00
var Cars = app.service("api/cars", type: Car);
2017-12-21 20:15:47 +00:00
Cars.onCreated.listen((Car car) {
2016-09-03 12:34:01 +00:00
// Automatically deserialized into a car :)
2017-12-21 20:15:47 +00:00
//
2016-09-03 12:34:01 +00:00
// I just bought a new 2016 Toyota Camry!
print("I just bought a new $car!");
});
// Happens asynchronously
Cars.create({"year": 2016, "brand": "Toyota", "make": "Camry"});
2017-02-28 14:15:34 +00:00
// Authenticate a WebSocket, if you were not already authenticated...
app.authenticateViaJwt('<some-jwt>');
2017-12-21 20:15:47 +00:00
}