| Index: pkg/shelf/lib/shelf_io.dart
|
| diff --git a/pkg/shelf/lib/shelf_io.dart b/pkg/shelf/lib/shelf_io.dart
|
| index 1bd4f5164def2a8d6d6dd6b390bf8087d0141355..d8d4d9ca3175e9b0cfea38c36302eeee00bfeb22 100644
|
| --- a/pkg/shelf/lib/shelf_io.dart
|
| +++ b/pkg/shelf/lib/shelf_io.dart
|
| @@ -6,6 +6,8 @@
|
| ///
|
| /// One can provide an instance of [HttpServer] as the `requests` parameter in
|
| /// [serveRequests].
|
| +///
|
| +/// The `dart:io` adapter supports request hijacking; see [Request.hijack].
|
| library shelf.io;
|
|
|
| import 'dart:async';
|
| @@ -53,15 +55,38 @@ void serveRequests(Stream<HttpRequest> requests, Handler handler) {
|
| Future handleRequest(HttpRequest request, Handler handler) {
|
| var shelfRequest = _fromHttpRequest(request);
|
|
|
| + // TODO(nweiz): abstract out hijack handling to make it easier to implement an
|
| + // adapter.
|
| return syncFuture(() => handler(shelfRequest))
|
| .catchError((error, stackTrace) {
|
| - return _logError('Error thrown by handler\n$error', stackTrace);
|
| + if (error is HijackException) {
|
| + // A HijackException should bypass the response-writing logic entirely.
|
| + if (!shelfRequest.canHijack) throw error;
|
| +
|
| + // If the request wasn't hijacked, we shouldn't be seeing this exception.
|
| + return _logError(
|
| + "Caught HijackException, but the request wasn't hijacked.",
|
| + stackTrace);
|
| + }
|
| +
|
| + return _logError('Error thrown by handler.\n$error', stackTrace);
|
| }).then((response) {
|
| if (response == null) {
|
| - response = _logError('null response from handler');
|
| + response = _logError('null response from handler.');
|
| + } else if (!shelfRequest.canHijack) {
|
| + var message = new StringBuffer()
|
| + ..writeln("Got a response for hijacked request "
|
| + "${shelfRequest.method} ${shelfRequest.requestedUri}:")
|
| + ..writeln(response.statusCode);
|
| + response.headers.forEach((key, value) =>
|
| + message.writeln("${key}: ${value}"));
|
| + throw new Exception(message.toString().trim());
|
| }
|
|
|
| return _writeResponse(response, request.response);
|
| + }).catchError((error, stackTrace) {
|
| + // Ignore HijackExceptions.
|
| + if (error is! HijackException) throw error;
|
| });
|
| }
|
|
|
| @@ -74,9 +99,14 @@ Request _fromHttpRequest(HttpRequest request) {
|
| headers[k] = v.join(',');
|
| });
|
|
|
| + onHijack(callback) {
|
| + return request.response.detachSocket(writeHeaders: false)
|
| + .then((socket) => callback(socket, socket));
|
| + }
|
| +
|
| return new Request(request.method, request.requestedUri,
|
| protocolVersion: request.protocolVersion, headers: headers,
|
| - body: request);
|
| + body: request, onHijack: onHijack);
|
| }
|
|
|
| Future _writeResponse(Response response, HttpResponse httpResponse) {
|
|
|