diff --git a/.gitignore b/.gitignore index 8078e48d..c40e7bad 100644 --- a/.gitignore +++ b/.gitignore @@ -21,9 +21,9 @@ doc/api/ *.js.map *.o -*.dylib +# *.dylib *.a -*.so +# *.so *.lib *.obj diff --git a/Makefile b/Makefile index 07bb2b86..6ac0c8ed 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ libangel_wings.dylib: lib/src/libangel_wings.dylib lib/src/libangel_wings.dylib: $(objects) %.dylib: $(objects) - $(CXX) -shared -undefined dynamic_lookup -o $@ $^ + $(CXX) -shared -Wl,-undefined -Wl,dynamic_lookup -o $@ $^ %.so: $(objects) $(CXX) -shared -o $@ $^ diff --git a/example/main.dart b/example/main.dart index b14aeae2..c5f4e13d 100644 --- a/example/main.dart +++ b/example/main.dart @@ -3,6 +3,7 @@ import 'package:angel_static/angel_static.dart'; import 'package:angel_wings/angel_wings.dart'; import 'package:file/local.dart'; import 'package:logging/logging.dart'; +import 'pretty_log.dart'; main() async { var app = Angel(); @@ -10,17 +11,14 @@ main() async { var fs = LocalFileSystem(); var vDir = CachingVirtualDirectory(app, fs, source: fs.currentDirectory, allowDirectoryListing: true); - app.logger = Logger('wings') - ..onRecord.listen((rec) { - print(rec); - if (rec.error != null) print(rec.error); - if (rec.stackTrace != null) print(rec.stackTrace); - }); + + app.logger = Logger('wings')..onRecord.listen(prettyLog); + app.mimeTypeResolver.addExtension('yaml', 'text/x-yaml'); app.get('/', (req, res) => 'WINGS!!!'); app.fallback(vDir.handleRequest); app.fallback((req, res) => throw AngelHttpException.notFound()); await wings.startServer('127.0.0.1', 3000); - print('Listening at http://localhost:3000'); + print('Listening at ${wings.uri}'); } diff --git a/example/pretty_log.dart b/example/pretty_log.dart new file mode 100644 index 00000000..079cf258 --- /dev/null +++ b/example/pretty_log.dart @@ -0,0 +1,35 @@ +import 'package:angel_http_exception/angel_http_exception.dart'; +import 'package:logging/logging.dart'; +import 'package:io/ansi.dart'; + +/// Prints the contents of a [LogRecord] with pretty colors. +void prettyLog(LogRecord record) { + var code = chooseLogColor(record.level); + + if (record.error == null) print(code.wrap(record.toString())); + + if (record.error != null) { + var err = record.error; + if (err is AngelHttpException && err.statusCode != 500) return; + print(code.wrap(record.toString() + '\n')); + print(code.wrap(err.toString())); + + if (record.stackTrace != null) { + print(code.wrap(record.stackTrace.toString())); + } + } +} + +/// Chooses a color based on the logger [level]. +AnsiCode chooseLogColor(Level level) { + if (level == Level.SHOUT) + return backgroundRed; + else if (level == Level.SEVERE) + return red; + else if (level == Level.WARNING) + return yellow; + else if (level == Level.INFO) + return cyan; + else if (level == Level.FINER || level == Level.FINEST) return lightGray; + return resetAll; +} \ No newline at end of file diff --git a/lib/src/libangel_wings.dylib b/lib/src/libangel_wings.dylib new file mode 100644 index 00000000..58a946f4 Binary files /dev/null and b/lib/src/libangel_wings.dylib differ diff --git a/lib/src/wings_driver.dart b/lib/src/wings_driver.dart index bc4bff0e..feda34f2 100644 --- a/lib/src/wings_driver.dart +++ b/lib/src/wings_driver.dart @@ -31,14 +31,17 @@ class AngelWings extends Driver createRequestContext(WingsClientSocket request, int response) { + Future createRequestContext( + WingsClientSocket request, int response) { return WingsRequestContext.from(app, request); } @override - Future createResponseContext(WingsClientSocket request, int response, + Future createResponseContext( + WingsClientSocket request, int response, [WingsRequestContext correspondingRequest]) { - return Future.value(WingsResponseContext(request.fileDescriptor, correspondingRequest)); + return Future.value(WingsResponseContext( + app, request.fileDescriptor, correspondingRequest)); } @override @@ -68,8 +71,9 @@ class AngelWings extends Driver null; + Uri get uri { + return Uri(scheme: 'http', host: server.address.address, port: server.port); + } @override void writeStringToResponse(int response, String value) { diff --git a/lib/src/wings_request.dart b/lib/src/wings_request.dart index 6b97e8e6..83203f29 100644 --- a/lib/src/wings_request.dart +++ b/lib/src/wings_request.dart @@ -28,6 +28,11 @@ class WingsRequestContext extends RequestContext { WingsRequestContext._(this.app, this.rawRequest, this._recv) : container = app.container.createChild(); + Future close() async { + await _body.close(); + _recv.close(); + } + static const int DELETE = 0, GET = 1, HEAD = 2, @@ -106,18 +111,19 @@ class WingsRequestContext extends RequestContext { if (e == 0) { state = _ParseState.method; } else { - lastHeader = e as String; + lastHeader = e as String; //Uri.decodeFull(e as String); state = _ParseState.headerValue; } } else if (state == _ParseState.headerValue) { if (e == 0) { state = _ParseState.method; } else { + var value = e as String; //Uri.decodeFull(e as String); if (lastHeader != null) { if (lastHeader == 'cookie') { - rq.__cookies.add(Cookie.fromSetCookieValue(e as String)); + rq.__cookies.add(Cookie.fromSetCookieValue(value)); } else { - rq._headers.add(lastHeader, e as String); + rq._headers.add(lastHeader, value); } lastHeader = null; } diff --git a/lib/src/wings_response.dart b/lib/src/wings_response.dart index cbc00794..206ea4b9 100644 --- a/lib/src/wings_response.dart +++ b/lib/src/wings_response.dart @@ -8,6 +8,9 @@ import 'wings_request.dart'; import 'wings_socket.dart'; class WingsResponseContext extends ResponseContext { + @override + final Angel app; + @override final WingsRequestContext correspondingRequest; @@ -18,7 +21,7 @@ class WingsResponseContext extends ResponseContext { bool _isDetached = false, _isClosed = false, _streamInitialized = false; - WingsResponseContext(this.rawResponse, [this.correspondingRequest]); + WingsResponseContext(this.app, this.rawResponse, [this.correspondingRequest]); Iterable __allowedEncodings; @@ -78,8 +81,9 @@ class WingsResponseContext extends ResponseContext { } void _wh(String k, String v) { - var headerLine = - utf8.encode('$k: ${Uri.encodeComponent(v)}').followedBy([$cr, $lf]); + // var vv =Uri.encodeComponent(v); + var vv = v; + var headerLine = utf8.encode('$k: $vv').followedBy([$cr, $lf]); writeToNativeSocket( rawResponse, Uint8List.fromList(headerLine.toList())); } @@ -127,8 +131,9 @@ class WingsResponseContext extends ResponseContext { } return output.forEach((buf) { - writeToNativeSocket( - rawResponse, buf is Uint8List ? buf : Uint8List.fromList(buf)); + if (!_isClosed) + writeToNativeSocket( + rawResponse, buf is Uint8List ? buf : Uint8List.fromList(buf)); }); } @@ -168,27 +173,21 @@ class WingsResponseContext extends ResponseContext { } @override - Future close() { + Future close() async { if (!_isDetached) { if (!_isClosed) { + _isClosed = true; if (!isBuffered) { - try { - _openStream(); - closeNativeSocketDescriptor(rawResponse); - } catch (_) { - // This only seems to occur on `MockHttpRequest`, but - // this try/catch prevents a crash. - } + _openStream(); + closeNativeSocketDescriptor(rawResponse); } else { _buffer.lock(); } - - _isClosed = true; } - super.close(); + await correspondingRequest?.close(); + await super.close(); } - return new Future.value(); } @override diff --git a/lib/src/wings_socket.dart b/lib/src/wings_socket.dart index 8b875f43..3a9a3c38 100644 --- a/lib/src/wings_socket.dart +++ b/lib/src/wings_socket.dart @@ -44,6 +44,7 @@ class WingsClientSocket { class WingsSocket extends Stream { final StreamController _ctrl = StreamController(); SendPort _acceptor; + InternetAddress _address; final int _pointer; final RawReceivePort _recv; bool _open = true; @@ -91,13 +92,15 @@ class WingsSocket extends Stream { addr.address, port, shared, backlog, v6Only, recv.sendPort); } - return WingsSocket._(ptr, recv); + return WingsSocket._(ptr, recv).._address = addr; } catch (e) { recv.close(); rethrow; } } + InternetAddress get address => _address; + int get port => _port ??= getWingsServerSocketPort(_pointer); @override diff --git a/libangel_wings.dylib b/libangel_wings.dylib new file mode 100644 index 00000000..58a946f4 Binary files /dev/null and b/libangel_wings.dylib differ diff --git a/pubspec.yaml b/pubspec.yaml index e24d2504..1d825c84 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -8,4 +8,5 @@ dependencies: dev_dependencies: angel_static: ^2.0.0 build_runner: ^1.0.0 + io: ^0.3.2 pedantic: ^1.0.0 \ No newline at end of file