platform/lib/src/convert.dart

67 lines
2.6 KiB
Dart
Raw Normal View History

2017-06-12 23:53:08 +00:00
import 'dart:async';
import 'dart:io';
import 'package:angel_framework/angel_framework.dart';
import 'package:shelf/shelf.dart' as shelf;
/// Creates a [shelf.Request] analogous to the input [request].
///
/// The new request's `context` will contain [request.properties] as `angel_shelf.properties`, as well as
/// the provided [context], if any.
///
/// The context will also have the original request available as `angel_shelf.request`.
///
/// If you want to read the request body, you *must* `storeOriginalBuffer` to `true`
/// on your application instance.
Future<shelf.Request> convertRequest(RequestContext request,
{String handlerPath, Map<String, Object> context}) async {
var headers = <String, String>{};
request.headers.forEach((k, v) {
headers[k] = v.join(',');
});
headers.remove(HttpHeaders.TRANSFER_ENCODING);
void onHijack(
void hijack(Stream<List<int>> stream, StreamSink<List<int>> sink)) {
request.io.response.detachSocket(writeHeaders: false).then((socket) {
return request.lazyOriginalBuffer().then((buf) {
var ctrl = new StreamController<List<int>>()..add(buf ?? []);
socket.listen(ctrl.add, onError: ctrl.addError, onDone: ctrl.close);
hijack(socket, socket);
});
}).catchError((e, st) {
stderr.writeln('An error occurred while hijacking a shelf request: $e');
stderr.writeln(st);
});
}
return new shelf.Request(request.method, request.io.requestedUri,
protocolVersion: request.io.protocolVersion,
headers: headers,
handlerPath: handlerPath,
url: new Uri(
path: request.io.requestedUri.path.substring(1),
query: request.io.requestedUri.query),
body: (await request.lazyOriginalBuffer()) ?? [],
context: {'angel_shelf.request': request}
..addAll({'angel_shelf.properties': request.properties})
..addAll(context ?? {}),
onHijack: onHijack);
}
/// Applies the state of the [shelfResponse] into the [angelResponse].
///
/// Merges all headers, sets the status code, and writes the body.
///
/// In addition, the response's context will be available in `angelResponse.properties`
/// as `shelf_context`.
Future mergeShelfResponse(
shelf.Response shelfResponse, ResponseContext angelResponse) async {
angelResponse.headers.addAll(shelfResponse.headers);
angelResponse.statusCode = shelfResponse.statusCode;
angelResponse.properties['shelf_context'] = shelfResponse.context;
2017-06-20 16:23:10 +00:00
angelResponse.properties['shelf_response'] = shelfResponse;
2017-06-12 23:53:08 +00:00
await shelfResponse.read().forEach(angelResponse.buffer.add);
angelResponse.end();
}