This commit is contained in:
thosakwe 2016-09-03 08:34:01 -04:00
parent bdb9ad4fcd
commit 29a682cce8
9 changed files with 73 additions and 125 deletions

View file

@ -1,2 +1,67 @@
# angel_websocket # angel_websocket
WebSocket plugin for Angel. Features JWT support. WebSocket plugin for Angel. Features JWT support.
# Usage
**Server-side**
```dart
import "package:angel_framework/angel_framework.dart";
import "package:angel_websocket/server.dart";
main() async {
var app = new Angel();
await app.configure(new AngelWebSocket("/ws"));
}
```
**In the Browser**
```dart
import "package:angel_websocket/browser.dart";
main() async {
Angel app = new WebSocketClient("/ws");
var Cars = app.service("api/cars");
Cars.onCreated.listen((e) => print("New car: ${e.data}"));
// Happens asynchronously
Cars.create({"brand": "Toyota"});
}
```
**CLI Client**
```dart
import "package:angel_framework/angel_framework" as srv;
import "package:angel_websocket/browser.dart";
// You can include these in a shared file and access on both client and server
class Car extends srv.Model {
int year;
String brand, make;
Car({this.year, this.brand, this.make});
@override String toString() => "$year $brand $make";
}
main() async {
Angel app = new WebSocketClient("/ws");
var Cars = app.service("api/cars", type: Car);
Cars.onCreated.listen((e) {
// Automatically deserialized into a car :)
Car car = e.data;
// 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"});
}
```

View file

@ -3,6 +3,7 @@ import 'dart:convert';
import 'dart:html'; import 'dart:html';
import 'package:angel_client/angel_client.dart'; import 'package:angel_client/angel_client.dart';
import 'package:angel_websocket/angel_websocket.dart'; import 'package:angel_websocket/angel_websocket.dart';
export 'package:angel_client/angel_client.dart';
export 'package:angel_websocket/angel_websocket.dart'; export 'package:angel_websocket/angel_websocket.dart';
class WebSocketClient extends Angel { class WebSocketClient extends Angel {

View file

@ -5,6 +5,8 @@ import 'package:angel_client/angel_client.dart';
import 'package:angel_framework/angel_framework.dart' as srv; import 'package:angel_framework/angel_framework.dart' as srv;
import 'package:angel_websocket/angel_websocket.dart'; import 'package:angel_websocket/angel_websocket.dart';
import 'package:json_god/json_god.dart' as god; import 'package:json_god/json_god.dart' as god;
export 'package:angel_client/angel_client.dart';
export 'package:angel_websocket/angel_websocket.dart';
class WebSocketClient extends Angel { class WebSocketClient extends Angel {
WebSocket _socket; WebSocket _socket;

View file

@ -7,6 +7,7 @@ import 'package:angel_framework/angel_framework.dart';
import 'package:json_god/json_god.dart' as god; import 'package:json_god/json_god.dart' as god;
import 'package:merge_map/merge_map.dart'; import 'package:merge_map/merge_map.dart';
import 'angel_websocket.dart'; import 'angel_websocket.dart';
export 'angel_websocket.dart';
part 'websocket_context.dart'; part 'websocket_context.dart';

View file

@ -1,120 +0,0 @@
library angel_websocket.server;
import 'dart:async';
import 'dart:io';
import 'package:angel_framework/angel_framework.dart';
import 'package:json_god/json_god.dart' as god;
import 'package:uuid/uuid.dart';
import 'angel_websocket.dart';
typedef Future<bool> WebSocketFilter(WebsocketContext context);
List<WebsocketContext> _clients = [];
Uuid _uuid = new Uuid();
class WebsocketContext {
WebSocket socket;
RequestContext request;
ResponseContext response;
WebsocketContext(WebSocket this.socket, RequestContext this.request,
ResponseContext this.response);
}
_broadcast(WebSocketEvent event) {
String json = god.serialize(event);
_clients.forEach((WebsocketContext client) {
client.socket.add(json);
});
}
_onData(Angel app) {
return (data) {
try {
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];
if (event == "index") {
}
}
}
} catch (e) {
}
};
}
_onError(e) {
}
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);
});
}
});
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(eventName: filterName,
data: event.result);
_broadcast(socketEvent);
}
});
}
}
});
}
};
}
}

View file

@ -1,6 +1,6 @@
name: angel_websocket name: angel_websocket
description: WebSocket plugin for Angel description: WebSocket plugin for Angel
version: 1.0.0-dev+1 version: 1.0.0-dev+2
author: thosakwe <thosakwe@gmail.com> author: thosakwe <thosakwe@gmail.com>
homepage: https://github.com/angel-dart/angel_websocket homepage: https://github.com/angel-dart/angel_websocket
dependencies: dependencies:

View file

@ -1,7 +1,6 @@
import 'dart:io'; import 'dart:io';
import 'package:angel_framework/angel_framework.dart' as server; import 'package:angel_framework/angel_framework.dart' as server;
import 'package:angel_websocket/client.dart' as client; import 'package:angel_websocket/cli.dart' as client;
import 'package:angel_websocket/angel_websocket.dart';
import 'package:angel_websocket/server.dart'; import 'package:angel_websocket/server.dart';
import 'package:json_god/json_god.dart' as god; import 'package:json_god/json_god.dart' as god;
import 'package:test/test.dart'; import 'package:test/test.dart';