platform/packages/shelf/lib/src/shelf_driver.dart
2021-06-20 20:37:20 +08:00

153 lines
4.5 KiB
Dart

import 'dart:async';
import 'dart:io';
import 'package:angel_framework/angel_framework.dart';
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf.dart';
import 'shelf_request.dart';
import 'shelf_response.dart';
class AngelShelf extends Driver<shelf.Request, ShelfResponseContext?,
Stream<shelf.Request>, ShelfRequestContext, ShelfResponseContext> {
final StreamController<shelf.Request> incomingRequests = StreamController();
final FutureOr<shelf.Response> Function()? notFound;
AngelShelf(Angel app, {FutureOr<shelf.Response> Function()? notFound})
: notFound = notFound ?? (() => shelf.Response.notFound('Not Found')),
super(app, null, useZone: false) {
// Inject a final handler that will keep responses open, if we are using the
// driver as a middleware.
app.fallback((req, res) {
if (res is ShelfResponseContext) {
res.closeSilently();
}
return true;
});
}
Future<Stream<Request>> aaa(dynamic param1, int param2) {}
@override
Future<void> close() {
incomingRequests.close();
return super.close();
}
@override
Future<Stream<shelf.Request>> Function(dynamic, int) get serverGenerator =>
(_, __) async => incomingRequests.stream;
static UnsupportedError _unsupported() => UnsupportedError(
'AngelShelf cannot mount a standalone server, or return a URI.');
Future<shelf.Response> handler(shelf.Request request) async {
var response = ShelfResponseContext(app);
var result = await handleRawRequest(request, response);
if (result is shelf.Response) {
return result;
} else if (!response.isOpen) {
return response.shelfResponse;
} else {
// return await handler(request);
return notFound!();
}
}
shelf.Handler middleware(shelf.Handler handler) {
return (request) async {
var response = ShelfResponseContext(app);
var result = await handleRawRequest(request, response);
if (result is shelf.Response) {
return result;
} else if (!response.isOpen) {
return response.shelfResponse;
} else {
return await handler(request);
}
};
}
@override
Future<shelf.Response> handleAngelHttpException(
AngelHttpException e,
StackTrace st,
RequestContext? req,
ResponseContext? res,
shelf.Request request,
ShelfResponseContext? response,
{bool ignoreFinalizers = false}) async {
await super.handleAngelHttpException(e, st, req, res, request, response,
ignoreFinalizers: ignoreFinalizers);
return response!.shelfResponse;
}
@override
void addCookies(ShelfResponseContext? response, Iterable<Cookie> 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<ShelfRequestContext> createRequestContext(
shelf.Request request, ShelfResponseContext? response) {
var path = request.url.path.replaceAll(_straySlashes, '');
if (path.isEmpty) path = '/';
var rq =
ShelfRequestContext(app, app.container!.createChild(), request, path);
return Future.value(rq);
}
@override
Future<ShelfResponseContext> createResponseContext(
shelf.Request request, ShelfResponseContext? response,
[ShelfRequestContext? correspondingRequest]) {
// Return the original response.
return Future.value(response..correspondingRequest = correspondingRequest);
}
@override
Stream<ShelfResponseContext?> 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<int> data) {
response!.add(data);
}
}