respond method

Handles one request from AuthTestHttpClient.

Implementation

Future<AuthTestHttpResponse> respond(AuthTestHttpRequest request) async {
  final prefix = _normalizeBasePath(basePath);
  if (request.method == 'GET' && request.uri.path == '$prefix/csrf') {
    return AuthTestHttpResponse.json(<String, dynamic>{
      'csrfToken': csrfToken,
    });
  }
  if (!request.uri.path.startsWith(prefix)) {
    return AuthTestHttpResponse.error('not_found', statusCode: 404);
  }
  final path = request.uri.path.substring(prefix.length);
  final match = _endpoints
      .map(
        (candidate) => (candidate, _matchPath(candidate.path.template, path)),
      )
      .where(
        (entry) =>
            entry.$2 != null &&
            entry.$1.method.name.toUpperCase() == request.method,
      )
      .firstOrNull;
  if (match == null) {
    return AuthTestHttpResponse.error('not_found', statusCode: 404);
  }
  final endpoint = match.$1;
  try {
    final endpointRequest = AuthEndpointRequest(
      path: endpoint.path.bind(Map<String, Object?>.from(match.$2!)),
      query: Map<String, dynamic>.from(request.uri.queryParameters),
      body: request.jsonObject(),
      headers: request.headers,
    );
    final endpointInvocation = invocation(
      request,
    ).withRequest(endpointRequest);
    final result = await endpoint.invoke(endpointInvocation, endpointRequest);
    if (result is AuthEndpointRedirect) {
      return AuthTestHttpResponse(
        statusCode: result.statusCode,
        body: '',
        headers: <String, String>{
          ...result.headers,
          'location': result.location.toString(),
        },
      );
    }
    if (result is AuthEndpointAuthenticationIntent) {
      final control = endpointInvocation.sessionControl;
      if (control is! AuthTestSessionControl) {
        return AuthTestHttpResponse.error('authentication_host_unavailable');
      }
      final session = control.completeAuthentication(result);
      return AuthTestHttpResponse.json(
        await result.projectResponse(session.redacted().toJson()),
      );
    }
    if (result is AuthEndpointHttpResponse) {
      return AuthTestHttpResponse(
        statusCode: result.statusCode,
        body: result.body == null ? '' : jsonEncode(result.body),
        headers: <String, String>{
          if (result.body != null) 'content-type': 'application/json',
          ...result.headers,
        },
      );
    }
    return AuthTestHttpResponse.json(result);
  } on AuthFlowException catch (error) {
    return AuthTestHttpResponse.error(error.code);
  } on FormatException {
    final errorEndpoint =
        endpoint is AuthEndpointPublicErrorResponseDescriptor
        ? endpoint as AuthEndpointPublicErrorResponseDescriptor
        : null;
    if (errorEndpoint != null) {
      final response = errorEndpoint.createPublicErrorResponse(
        AuthEndpointPublicErrorKind.invalidRequest,
      );
      if (response != null) {
        return AuthTestHttpResponse(
          statusCode: response.statusCode,
          body: response.body == null ? '' : jsonEncode(response.body),
          headers: <String, String>{
            if (response.body != null) 'content-type': 'application/json',
            ...response.headers,
          },
        );
      }
    }
    return AuthTestHttpResponse.error('invalid_request');
  }
}