// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. // ignore_for_file: only_throw_errors import 'dart:async'; import 'package:shelf/shelf.dart'; import 'package:test/test.dart'; import 'test_util.dart'; void main() { test('forwards the request and response if both handlers are null', () async { var handler = const Pipeline() .addMiddleware(createMiddleware()) .addHandler((request) { return syncHandler(request, headers: {'from': 'innerHandler'}); }); final response = await makeSimpleRequest(handler); expect(response.headers['from'], 'innerHandler'); }); group('requestHandler', () { test('sync null response forwards to inner handler', () async { var handler = const Pipeline() .addMiddleware(createMiddleware(requestHandler: (request) => null)) .addHandler(syncHandler); final response = await makeSimpleRequest(handler); expect(response.headers['from'], isNull); }); test('async null response forwards to inner handler', () async { var handler = const Pipeline() .addMiddleware( createMiddleware(requestHandler: (request) => Future.value(null))) .addHandler(syncHandler); final response = await makeSimpleRequest(handler); expect(response.headers['from'], isNull); }); test('sync response is returned', () async { var handler = const Pipeline() .addMiddleware(createMiddleware( requestHandler: (request) => _middlewareResponse)) .addHandler(_failHandler); final response = await makeSimpleRequest(handler); expect(response.headers['from'], 'middleware'); }); test('async response is returned', () async { var handler = const Pipeline() .addMiddleware(createMiddleware( requestHandler: (request) => Future.value(_middlewareResponse))) .addHandler(_failHandler); final response = await makeSimpleRequest(handler); expect(response.headers['from'], 'middleware'); }); group('with responseHandler', () { test('with sync result, responseHandler is not called', () async { var middleware = createMiddleware( requestHandler: (request) => _middlewareResponse, responseHandler: (response) => fail('should not be called')); var handler = const Pipeline().addMiddleware(middleware).addHandler(syncHandler); final response = await makeSimpleRequest(handler); expect(response.headers['from'], 'middleware'); }); test('with async result, responseHandler is not called', () async { var middleware = createMiddleware( requestHandler: (request) => Future.value(_middlewareResponse), responseHandler: (response) => fail('should not be called')); var handler = const Pipeline().addMiddleware(middleware).addHandler(syncHandler); final response = await makeSimpleRequest(handler); expect(response.headers['from'], 'middleware'); }); }); }); group('responseHandler', () { test('innerHandler sync response is seen, replaced value continues', () async { var handler = const Pipeline() .addMiddleware(createMiddleware(responseHandler: (response) { expect(response.headers['from'], 'handler'); return _middlewareResponse; })).addHandler((request) { return syncHandler(request, headers: {'from': 'handler'}); }); final response = await makeSimpleRequest(handler); expect(response.headers['from'], 'middleware'); }); test('innerHandler async response is seen, async value continues', () async { var handler = const Pipeline() .addMiddleware(createMiddleware(responseHandler: (response) { expect(response.headers['from'], 'handler'); return Future.value(_middlewareResponse); })).addHandler((request) { return Future(() => syncHandler(request, headers: {'from': 'handler'})); }); final response = await makeSimpleRequest(handler); expect(response.headers['from'], 'middleware'); }); }); group('error handling', () { test('sync error thrown by requestHandler bubbles down', () { var handler = const Pipeline() .addMiddleware(createMiddleware( requestHandler: (request) => throw 'middleware error')) .addHandler(_failHandler); expect(makeSimpleRequest(handler), throwsA('middleware error')); }); test('async error thrown by requestHandler bubbles down', () { var handler = const Pipeline() .addMiddleware(createMiddleware( requestHandler: (request) => Future.error('middleware error'))) .addHandler(_failHandler); expect(makeSimpleRequest(handler), throwsA('middleware error')); }); test('throw from responseHandler does not hit error handler', () { var middleware = createMiddleware( responseHandler: (response) { throw 'middleware error'; }, errorHandler: (e, s) => fail('should never get here')); var handler = const Pipeline().addMiddleware(middleware).addHandler(syncHandler); expect(makeSimpleRequest(handler), throwsA('middleware error')); }); test('requestHandler throw does not hit errorHandlers', () { var middleware = createMiddleware( requestHandler: (request) { throw 'middleware error'; }, errorHandler: (e, s) => fail('should never get here')); var handler = const Pipeline().addMiddleware(middleware).addHandler(syncHandler); expect(makeSimpleRequest(handler), throwsA('middleware error')); }); test('inner handler throws, is caught by errorHandler with response', () async { var middleware = createMiddleware(errorHandler: (error, stack) { expect(error, 'bad handler'); return _middlewareResponse; }); var handler = const Pipeline().addMiddleware(middleware).addHandler((request) { throw 'bad handler'; }); final response = await makeSimpleRequest(handler); expect(response.headers['from'], 'middleware'); }); test('inner handler throws, is caught by errorHandler and rethrown', () { var middleware = createMiddleware(errorHandler: (Object error, stack) { expect(error, 'bad handler'); throw error; }); var handler = const Pipeline().addMiddleware(middleware).addHandler((request) { throw 'bad handler'; }); expect(makeSimpleRequest(handler), throwsA('bad handler')); }); test( 'error thrown by inner handler without a middleware errorHandler is ' 'rethrown', () { var middleware = createMiddleware(); var handler = const Pipeline().addMiddleware(middleware).addHandler((request) { throw 'bad handler'; }); expect(makeSimpleRequest(handler), throwsA('bad handler')); }); test("doesn't handle HijackException", () { var middleware = createMiddleware(errorHandler: (error, stack) { fail("error handler shouldn't be called"); }); var handler = const Pipeline() .addMiddleware(middleware) .addHandler((request) => throw const HijackException()); expect(makeSimpleRequest(handler), throwsHijackException); }); }); } Response _failHandler(Request request) => fail('should never get here'); final Response _middlewareResponse = Response.ok('middleware content', headers: {'from': 'middleware'});