send method

  1. @override
Future<ServerResponse> send(
  1. ServerRequest request
)
override

Sends request and returns its response.

Implementations must stop request and response work when ServerRequest.cancelled completes.

Implementation

@override
Future<ServerResponse> send(ServerRequest request) async {
  var callerCancelled = false;
  final abortTrigger = request.cancelled?.then<void>(
    (_) => callerCancelled = true,
    onError: (Object _, StackTrace _) => callerCancelled = true,
  );
  final outgoing = http.AbortableRequest(
    request.method.wire,
    request.uri,
    abortTrigger: abortTrigger,
  );
  for (final entry in request.headers.entries) {
    if (_framingHeaders.contains(entry.key)) continue;
    outgoing.headers[entry.key] = entry.value.join(', ');
  }
  outgoing.bodyBytes = await runUntilRpcCancelled(
    () => _readBytes(
      stopOnRpcCancellation(request.body, request.cancelled),
      maxRequestBodyBytes,
    ),
    request.cancelled,
  );

  Future<http.StreamedResponse>? pending;
  late final http.StreamedResponse incoming;
  try {
    incoming = await runUntilRpcCancelled(
      () => pending = _client.send(outgoing),
      request.cancelled,
    );
  } on http.RequestAbortedException catch (_, stackTrace) {
    if (callerCancelled) {
      Error.throwWithStackTrace(const RpcCancelledException(), stackTrace);
    }
    rethrow;
  } on RpcCancelledException {
    final lateResponse = pending;
    if (lateResponse != null) {
      unawaited(
        lateResponse.then<void>(
          (response) => _cancelBody(response.stream),
          onError: (Object _, StackTrace _) {},
        ),
      );
    }
    rethrow;
  }
  return ServerResponse(
    status: incoming.statusCode,
    reason: incoming.reasonPhrase,
    headers: Headers.single(incoming.headers),
    body: incoming.stream.handleError((Object error, StackTrace stackTrace) {
      if (callerCancelled) {
        Error.throwWithStackTrace(const RpcCancelledException(), stackTrace);
      }
      Error.throwWithStackTrace(error, stackTrace);
    }, test: (error) => error is http.RequestAbortedException),
  );
}