1.1.0-alpha
This commit is contained in:
parent
1108997817
commit
3c01c4b360
12 changed files with 143 additions and 168 deletions
|
@ -23,8 +23,13 @@ import "package:angel_websocket/server.dart";
|
||||||
main() async {
|
main() async {
|
||||||
var app = new Angel();
|
var app = new Angel();
|
||||||
|
|
||||||
// Ensure this runs after all our services are in-place
|
var ws = new AngelWebSocket();
|
||||||
app.justBeforeStart.add(new AngelWebSocket("/ws"));
|
|
||||||
|
// Apply configuration
|
||||||
|
await app.configure(ws.configureServer);
|
||||||
|
|
||||||
|
// Listen for requests at `/ws`.
|
||||||
|
app.all('/ws', ws.handleRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
@ -2,12 +2,12 @@ import 'dart:async';
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:angel_client/angel_client.dart';
|
import 'package:angel_client/angel_client.dart';
|
||||||
|
import 'package:angel_client/base_angel_client.dart';
|
||||||
|
import 'package:angel_http_exception/angel_http_exception.dart';
|
||||||
import 'package:http/src/base_client.dart' as http;
|
import 'package:http/src/base_client.dart' as http;
|
||||||
import 'package:web_socket_channel/web_socket_channel.dart';
|
import 'package:web_socket_channel/web_socket_channel.dart';
|
||||||
import 'package:web_socket_channel/status.dart' as status;
|
import 'package:web_socket_channel/status.dart' as status;
|
||||||
import 'angel_websocket.dart';
|
import 'angel_websocket.dart';
|
||||||
export 'package:angel_client/angel_client.dart';
|
|
||||||
import 'package:angel_client/base_angel_client.dart';
|
|
||||||
|
|
||||||
final RegExp _straySlashes = new RegExp(r"(^/)|(/+$)");
|
final RegExp _straySlashes = new RegExp(r"(^/)|(/+$)");
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ abstract class BaseWebSocketClient extends BaseAngelClient {
|
||||||
Future<WebSocketChannel> getConnectedWebSocket();
|
Future<WebSocketChannel> getConnectedWebSocket();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
WebSocketsService service<T>(String path,
|
WebSocketsService service(String path,
|
||||||
{Type type, AngelDeserializer deserializer}) {
|
{Type type, AngelDeserializer deserializer}) {
|
||||||
String uri = path.toString().replaceAll(_straySlashes, '');
|
String uri = path.toString().replaceAll(_straySlashes, '');
|
||||||
return new WebSocketsService(socket, this, uri,
|
return new WebSocketsService(socket, this, uri,
|
||||||
|
|
|
@ -4,11 +4,11 @@ library angel_websocket.browser;
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:html';
|
import 'dart:html';
|
||||||
import 'package:angel_client/angel_client.dart';
|
import 'package:angel_client/angel_client.dart';
|
||||||
|
import 'package:angel_http_exception/angel_http_exception.dart';
|
||||||
import 'package:http/browser_client.dart' as http;
|
import 'package:http/browser_client.dart' as http;
|
||||||
import 'package:web_socket_channel/web_socket_channel.dart';
|
import 'package:web_socket_channel/web_socket_channel.dart';
|
||||||
import 'package:web_socket_channel/html.dart';
|
import 'package:web_socket_channel/html.dart';
|
||||||
import 'base_websocket_client.dart';
|
import 'base_websocket_client.dart';
|
||||||
export 'package:angel_client/angel_client.dart';
|
|
||||||
export 'angel_websocket.dart';
|
export 'angel_websocket.dart';
|
||||||
|
|
||||||
final RegExp _straySlashes = new RegExp(r"(^/)|(/+$)");
|
final RegExp _straySlashes = new RegExp(r"(^/)|(/+$)");
|
||||||
|
@ -50,9 +50,9 @@ class WebSockets extends BaseWebSocketClient {
|
||||||
timer.cancel();
|
timer.cancel();
|
||||||
});
|
});
|
||||||
|
|
||||||
sub = window.on[eventName ?? 'token'].listen((CustomEvent e) {
|
sub = window.on[eventName ?? 'token'].listen((e) {
|
||||||
if (!ctrl.isClosed) {
|
if (!ctrl.isClosed) {
|
||||||
ctrl.add(e.detail);
|
ctrl.add((e as CustomEvent).detail);
|
||||||
t.cancel();
|
t.cancel();
|
||||||
ctrl.close();
|
ctrl.close();
|
||||||
sub.cancel();
|
sub.cancel();
|
||||||
|
@ -64,7 +64,9 @@ class WebSockets extends BaseWebSocketClient {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<WebSocketChannel> getConnectedWebSocket() {
|
Future<WebSocketChannel> getConnectedWebSocket() {
|
||||||
var socket = new WebSocket(authToken?.isNotEmpty == true ? '$basePath?token=$authToken' : basePath );
|
var socket = new WebSocket(authToken?.isNotEmpty == true
|
||||||
|
? '$basePath?token=$authToken'
|
||||||
|
: basePath);
|
||||||
var completer = new Completer<WebSocketChannel>();
|
var completer = new Completer<WebSocketChannel>();
|
||||||
|
|
||||||
socket
|
socket
|
||||||
|
@ -72,18 +74,20 @@ class WebSockets extends BaseWebSocketClient {
|
||||||
if (!completer.isCompleted)
|
if (!completer.isCompleted)
|
||||||
return completer.complete(new HtmlWebSocketChannel(socket));
|
return completer.complete(new HtmlWebSocketChannel(socket));
|
||||||
})
|
})
|
||||||
..onError.listen((ErrorEvent e) {
|
..onError.listen((e) {
|
||||||
if (!completer.isCompleted) return completer.completeError(e.error);
|
var err = e as ErrorEvent;
|
||||||
|
if (!completer.isCompleted) return completer.completeError(err.error);
|
||||||
});
|
});
|
||||||
|
|
||||||
return completer.future;
|
return completer.future;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
BrowserWebSocketsService service<T>(String path,
|
BrowserWebSocketsService service(String path,
|
||||||
{Type type, AngelDeserializer deserializer}) {
|
{Type type, AngelDeserializer deserializer}) {
|
||||||
String uri = path.replaceAll(_straySlashes, '');
|
String uri = path.replaceAll(_straySlashes, '');
|
||||||
return new BrowserWebSocketsService(socket, this, uri, deserializer: deserializer);
|
return new BrowserWebSocketsService(socket, this, uri,
|
||||||
|
deserializer: deserializer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,9 @@ library angel_websocket.flutter;
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:angel_client/angel_client.dart';
|
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:web_socket_channel/web_socket_channel.dart';
|
import 'package:web_socket_channel/web_socket_channel.dart';
|
||||||
import 'package:web_socket_channel/io.dart';
|
import 'package:web_socket_channel/io.dart';
|
||||||
import 'angel_websocket.dart';
|
|
||||||
import 'base_websocket_client.dart';
|
import 'base_websocket_client.dart';
|
||||||
export 'package:angel_client/angel_client.dart';
|
export 'package:angel_client/angel_client.dart';
|
||||||
export 'angel_websocket.dart';
|
export 'angel_websocket.dart';
|
||||||
|
|
|
@ -46,10 +46,10 @@ class WebSockets extends BaseWebSocketClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
IoWebSocketsService service<T>(String path,
|
IoWebSocketsService service(String path,
|
||||||
{Type type, AngelDeserializer deserializer}) {
|
{Type type, AngelDeserializer deserializer}) {
|
||||||
String uri = path.replaceAll(_straySlashes, '');
|
String uri = path.replaceAll(_straySlashes, '');
|
||||||
return new IoWebSocketsService(socket, this, uri, T != dynamic ? T : type);
|
return new IoWebSocketsService(socket, this, uri, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
143
lib/server.dart
143
lib/server.dart
|
@ -16,12 +16,8 @@ part 'websocket_context.dart';
|
||||||
|
|
||||||
part 'websocket_controller.dart';
|
part 'websocket_controller.dart';
|
||||||
|
|
||||||
/// Used to assign routes to a given handler.
|
|
||||||
typedef AngelWebSocketRegisterer(Angel app, RequestHandler handler);
|
|
||||||
|
|
||||||
/// Broadcasts events from [HookedService]s, and handles incoming [WebSocketAction]s.
|
/// Broadcasts events from [HookedService]s, and handles incoming [WebSocketAction]s.
|
||||||
class AngelWebSocket extends AngelPlugin {
|
class AngelWebSocket {
|
||||||
Angel _app;
|
|
||||||
List<WebSocketContext> _clients = [];
|
List<WebSocketContext> _clients = [];
|
||||||
final List<String> _servicesAlreadyWired = [];
|
final List<String> _servicesAlreadyWired = [];
|
||||||
|
|
||||||
|
@ -33,6 +29,8 @@ class AngelWebSocket extends AngelPlugin {
|
||||||
final StreamController<WebSocketContext> _onDisconnect =
|
final StreamController<WebSocketContext> _onDisconnect =
|
||||||
new StreamController<WebSocketContext>.broadcast();
|
new StreamController<WebSocketContext>.broadcast();
|
||||||
|
|
||||||
|
final Angel app;
|
||||||
|
|
||||||
/// If this is not `true`, then all client-side service parameters will be
|
/// If this is not `true`, then all client-side service parameters will be
|
||||||
/// discarded, other than `params['query']`.
|
/// discarded, other than `params['query']`.
|
||||||
final bool allowClientParams;
|
final bool allowClientParams;
|
||||||
|
@ -40,16 +38,8 @@ class AngelWebSocket extends AngelPlugin {
|
||||||
/// If `true`, then clients can authenticate their WebSockets by sending a valid JWT.
|
/// If `true`, then clients can authenticate their WebSockets by sending a valid JWT.
|
||||||
final bool allowAuth;
|
final bool allowAuth;
|
||||||
|
|
||||||
/// Include debug information, and send error information across WebSockets.
|
|
||||||
final bool debug;
|
|
||||||
|
|
||||||
bool _sendErrors;
|
|
||||||
|
|
||||||
/// Send error information across WebSockets, without including [debug] information..
|
/// Send error information across WebSockets, without including [debug] information..
|
||||||
bool get sendErrors => _sendErrors == true;
|
final bool sendErrors;
|
||||||
|
|
||||||
/// Registers this instance as a route on the server.
|
|
||||||
final AngelWebSocketRegisterer register;
|
|
||||||
|
|
||||||
/// A list of clients currently connected to this server via WebSockets.
|
/// A list of clients currently connected to this server via WebSockets.
|
||||||
List<WebSocketContext> get clients => new List.unmodifiable(_clients);
|
List<WebSocketContext> get clients => new List.unmodifiable(_clients);
|
||||||
|
@ -58,9 +48,6 @@ class AngelWebSocket extends AngelPlugin {
|
||||||
List<String> get servicesAlreadyWired =>
|
List<String> get servicesAlreadyWired =>
|
||||||
new List.unmodifiable(_servicesAlreadyWired);
|
new List.unmodifiable(_servicesAlreadyWired);
|
||||||
|
|
||||||
/// The endpoint that users should connect a WebSocket to.
|
|
||||||
final String endpoint;
|
|
||||||
|
|
||||||
/// Used to notify other nodes of an event's firing. Good for scaled applications.
|
/// Used to notify other nodes of an event's firing. Good for scaled applications.
|
||||||
final WebSocketSynchronizer synchronizer;
|
final WebSocketSynchronizer synchronizer;
|
||||||
|
|
||||||
|
@ -82,17 +69,13 @@ class AngelWebSocket extends AngelPlugin {
|
||||||
/// Deserializes data from WebSockets.
|
/// Deserializes data from WebSockets.
|
||||||
Function deserializer;
|
Function deserializer;
|
||||||
|
|
||||||
AngelWebSocket({this.endpoint: '/ws',
|
AngelWebSocket(this.app,
|
||||||
this.debug: false,
|
{this.sendErrors: false,
|
||||||
bool sendErrors,
|
|
||||||
this.allowClientParams: false,
|
this.allowClientParams: false,
|
||||||
this.allowAuth: true,
|
this.allowAuth: true,
|
||||||
this.register,
|
|
||||||
this.synchronizer,
|
this.synchronizer,
|
||||||
this.serializer,
|
this.serializer,
|
||||||
this.deserializer}) {
|
this.deserializer}) {
|
||||||
_sendErrors = sendErrors;
|
|
||||||
|
|
||||||
if (serializer == null) serializer = god.serialize;
|
if (serializer == null) serializer = god.serialize;
|
||||||
if (deserializer == null) deserializer = (params) => params;
|
if (deserializer == null) deserializer = (params) => params;
|
||||||
}
|
}
|
||||||
|
@ -117,10 +100,6 @@ class AngelWebSocket extends AngelPlugin {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void _printDebug(String msg) {
|
|
||||||
if (debug == true) print(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Slates an event to be dispatched.
|
/// Slates an event to be dispatched.
|
||||||
Future batchEvent(WebSocketEvent event,
|
Future batchEvent(WebSocketEvent event,
|
||||||
{filter(WebSocketContext socket), bool notify: true}) async {
|
{filter(WebSocketContext socket), bool notify: true}) async {
|
||||||
|
@ -129,9 +108,6 @@ class AngelWebSocket extends AngelPlugin {
|
||||||
var result = true;
|
var result = true;
|
||||||
if (filter != null) result = await filter(client);
|
if (filter != null) result = await filter(client);
|
||||||
if (result == true) {
|
if (result == true) {
|
||||||
var serialized = event.toJson();
|
|
||||||
_printDebug('Batching this event: $serialized');
|
|
||||||
// print('Serialized: ' + JSON.encode(serialized));
|
|
||||||
client.io.add((serializer ?? god.serialize)(event.toJson()));
|
client.io.add((serializer ?? god.serialize)(event.toJson()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -150,7 +126,7 @@ class AngelWebSocket extends AngelPlugin {
|
||||||
if (split.length < 2)
|
if (split.length < 2)
|
||||||
return socket.sendError(new AngelHttpException.badRequest());
|
return socket.sendError(new AngelHttpException.badRequest());
|
||||||
|
|
||||||
var service = _app.service(split[0]);
|
var service = app.service(split[0]);
|
||||||
|
|
||||||
if (service == null)
|
if (service == null)
|
||||||
return socket.sendError(new AngelHttpException.notFound(
|
return socket.sendError(new AngelHttpException.notFound(
|
||||||
|
@ -170,7 +146,7 @@ class AngelWebSocket extends AngelPlugin {
|
||||||
var params = mergeMap([
|
var params = mergeMap([
|
||||||
(deserializer ?? (params) => params)(action.params),
|
(deserializer ?? (params) => params)(action.params),
|
||||||
{
|
{
|
||||||
"provider": Providers.WEBSOCKET,
|
"provider": Providers.websocket,
|
||||||
'__requestctx': socket.request,
|
'__requestctx': socket.request,
|
||||||
'__responsectx': socket.response
|
'__responsectx': socket.response
|
||||||
}
|
}
|
||||||
|
@ -204,13 +180,7 @@ class AngelWebSocket extends AngelPlugin {
|
||||||
message: "Method Not Allowed: \"$actionName\""));
|
message: "Method Not Allowed: \"$actionName\""));
|
||||||
}
|
}
|
||||||
} catch (e, st) {
|
} catch (e, st) {
|
||||||
if (e is AngelHttpException)
|
catchError(e, st, socket);
|
||||||
return socket.sendError(e);
|
|
||||||
else if (debug == true || _sendErrors == true)
|
|
||||||
socket.sendError(new AngelHttpException(e,
|
|
||||||
message: e.toString(), stackTrace: st, errors: [st.toString()]));
|
|
||||||
else
|
|
||||||
socket.sendError(new AngelHttpException(e));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,19 +198,13 @@ class AngelWebSocket extends AngelPlugin {
|
||||||
token = new AuthToken.validate(jwt, auth.hmac);
|
token = new AuthToken.validate(jwt, auth.hmac);
|
||||||
var user = await auth.deserializer(token.userId);
|
var user = await auth.deserializer(token.userId);
|
||||||
var req = socket.request;
|
var req = socket.request;
|
||||||
req..inject(AuthToken, req.properties['token'] = token)..inject(
|
req
|
||||||
user.runtimeType, req.properties["user"] = user);
|
..inject(AuthToken, req.properties['token'] = token)
|
||||||
|
..inject(user.runtimeType, req.properties["user"] = user);
|
||||||
socket.send(EVENT_AUTHENTICATED,
|
socket.send(EVENT_AUTHENTICATED,
|
||||||
{'token': token.serialize(auth.hmac), 'data': user});
|
{'token': token.serialize(auth.hmac), 'data': user});
|
||||||
} catch (e, st) {
|
} catch (e, st) {
|
||||||
// Send an error
|
catchError(e, st, socket);
|
||||||
if (e is AngelHttpException)
|
|
||||||
socket.sendError(e);
|
|
||||||
else if (debug == true || _sendErrors == true)
|
|
||||||
socket.sendError(new AngelHttpException(e,
|
|
||||||
message: e.toString(), stackTrace: st, errors: [st.toString()]));
|
|
||||||
else
|
|
||||||
socket.sendError(new AngelHttpException(e));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
socket.sendError(new AngelHttpException.badRequest(
|
socket.sendError(new AngelHttpException.badRequest(
|
||||||
|
@ -251,12 +215,15 @@ class AngelWebSocket extends AngelPlugin {
|
||||||
/// Hooks a service up to have its events broadcasted.
|
/// Hooks a service up to have its events broadcasted.
|
||||||
hookupService(Pattern _path, HookedService service) {
|
hookupService(Pattern _path, HookedService service) {
|
||||||
String path = _path.toString();
|
String path = _path.toString();
|
||||||
service.after([
|
service.after(
|
||||||
HookedServiceEvent.CREATED,
|
[
|
||||||
HookedServiceEvent.MODIFIED,
|
HookedServiceEvent.created,
|
||||||
HookedServiceEvent.UPDATED,
|
HookedServiceEvent.modified,
|
||||||
HookedServiceEvent.REMOVED
|
HookedServiceEvent.updated,
|
||||||
], serviceHook(path));
|
HookedServiceEvent.removed
|
||||||
|
],
|
||||||
|
serviceHook(path),
|
||||||
|
);
|
||||||
_servicesAlreadyWired.add(path);
|
_servicesAlreadyWired.add(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,14 +265,24 @@ class AngelWebSocket extends AngelPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e, st) {
|
} catch (e, st) {
|
||||||
|
catchError(e, st, socket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void catchError(e, StackTrace st, WebSocketContext socket) {
|
||||||
// Send an error
|
// Send an error
|
||||||
if (e is AngelHttpException)
|
if (e is AngelHttpException) {
|
||||||
socket.sendError(e);
|
socket.sendError(e);
|
||||||
else if (debug == true || _sendErrors == true)
|
app.logger?.severe(e.message, e.error ?? e, e.stackTrace);
|
||||||
socket.sendError(new AngelHttpException(e,
|
} else if (sendErrors) {
|
||||||
message: e.toString(), stackTrace: st, errors: [st.toString()]));
|
var err = new AngelHttpException(e,
|
||||||
else
|
message: e.toString(), stackTrace: st, errors: [st.toString()]);
|
||||||
socket.sendError(new AngelHttpException(e));
|
socket.sendError(err);
|
||||||
|
app.logger?.severe(err.message, e, st);
|
||||||
|
} else {
|
||||||
|
var err = new AngelHttpException(e);
|
||||||
|
socket.sendError(err);
|
||||||
|
app.logger?.severe(e.toString(), e, st);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,11 +301,9 @@ class AngelWebSocket extends AngelPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
/// Configiures an [Angel] instance to listen for WebSocket connections.
|
||||||
Future call(Angel app) async {
|
Future configureServer(Angel app) async {
|
||||||
if (_sendErrors == null) _sendErrors = app.isProduction;
|
app..container.singleton(this);
|
||||||
|
|
||||||
_app = app..container.singleton(this);
|
|
||||||
|
|
||||||
if (runtimeType != AngelWebSocket)
|
if (runtimeType != AngelWebSocket)
|
||||||
app.container.singleton(this, as: AngelWebSocket);
|
app.container.singleton(this, as: AngelWebSocket);
|
||||||
|
@ -340,7 +315,13 @@ class AngelWebSocket extends AngelPlugin {
|
||||||
wireAllServices(app);
|
wireAllServices(app);
|
||||||
});
|
});
|
||||||
|
|
||||||
handler(RequestContext req, ResponseContext res) async {
|
if (synchronizer != null) {
|
||||||
|
synchronizer.stream.listen((e) => batchEvent(e, notify: false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Handles an incoming HTTP request.
|
||||||
|
Future<bool> handleRequest(RequestContext req, ResponseContext res) async {
|
||||||
if (!WebSocketTransformer.isUpgradeRequest(req.io))
|
if (!WebSocketTransformer.isUpgradeRequest(req.io))
|
||||||
throw new AngelHttpException.badRequest();
|
throw new AngelHttpException.badRequest();
|
||||||
|
|
||||||
|
@ -359,30 +340,22 @@ class AngelWebSocket extends AngelPlugin {
|
||||||
..properties['socket'] = socket
|
..properties['socket'] = socket
|
||||||
..inject(WebSocketContext, socket);
|
..inject(WebSocketContext, socket);
|
||||||
|
|
||||||
ws.listen((data) {
|
ws.listen(
|
||||||
|
(data) {
|
||||||
_onData.add(data);
|
_onData.add(data);
|
||||||
handleData(socket, data);
|
handleData(socket, data);
|
||||||
}, onDone: () {
|
},
|
||||||
|
onDone: () {
|
||||||
_onDisconnect.add(socket);
|
_onDisconnect.add(socket);
|
||||||
_clients.remove(ws);
|
_clients.remove(ws);
|
||||||
}, onError: (e) {
|
},
|
||||||
|
onError: (e) {
|
||||||
_onDisconnect.add(socket);
|
_onDisconnect.add(socket);
|
||||||
_clients.remove(ws);
|
_clients.remove(ws);
|
||||||
}, cancelOnError: true);
|
},
|
||||||
}
|
cancelOnError: true,
|
||||||
|
);
|
||||||
_register() {
|
return false;
|
||||||
if (register != null)
|
|
||||||
return register(app, handler);
|
|
||||||
else
|
|
||||||
app.get(endpoint, handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
await _register();
|
|
||||||
|
|
||||||
if (synchronizer != null) {
|
|
||||||
synchronizer.stream.listen((e) => batchEvent(e, notify: false));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,16 +78,7 @@ class WebSocketController extends Controller {
|
||||||
return app.runContained(fn, socket.request, socket.response);
|
return app.runContained(fn, socket.request, socket.response);
|
||||||
}
|
}
|
||||||
} catch (e, st) {
|
} catch (e, st) {
|
||||||
// Send an error
|
ws.catchError(e, st, socket);
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
10
pubspec.yaml
10
pubspec.yaml
|
@ -2,18 +2,18 @@ name: angel_websocket
|
||||||
description: WebSocket plugin for Angel.
|
description: WebSocket plugin for Angel.
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=1.19.0"
|
sdk: ">=1.19.0"
|
||||||
version: 1.0.8
|
version: 1.1.0-alpha
|
||||||
author: Tobe O <thosakwe@gmail.com>
|
author: Tobe O <thosakwe@gmail.com>
|
||||||
homepage: https://github.com/angel-dart/angel_websocket
|
homepage: https://github.com/angel-dart/angel_websocket
|
||||||
dependencies:
|
dependencies:
|
||||||
angel_auth: ^1.0.0-dev
|
angel_auth: ^1.1.0-alpha
|
||||||
angel_client: "^1.0.0"
|
angel_client: ^1.1.0-alpha
|
||||||
angel_framework: ^1.0.0-dev
|
angel_framework: ^1.1.0-alpha
|
||||||
http: ">=0.11.0 <0.12.0"
|
http: ">=0.11.0 <0.12.0"
|
||||||
json_god: ^2.0.0-beta
|
json_god: ^2.0.0-beta
|
||||||
merge_map: ^1.0.0
|
merge_map: ^1.0.0
|
||||||
|
meta: ^1.0.0
|
||||||
uuid: "^0.5.3"
|
uuid: "^0.5.3"
|
||||||
web_socket_channel: "^1.0.0"
|
web_socket_channel: "^1.0.0"
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
angel_diagnostics: "^1.0.0"
|
|
||||||
test: "^0.12.15"
|
test: "^0.12.15"
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:angel_auth/angel_auth.dart';
|
import 'package:angel_auth/angel_auth.dart';
|
||||||
import 'package:angel_client/io.dart' as c;
|
import 'package:angel_client/io.dart' as c;
|
||||||
import 'package:angel_diagnostics/angel_diagnostics.dart';
|
|
||||||
import 'package:angel_framework/angel_framework.dart';
|
import 'package:angel_framework/angel_framework.dart';
|
||||||
import 'package:angel_websocket/io.dart' as c;
|
import 'package:angel_websocket/io.dart' as c;
|
||||||
import 'package:angel_websocket/server.dart';
|
import 'package:angel_websocket/server.dart';
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
const Map<String, String> USER = const {'username': 'foo', 'password': 'bar'};
|
const Map<String, String> USER = const {'username': 'foo', 'password': 'bar'};
|
||||||
|
@ -27,10 +27,11 @@ main() {
|
||||||
|
|
||||||
app.post('/auth/local', auth.authenticate('local'));
|
app.post('/auth/local', auth.authenticate('local'));
|
||||||
|
|
||||||
await app.configure(auth);
|
await app.configure(auth.configureServer);
|
||||||
var sock = new AngelWebSocket();
|
var sock = new AngelWebSocket(app);
|
||||||
await app.configure(sock);
|
await app.configure(sock.configureServer);
|
||||||
await app.configure(logRequests());
|
app.all('/ws', sock.handleRequest);
|
||||||
|
app.logger = new Logger('angel_auth')..onRecord.listen(print);
|
||||||
|
|
||||||
var server = await app.startServer();
|
var server = await app.startServer();
|
||||||
client = new c.Rest('http://${server.address.address}:${server.port}');
|
client = new c.Rest('http://${server.address.address}:${server.port}');
|
||||||
|
@ -38,12 +39,13 @@ main() {
|
||||||
await ws.connect();
|
await ws.connect();
|
||||||
});
|
});
|
||||||
|
|
||||||
tearDown(() =>
|
tearDown(() {
|
||||||
Future.wait([
|
return Future.wait([
|
||||||
app.close(),
|
app.close(),
|
||||||
client.close(),
|
client.close(),
|
||||||
ws.close()
|
ws.close(),
|
||||||
]));
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
test('auth event fires', () async {
|
test('auth event fires', () async {
|
||||||
var localAuth = await client.authenticate(type: 'local', credentials: USER);
|
var localAuth = await client.authenticate(type: 'local', credentials: USER);
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:angel_diagnostics/angel_diagnostics.dart';
|
|
||||||
import 'package:angel_framework/angel_framework.dart' as srv;
|
import 'package:angel_framework/angel_framework.dart' as srv;
|
||||||
import 'package:angel_websocket/io.dart' as ws;
|
import 'package:angel_websocket/io.dart' as ws;
|
||||||
import 'package:angel_websocket/server.dart' as srv;
|
import 'package:angel_websocket/server.dart' as srv;
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
import 'common.dart';
|
import 'common.dart';
|
||||||
|
|
||||||
|
@ -16,14 +16,15 @@ main() {
|
||||||
setUp(() async {
|
setUp(() async {
|
||||||
app = new srv.Angel();
|
app = new srv.Angel();
|
||||||
|
|
||||||
websockets = new srv.AngelWebSocket(debug: true)
|
websockets = new srv.AngelWebSocket(app)
|
||||||
..onData.listen((data) {
|
..onData.listen((data) {
|
||||||
print('Received by server: $data');
|
print('Received by server: $data');
|
||||||
});
|
});
|
||||||
|
|
||||||
await app.configure(websockets);
|
await app.configure(websockets.configureServer);
|
||||||
|
app.all('/ws', websockets.handleRequest);
|
||||||
await app.configure(new GameController());
|
await app.configure(new GameController());
|
||||||
await app.configure(logRequests(new File('log.txt')));
|
app.logger = new Logger('angel_auth')..onRecord.listen(print);
|
||||||
|
|
||||||
server = await app.startServer();
|
server = await app.startServer();
|
||||||
url = 'ws://${server.address.address}:${server.port}/ws';
|
url = 'ws://${server.address.address}:${server.port}/ws';
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:angel_diagnostics/angel_diagnostics.dart';
|
|
||||||
import 'package:angel_framework/angel_framework.dart' as srv;
|
import 'package:angel_framework/angel_framework.dart' as srv;
|
||||||
import 'package:angel_websocket/io.dart' as ws;
|
import 'package:angel_websocket/io.dart' as ws;
|
||||||
import 'package:angel_websocket/server.dart' as srv;
|
import 'package:angel_websocket/server.dart' as srv;
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
import 'common.dart';
|
import 'common.dart';
|
||||||
|
|
||||||
|
@ -16,13 +16,14 @@ main() {
|
||||||
setUp(() async {
|
setUp(() async {
|
||||||
app = new srv.Angel()..use('/api/todos', new TodoService());
|
app = new srv.Angel()..use('/api/todos', new TodoService());
|
||||||
|
|
||||||
websockets = new srv.AngelWebSocket(debug: true)
|
websockets = new srv.AngelWebSocket(app)
|
||||||
..onData.listen((data) {
|
..onData.listen((data) {
|
||||||
print('Received by server: $data');
|
print('Received by server: $data');
|
||||||
});
|
});
|
||||||
|
|
||||||
await app.configure(websockets);
|
await app.configure(websockets.configureServer);
|
||||||
await app.configure(logRequests(new File('log.txt')));
|
app.all('/ws', websockets.handleRequest);
|
||||||
|
app.logger = new Logger('angel_auth')..onRecord.listen(print);
|
||||||
server = await app.startServer();
|
server = await app.startServer();
|
||||||
url = 'ws://${server.address.address}:${server.port}/ws';
|
url = 'ws://${server.address.address}:${server.port}/ws';
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue