send method

  1. @override
Future send(
  1. dynamic request
)

Implementation

@override
Future<http.StreamedResponse> send(http.BaseRequest request) async {
  if (Client.cookieStore == null) {
    Client.cookieStore = SuperTokensCookieStore();
  }

  if (!SuperTokens.isInitCalled) {
    throw http.ClientException(
        "SuperTokens.initialise must be called before using Client");
  }

  if (SuperTokensUtils.getApiDomain(request.url.toString()) !=
      SuperTokens.config.apiDomain) {
    return _innerClient.send(request);
  }

  if (SuperTokensUtils.getApiDomain(request.url.toString()) ==
      SuperTokens.refreshTokenUrl) {
    return _innerClient.send(request);
  }

  if (!Utils.shouldDoInterceptions(
      request.url.toString(),
      SuperTokens.config.apiDomain,
      SuperTokens.config.sessionTokenBackendDomain)) {
    return _innerClient.send(request);
  }

  try {
    while (true) {
      await _refreshAPILock.acquireRead();
      // http package does not allow retries with the same request object, so we clone the request when making the network call
      http.BaseRequest copiedRequest;
      LocalSessionState preRequestLocalSessionState;
      http.StreamedResponse response;
      try {
        copiedRequest = SuperTokensUtils.copyRequest(request);
        copiedRequest =
            await _removeAuthHeaderIfMatchesLocalToken(copiedRequest);
        preRequestLocalSessionState =
            await SuperTokensUtils.getLocalSessionState();
        String? antiCSRFToken = await AntiCSRF.getToken(
            preRequestLocalSessionState.lastAccessTokenUpdate);

        if (antiCSRFToken != null) {
          copiedRequest.headers[antiCSRFHeaderKey] = antiCSRFToken;
        }

        SuperTokensTokenTransferMethod tokenTransferMethod =
            SuperTokens.config.tokenTransferMethod;
        copiedRequest.headers["st-auth-mode"] =
            tokenTransferMethod.getValue();

        // Adding Authorization headers
        copiedRequest =
            await Utils.setAuthorizationHeaderIfRequired(copiedRequest);

        // Add cookies to request headers
        String? newCookiesToAdd = await Client.cookieStore
            ?.getCookieHeaderStringForRequest(copiedRequest.url);
        String? existingCookieHeader =
            copiedRequest.headers[HttpHeaders.cookieHeader];

        // If the request already has a "cookie" header, combine it with persistent cookies
        if (existingCookieHeader != null && existingCookieHeader != "") {
          copiedRequest.headers[HttpHeaders.cookieHeader] =
              _generateCookieHeader(existingCookieHeader, newCookiesToAdd);
        } else {
          copiedRequest.headers[HttpHeaders.cookieHeader] =
              newCookiesToAdd ?? "";
        }

        // http package does not allow retries with the same request object, so we clone the request when making the network call
        response = await _innerClient.send(copiedRequest);
        await Utils.saveTokenFromHeaders(response);
        String? frontTokenInHeaders = response.headers[frontTokenHeaderKey];
        SuperTokensUtils.fireSessionUpdateEventsIfNecessary(
          wasLoggedIn: preRequestLocalSessionState.status ==
              LocalSessionStateStatus.EXISTS,
          status: response.statusCode,
          frontTokenFromResponse: frontTokenInHeaders,
        );

        // Save cookies from the response
        String? setCookieFromResponse =
            response.headers[HttpHeaders.setCookieHeader];
        await Client.cookieStore?.saveFromSetCookieHeader(
            copiedRequest.url, setCookieFromResponse);
      } finally {
        _refreshAPILock.release();
      }

      if (response.statusCode == SuperTokens.sessionExpiryStatusCode) {
        request = await _removeAuthHeaderIfMatchesLocalToken(copiedRequest);
        UnauthorisedResponse shouldRetry =
            await onUnauthorisedResponse(preRequestLocalSessionState);
        if (shouldRetry.status == UnauthorisedStatus.RETRY) {
          // Here we use the original request because it wont contain any of the modifications we make
          return await send(request);
        } else {
          if (shouldRetry.exception != null) {
            throw SuperTokensException(shouldRetry.exception!.message);
          } else
            return response;
        }
      } else {
        return response;
      }
    }
  } finally {
    LocalSessionState localSessionState =
        await SuperTokensUtils.getLocalSessionState();
    if (localSessionState.status == LocalSessionStateStatus.NOT_EXISTS) {
      await AntiCSRF.removeToken();
      await FrontToken.removeToken();
    }
  }
}