From b84da76815ce8971dd204924fbd3d1bdacbfd06f Mon Sep 17 00:00:00 2001 From: Tobe O Date: Mon, 14 Oct 2019 11:54:55 -0400 Subject: [PATCH] Base AngelShelf impl --- lib/src/shelf_driver.dart | 91 +++++++++++++++++++++++++++++++++++++ lib/src/shelf_response.dart | 15 +++++- 2 files changed, 104 insertions(+), 2 deletions(-) diff --git a/lib/src/shelf_driver.dart b/lib/src/shelf_driver.dart index e69de29b..0467175a 100644 --- a/lib/src/shelf_driver.dart +++ b/lib/src/shelf_driver.dart @@ -0,0 +1,91 @@ +import 'dart:async'; +import 'dart:io'; +import 'package:angel_framework/angel_framework.dart'; +import 'package:shelf/shelf.dart' as shelf; +import 'shelf_request.dart'; +import 'shelf_response.dart'; + +class AngelShelf extends Driver, ShelfRequestContext, ShelfResponseContext> { + AngelShelf.custom(Angel app, {bool useZone = true}) + : super(app, (_, __) => throw _unsupported(), useZone: useZone); + + static UnsupportedError _unsupported() => UnsupportedError( + 'AngelShelf cannot mount a standalone server, or return a URI.'); + + Future handler(shelf.Request request) async { + var response = ShelfResponseContext(app); + await handleRawRequest(request, response); + return response.shelfResponse; + } + + @override + void addCookies(ShelfResponseContext response, Iterable cookies) { + // Don't do anything here, otherwise you get duplicate cookies. + // response.cookies.addAll(cookies); + } + + @override + Future closeResponse(ShelfResponseContext response) { + return response.close(); + } + + @override + Uri get uri => throw _unsupported(); + + static final RegExp _straySlashes = RegExp(r'(^/+)|(/+$)'); + + @override + Future createRequestContext( + shelf.Request request, ShelfResponseContext response) { + var path = uri.path.replaceAll(_straySlashes, ''); + if (path.isEmpty) path = '/'; + var rq = + ShelfRequestContext(app, app.container.createChild(), request, path); + return Future.value(rq); + } + + @override + Future createResponseContext( + shelf.Request request, ShelfResponseContext response, + [ShelfRequestContext correspondingRequest]) { + // Return the original response. + return Future.value(response..correspondingRequest = correspondingRequest); + } + + @override + Stream createResponseStreamFromRawRequest( + shelf.Request request) { + return Stream.fromIterable([null]); + } + + @override + void setChunkedEncoding(ShelfResponseContext response, bool value) { + response.chunked = value; + } + + @override + void setContentLength(ShelfResponseContext response, int length) { + response.contentLength = length; + } + + @override + void setHeader(ShelfResponseContext response, String key, String value) { + response.headers[key] = value; + } + + @override + void setStatusCode(ShelfResponseContext response, int value) { + response.statusCode = value; + } + + @override + void writeStringToResponse(ShelfResponseContext response, String value) { + response.write(value); + } + + @override + void writeToResponse(ShelfResponseContext response, List data) { + response.add(data); + } +} diff --git a/lib/src/shelf_response.dart b/lib/src/shelf_response.dart index e671c236..8e03fda9 100644 --- a/lib/src/shelf_response.dart +++ b/lib/src/shelf_response.dart @@ -7,11 +7,22 @@ import 'shelf_request.dart'; class ShelfResponseContext extends ResponseContext { final Angel app; - final ShelfRequestContext correspondingRequest; final StreamController> _ctrl = StreamController(); bool _isOpen = true, _isDetached = false; - ShelfResponseContext(this.app, this.correspondingRequest); + ShelfResponseContext(this.app); + + ShelfRequestContext _correspondingRequest; + + ShelfRequestContext get correspondingRequest => _correspondingRequest; + + set correspondingRequest(ShelfRequestContext value) { + if (_correspondingRequest == null) { + _correspondingRequest = value; + } else { + throw StateError('The corresponding request has already been assigned.'); + } + } shelf.Response get shelfResponse { return shelf.Response(statusCode, body: _ctrl.stream, headers: headers);