2016-04-29 01:19:09 +00:00
|
|
|
library angel_websocket.server;
|
|
|
|
|
2016-06-27 00:42:21 +00:00
|
|
|
import 'dart:async';
|
2016-04-29 01:19:09 +00:00
|
|
|
import 'dart:io';
|
|
|
|
import 'package:angel_framework/angel_framework.dart';
|
2016-06-27 00:42:21 +00:00
|
|
|
import 'package:json_god/json_god.dart' as god;
|
|
|
|
import 'package:uuid/uuid.dart';
|
|
|
|
import 'angel_websocket.dart';
|
2016-04-29 01:19:09 +00:00
|
|
|
|
2016-06-27 00:42:21 +00:00
|
|
|
typedef Future<bool> WebSocketFilter(WebsocketContext context);
|
2016-05-03 23:42:06 +00:00
|
|
|
|
2016-06-27 00:42:21 +00:00
|
|
|
List<WebsocketContext> _clients = [];
|
|
|
|
Uuid _uuid = new Uuid();
|
2016-04-29 01:19:09 +00:00
|
|
|
|
2016-06-27 00:42:21 +00:00
|
|
|
class WebsocketContext {
|
|
|
|
WebSocket socket;
|
|
|
|
RequestContext request;
|
|
|
|
ResponseContext response;
|
2016-04-29 01:19:09 +00:00
|
|
|
|
2016-06-27 00:42:21 +00:00
|
|
|
WebsocketContext(WebSocket this.socket, RequestContext this.request,
|
|
|
|
ResponseContext this.response);
|
|
|
|
}
|
2016-04-29 01:19:09 +00:00
|
|
|
|
2016-06-27 00:42:21 +00:00
|
|
|
_broadcast(WebSocketEvent event) {
|
|
|
|
String json = god.serialize(event);
|
|
|
|
_clients.forEach((WebsocketContext client) {
|
|
|
|
client.socket.add(json);
|
|
|
|
});
|
2016-04-29 01:19:09 +00:00
|
|
|
}
|
|
|
|
|
2016-06-27 00:42:21 +00:00
|
|
|
_onData(Angel app) {
|
|
|
|
return (data) {
|
2016-04-29 01:19:09 +00:00
|
|
|
try {
|
2016-06-27 00:42:21 +00:00
|
|
|
WebSocketAction action = god.deserialize(
|
|
|
|
data, outputType: WebSocketAction);
|
|
|
|
|
|
|
|
List<String> split = action.eventName.split("::");
|
|
|
|
|
|
|
|
if (split.length >= 2) {
|
|
|
|
Service service = app.service(split[0]);
|
|
|
|
|
|
|
|
if (service != null) {
|
|
|
|
String event = split[1];
|
2016-04-29 01:19:09 +00:00
|
|
|
|
2016-06-27 00:42:21 +00:00
|
|
|
if (event == "index") {
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2016-04-29 01:19:09 +00:00
|
|
|
}
|
|
|
|
} catch (e) {
|
2016-06-27 00:42:21 +00:00
|
|
|
|
2016-04-29 01:19:09 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2016-06-27 00:42:21 +00:00
|
|
|
_onError(e) {
|
2016-05-03 23:42:06 +00:00
|
|
|
|
2016-06-27 00:42:21 +00:00
|
|
|
}
|
2016-05-03 23:42:06 +00:00
|
|
|
|
2016-06-27 00:42:21 +00:00
|
|
|
class websocket {
|
|
|
|
static Map<String, WebSocketFilter> filters = {};
|
|
|
|
|
|
|
|
call({List<Pattern> endPoints: const['/ws']}) {
|
|
|
|
return (Angel app) async {
|
|
|
|
for (Pattern endPoint in endPoints) {
|
|
|
|
app.all(endPoint, (RequestContext req, ResponseContext res) async {
|
|
|
|
if (!WebSocketTransformer.isUpgradeRequest(req.underlyingRequest)) {
|
|
|
|
res.write("This endpoint is only accessible via WebSockets.");
|
|
|
|
res.end();
|
|
|
|
} else {
|
|
|
|
res
|
|
|
|
..willCloseItself = true
|
|
|
|
..end();
|
|
|
|
WebSocket socket = await WebSocketTransformer.upgrade(
|
|
|
|
req.underlyingRequest);
|
|
|
|
WebsocketContext context = new WebsocketContext(socket, req, res);
|
|
|
|
_clients.add(context);
|
|
|
|
|
|
|
|
socket.listen(_onData(app), onError: _onError, onDone: () {
|
|
|
|
_clients.remove(context);
|
|
|
|
});
|
|
|
|
}
|
2016-05-03 23:42:06 +00:00
|
|
|
});
|
|
|
|
|
2016-06-27 00:42:21 +00:00
|
|
|
app.services.forEach((Pattern path, Service service) {
|
|
|
|
if (service is HookedService) {
|
|
|
|
String pathName = (path is RegExp) ? path.pattern : path;
|
|
|
|
List<HookedServiceEventDispatcher> dispatchers = [
|
|
|
|
service.afterIndexed,
|
|
|
|
service.afterCreated,
|
|
|
|
service.afterRead,
|
|
|
|
service.afterModified,
|
|
|
|
service.afterUpdated,
|
|
|
|
service.afterRemoved
|
|
|
|
];
|
|
|
|
|
|
|
|
for (HookedServiceEventDispatcher dispatcher in dispatchers) {
|
|
|
|
dispatcher.listen((HookedServiceEvent event) async {
|
|
|
|
bool canContinue = true;
|
|
|
|
String filterName = "$pathName::${event.eventName}";
|
|
|
|
WebSocketFilter filter = filters[filterName];
|
|
|
|
|
|
|
|
for (WebsocketContext client in _clients) {
|
|
|
|
if (filter != null)
|
|
|
|
canContinue = await filter(client);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (canContinue) {
|
|
|
|
WebSocketEvent socketEvent = new WebSocketEvent(
|
|
|
|
id: _uuid.v4(),
|
|
|
|
eventName: filterName,
|
|
|
|
data: event.result);
|
|
|
|
_broadcast(socketEvent);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
2016-05-03 23:42:06 +00:00
|
|
|
});
|
2016-04-29 01:19:09 +00:00
|
|
|
}
|
2016-06-27 00:42:21 +00:00
|
|
|
};
|
|
|
|
}
|
2016-04-29 01:19:09 +00:00
|
|
|
}
|