handleRequest function

Future<void> handleRequest(
  1. HttpRequest request,
  2. Handler handler,
  3. {String? poweredByHeader = 'Dart with package:shelf'}
)

Uses handler to handle request.

Returns a Future which completes when the request has been handled.

Every response will get a "date" header and an "X-Powered-By" header. If the either header is present in the Response, it will not be overwritten. Pass poweredByHeader to set the default content for "X-Powered-By", pass null to omit this header.

Implementation

Future<void> handleRequest(
  HttpRequest request,
  Handler handler, {
  String? poweredByHeader = 'Dart with package:shelf',
}) async {
  Request shelfRequest;
  try {
    shelfRequest = _fromHttpRequest(request);
    // ignore: avoid_catching_errors
  } on ArgumentError catch (error, stackTrace) {
    if (error.name == 'method' || error.name == 'requestedUri') {
      // TODO: use a reduced log level when using package:logging
      _logTopLevelError('Error parsing request.\n$error', stackTrace);
      final response = Response(
        400,
        body: 'Bad Request',
        headers: {HttpHeaders.contentTypeHeader: 'text/plain'},
      );
      await _writeResponse(response, request.response, poweredByHeader);
    } else {
      _logTopLevelError('Error parsing request.\n$error', stackTrace);
      final response = Response.internalServerError();
      await _writeResponse(response, request.response, poweredByHeader);
    }
    return;
  } catch (error, stackTrace) {
    _logTopLevelError('Error parsing request.\n$error', stackTrace);
    final response = Response.internalServerError();
    await _writeResponse(response, request.response, poweredByHeader);
    return;
  }

  // TODO(nweiz): abstract out hijack handling to make it easier to implement an
  // adapter.
  Response? response;
  try {
    response = await handler(shelfRequest);
  } on HijackException catch (error, stackTrace) {
    // A HijackException should bypass the response-writing logic entirely.
    if (!shelfRequest.canHijack) return;

    // If the request wasn't hijacked, we shouldn't be seeing this exception.
    response = _logError(
      shelfRequest,
      "Caught HijackException, but the request wasn't hijacked.",
      stackTrace,
    );
  } catch (error, stackTrace) {
    response = _logError(
      shelfRequest,
      'Error thrown by handler.\n$error',
      stackTrace,
    );
  }

  if ((response as dynamic) == null) {
    // Handle nulls flowing from opt-out code
    await _writeResponse(
        _logError(
            shelfRequest, 'null response from handler.', StackTrace.current),
        request.response,
        poweredByHeader);
    return;
  }
  if (shelfRequest.canHijack) {
    await _writeResponse(response, request.response, poweredByHeader);
    return;
  }

  var message = 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 Exception(message.toString().trim());
}