diff --git a/CHANGELOG.md b/CHANGELOG.md index 4392e1e..7345508 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 0.5.0 + +Websocket format is changed. + ## 0.4.0 Fix Websockets diff --git a/README.md b/README.md index 730c27a..582b6b6 100644 --- a/README.md +++ b/README.md @@ -21,11 +21,21 @@ void main() { }); app.ws('/socket').listen((socket) { - socket.on('ping').listen((data) => socket.send('pong')); - socket.on('pong').listen((data) => socket.close(1000, 'requested')); - }); - }); + socket.onMessage().listen((data) { + print('data: $data'); + socket.send(data); + }); + + socket.onOpen.listen((ws) { + print('new socket opened'); + }); + + socket.onClose.listen((ws) { + print('socket has been closed'); + }); + + }); } ``` @@ -37,7 +47,7 @@ You start the server with `start()` function. It has 3 named arguments and returns `Server` future ```dart -start({String host: '127.0.0.1', int port: 80}) +start({String host: '127.0.0.1', int port: 80, cors : false}) ``` ### Server @@ -93,7 +103,7 @@ render(viewName, [Map params]) // renders server view ```dart send(message) // sends message -on(message, action) // adds handler to message +onMessage() // adds handler to message close(status, reason) // closes socket ``` @@ -103,6 +113,8 @@ close(status, reason) // closes socket Copyright (c) 2012 Yehor Lvivski +Copyright (c) 2020 Benjamin Jung + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including diff --git a/example/app.dart b/example/app.dart index 6fea2bb..dc824ed 100644 --- a/example/app.dart +++ b/example/app.dart @@ -38,13 +38,10 @@ void main() { }); }); - app.ws('/socket').listen((socket) { - socket.on('connected').listen((data) { - socket.send('ping', 'data-from-ping'); - }); + app.ws('/').listen((socket) { - socket.on('pong').listen((data) { - print('pong: $data'); + socket.onMessage().listen((data) { + print('msg: $data'); socket.close(1000, 'requested'); }); diff --git a/lib/socket.dart b/lib/socket.dart index 928f7e0..9bf562b 100644 --- a/lib/socket.dart +++ b/lib/socket.dart @@ -14,19 +14,17 @@ class Socket implements SocketBase { this._ws = new WebSocket(url) { _messages = _messageController.stream.asBroadcastStream(); _ws.onMessage.listen((e) { - var msg = new Message.fromPacket(e.data); + var msg = e.data; _messageController.add(msg); }); } - void send(String messageName, [ data ]) { - var message = new Message(messageName, data); - _ws.send(message.toPacket()); + void send(String message) { + _ws.send(message); } - Stream on(String messageName) { - return _messages.where((msg) => msg.name == messageName).map((msg) => - msg.data); + Stream onMessage() { + return _messages; } Stream get onOpen => _ws.onOpen; @@ -36,4 +34,4 @@ class Socket implements SocketBase { void close([int status, String reason]) { _ws.close(status, reason); } -} \ No newline at end of file +} diff --git a/lib/src/message.dart b/lib/src/message.dart deleted file mode 100644 index 28c6b9c..0000000 --- a/lib/src/message.dart +++ /dev/null @@ -1,35 +0,0 @@ -library start_message; - -import 'dart:convert'; - -class Message { - final String name; - final Object data; - - Message(this.name, [this.data]); - - factory Message.fromPacket(String message) { - if (message.isEmpty) { - return new Message.empty(); - } - - List parts = message.split(':'); - String name = parts.first; - var data = null; - - if (parts.length > 1 && !parts[1].isEmpty) { - data = jsonDecode(parts.sublist(1).join(':')); - } - - return new Message(name, data); - } - - Message.empty() : this(''); - - String toPacket() { - if (data == null) { - return name; - } - return '$name:${jsonEncode(data)}'; - } -} \ No newline at end of file diff --git a/lib/src/request.dart b/lib/src/request.dart index 0273ca3..ea9d39a 100644 --- a/lib/src/request.dart +++ b/lib/src/request.dart @@ -13,7 +13,7 @@ class Request { .where((name) => name.split(',').indexOf(type) > 0) .length > 0; - bool isMime(String type, {loose: false}) => + bool isMime(String type, {loose: true}) => _request.headers[HttpHeaders.contentTypeHeader] .where((value) => loose ? value.contains(type) : value == type) .isNotEmpty; diff --git a/lib/src/route.dart b/lib/src/route.dart index edb2633..b9fda60 100644 --- a/lib/src/route.dart +++ b/lib/src/route.dart @@ -8,21 +8,19 @@ class Route { Stream requestStream; Stream socketStream; - Route(String method, path, { List keys }) - : + Route(String method, path, { List keys }) : _method = method.toUpperCase(), _path = _normalize(path, keys: keys) { requestStream = _requestController.stream; } - Route.ws(dynamic path, { List keys }) - : + Route.ws(dynamic path, { List keys }) : _method = 'WS', _path = _normalize(path, keys: keys) { socketStream = _socketController.stream .transform(new WebSocketTransformer()) .map((WebSocket ws) => new Socket(ws)); - } + } bool match(HttpRequest req) { return ((_method == req.method || _method == 'WS') @@ -33,15 +31,14 @@ class Route { if (_method == 'WS') { _socketController.add(req); } else { - var request = new Request(req); + var request = new Request(req); request.params = _parseParams(req.uri.path, _path); request.response = new Response(req.response); _requestController.add(request); } } - static Map _normalize(dynamic path, - { List keys, bool strict: false }) { + static Map _normalize(dynamic path, { List keys, bool strict: false }) { if (keys == null) { keys = []; } diff --git a/lib/src/server.dart b/lib/src/server.dart index 3599675..e24994d 100644 --- a/lib/src/server.dart +++ b/lib/src/server.dart @@ -16,11 +16,18 @@ class Server { } Future listen(String host, num port, - {String certificateChain, String privateKey, String password}) { + {String certificateChain, String privateKey, String password, bool cors}) { handle(HttpServer server) { _server = server; server.listen((HttpRequest req) { + if (cors) { + addCorsHeaders(req.response); + if (req.method.toLowerCase() == 'options') { + _sendDummy(req); + return; + } + } var route = _routes.firstWhere((Route route) => route.match(req), orElse: () => null); if (route != null) { @@ -50,6 +57,13 @@ class Server { return HttpServer.bind(host, port).then(handle); } + void addCorsHeaders(HttpResponse response) { + response.headers.add('Access-Control-Allow-Origin', '*'); + response.headers.add('Access-Control-Allow-Methods', 'GET,HEAD,PUT,PATCH,POST,DELETE'); + response.headers.add('Access-Control-Allow-Headers', + 'access-control-allow-origin,content-type,x-access-token'); + } + void static(path, { listing: true, links: true, jail: true }) { _staticServer = new VirtualDirectory(path) ..allowDirectoryListing = listing @@ -106,6 +120,13 @@ class Server { return route.requestStream; } + void _sendDummy(HttpRequest req) { + var msg = {}; + msg['status'] = 'ok'; + req.response.write(jsonEncode(msg)); + req.response.close(); + } + void _send404(HttpRequest req) { req.response ..statusCode = HttpStatus.notFound diff --git a/lib/src/socket.dart b/lib/src/socket.dart index 9a01aea..d47a476 100644 --- a/lib/src/socket.dart +++ b/lib/src/socket.dart @@ -13,22 +13,19 @@ class Socket implements SocketBase { _openController.add(_ws); _ws.listen((data) { - var msg = new Message.fromPacket(data); - _messageController.add(msg); + _messageController.add(data); }, onDone: () { _closeController.add(_ws); }); } - void send(String messageName, [ data ]) { - var message = new Message(messageName, data); - _ws.add(message.toPacket()); + void send(String message) { + _ws.add(message); } - Stream on(String messageName) { - return _messages.where((msg) => msg.name == messageName).map((msg) => - msg.data); + Stream onMessage() { + return _messages; } Stream get onOpen => _openController.stream; diff --git a/lib/src/socket_base.dart b/lib/src/socket_base.dart index 76c4247..332b7d4 100644 --- a/lib/src/socket_base.dart +++ b/lib/src/socket_base.dart @@ -2,12 +2,10 @@ library start_socket; import 'dart:async'; -export 'message.dart' show Message; - abstract class SocketBase { - void send(String msg_name, [ data ]); + void send(String msg); - Stream on(String message_name); + Stream onMessage(); void close([int status, String reason]); } diff --git a/lib/start.dart b/lib/start.dart index 563bc8b..2e7e579 100644 --- a/lib/start.dart +++ b/lib/start.dart @@ -20,6 +20,6 @@ part 'src/server.dart'; part 'src/socket.dart'; -Future start({ String host: '127.0.0.1', int port: 80, String certificateChain, String privateKey, String password}) { - return new Server().listen(host, port, certificateChain: certificateChain, privateKey: privateKey, password: password); +Future start({ String host: '127.0.0.1', int port: 80, String certificateChain, String privateKey, String password, bool cors:false}) { + return new Server().listen(host, port, certificateChain: certificateChain, privateKey: privateKey, password: password, cors: cors); } diff --git a/pubspec.yaml b/pubspec.yaml index 9593a15..afcad66 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: start -author: Yehor Lvivski -version: 0.4.0 +author: Yehor Lvivski , Benjamin Jung +version: 0.5.0 homepage: http://github.com/lvivski/start description: Sinatra inspired Web framework environment: