diff --git a/README.md b/README.md index d3d89267..89652e74 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # angel_websocket -[![1.0.5](https://img.shields.io/badge/pub-1.0.5+3-brightgreen.svg)](https://pub.dartlang.org/packages/angel_websocket) +[![1.0.6](https://img.shields.io/badge/pub-1.0.6-brightgreen.svg)](https://pub.dartlang.org/packages/angel_websocket) [![build status](https://travis-ci.org/angel-dart/websocket.svg)](https://travis-ci.org/angel-dart/websocket) WebSocket plugin for Angel. diff --git a/lib/browser.dart b/lib/browser.dart index b7ab6910..0cdee541 100644 --- a/lib/browser.dart +++ b/lib/browser.dart @@ -34,21 +34,27 @@ class WebSockets extends BaseWebSocketClient { var ctrl = new StreamController(); var wnd = window.open(url, 'angel_client_auth_popup'); - wnd - ..on['beforeunload'].listen((_) { - if (!ctrl.isClosed) { + Timer t; + t = new Timer.periodic(new Duration(milliseconds: 500), (timer) { + if (!ctrl.isClosed) { + if (wnd.closed) { ctrl.addError(new AngelHttpException.notAuthenticated( message: - errorMessage ?? 'Authentication via popup window failed.')); + errorMessage ?? 'Authentication via popup window failed.')); ctrl.close(); + timer.cancel(); } - }) - ..on[eventName ?? 'token'].listen((CustomEvent e) { - if (!ctrl.isClosed) { - ctrl.add(e.detail); - ctrl.close(); - } - }); + } else + timer.cancel(); + }); + + window.on[eventName ?? 'token'].listen((CustomEvent e) { + if (!ctrl.isClosed) { + ctrl.add(e.detail); + t.cancel(); + ctrl.close(); + } + }); return ctrl.stream; } diff --git a/lib/hooks.dart b/lib/hooks.dart index 32dea957..362e5d62 100644 --- a/lib/hooks.dart +++ b/lib/hooks.dart @@ -3,7 +3,8 @@ import 'package:angel_framework/angel_framework.dart'; /// Prevents a WebSocket event from being broadcasted, to any client from the given [provider]. /// /// [provider] can be a String, a [Provider], or an Iterable. -HookedServiceEventListener doNotBroadcast(provider) { +/// If [provider] is `null`, any provider will be blocked. +HookedServiceEventListener doNotBroadcast([provider]) { return (HookedServiceEvent e) { if (e.params != null && e.params.containsKey('provider')) { bool deny = false; @@ -16,6 +17,8 @@ HookedServiceEventListener doNotBroadcast(provider) { deny = deny || p == e.params['provider'] || e.params['provider'] == p.via; + } else if (p == null) { + deny = true; } else deny = deny || (e.params['provider'] as Providers).via == p.toString(); diff --git a/lib/server.dart b/lib/server.dart index 876ddc47..45777912 100644 --- a/lib/server.dart +++ b/lib/server.dart @@ -42,6 +42,11 @@ class AngelWebSocket extends AngelPlugin { /// Include debug information, and send error information across WebSockets. final bool debug; + bool _sendErrors; + + /// Send error information across WebSockets, without including [debug] information.. + bool get sendErrors => _sendErrors == true; + /// Registers this instance as a route on the server. final AngelWebSocketRegisterer register; @@ -70,13 +75,27 @@ class AngelWebSocket extends AngelPlugin { /// Fired when a user disconnects. Stream get onDisconnection => _onDisconnect.stream; + /// Serializes data to WebSockets. + ResponseSerializer serializer; + + /// Deserializes data from WebSockets. + Function deserializer; + AngelWebSocket( {this.endpoint: '/ws', this.debug: false, + bool sendErrors, this.allowClientParams: false, this.allowAuth: true, this.register, - this.synchronizer}); + this.synchronizer, + this.serializer, + this.deserializer}) { + _sendErrors = sendErrors; + + if (serializer == null) serializer = god.serialize; + if (deserializer == null) deserializer = (params) => params; + } serviceHook(String path) { return (HookedServiceEvent e) async { @@ -111,7 +130,7 @@ class AngelWebSocket extends AngelPlugin { var serialized = event.toJson(); _printDebug('Batching this event: $serialized'); // print('Serialized: ' + JSON.encode(serialized)); - client.io.add(god.serialize(event.toJson())); + client.io.add((serializer ?? god.serialize)(event.toJson())); } }); @@ -150,7 +169,7 @@ class AngelWebSocket extends AngelPlugin { } var params = mergeMap([ - god.deserializeDatum(action.params), + (deserializer ?? (params) => params)(action.params), { "provider": Providers.WEBSOCKET, '__requestctx': socket.request, @@ -188,7 +207,7 @@ class AngelWebSocket extends AngelPlugin { } catch (e, st) { if (e is AngelHttpException) return socket.sendError(e); - else if (debug == true) + else if (debug == true || _sendErrors == true) socket.sendError(new AngelHttpException(e, message: e.toString(), stackTrace: st, errors: [st.toString()])); else @@ -218,7 +237,7 @@ class AngelWebSocket extends AngelPlugin { // Send an error if (e is AngelHttpException) socket.sendError(e); - else if (debug == true) + else if (debug == true || _sendErrors == true) socket.sendError(new AngelHttpException(e, message: e.toString(), stackTrace: st, errors: [st.toString()])); else @@ -277,7 +296,7 @@ class AngelWebSocket extends AngelPlugin { // Send an error if (e is AngelHttpException) socket.sendError(e); - else if (debug == true) + else if (debug == true || _sendErrors == true) socket.sendError(new AngelHttpException(e, message: e.toString(), stackTrace: st, errors: [st.toString()])); else @@ -302,6 +321,8 @@ class AngelWebSocket extends AngelPlugin { @override Future call(Angel app) async { + if (_sendErrors == null) _sendErrors = app.isProduction; + _app = app..container.singleton(this); if (runtimeType != AngelWebSocket) diff --git a/lib/websocket_controller.dart b/lib/websocket_controller.dart index c0d3db12..c1da2ec9 100644 --- a/lib/websocket_controller.dart +++ b/lib/websocket_controller.dart @@ -68,25 +68,26 @@ class WebSocketController extends Controller { socket.onAction.listen((WebSocketAction action) async { socket.request.inject(WebSocketAction, action); - await onAction(action, socket); - if (_handlers.containsKey(action.eventName)) { - try { + try { + await onAction(action, socket); + + if (_handlers.containsKey(action.eventName)) { var methodMirror = _handlers[action.eventName]; var fn = instanceMirror.getField(methodMirror.simpleName).reflectee; return app.runContained(fn, socket.request, socket.response); - } catch (e, st) { - // Send an error - if (e is AngelHttpException) - socket.sendError(e); - else if (ws.debug == true) - socket.sendError(new AngelHttpException(e, - message: e.toString(), - stackTrace: st, - errors: [st.toString()])); - else - socket.sendError(new AngelHttpException(e)); } + } catch (e, st) { + // Send an error + if (e is AngelHttpException) + socket.sendError(e); + else if (ws.debug == true || ws.sendErrors == true) + socket.sendError(new AngelHttpException(e, + message: e.toString(), + stackTrace: st, + errors: [st.toString()])); + else + socket.sendError(new AngelHttpException(e)); } }); }); diff --git a/pubspec.yaml b/pubspec.yaml index 82d64578..b1270b0d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: angel_websocket description: WebSocket plugin for Angel. environment: sdk: ">=1.19.0" -version: 1.0.5 +version: 1.0.6 author: Tobe O homepage: https://github.com/angel-dart/angel_websocket dependencies: