onResponse method
void
onResponse(- dynamic response,
- dynamic handler
)
Implementation
@override
void onResponse(Response response, ResponseInterceptorHandler handler) async {
logDebugMessage('SuperTokensInterceptorWrapper.onResponse: Intercepting response call');
if (!shouldRunDioInterceptor(response.requestOptions)) {
logDebugMessage('SuperTokensInterceptorWrapper.onResponse: Skipping dio interceptor');
return handler.next(response);
}
logDebugMessage('SuperTokensInterceptorWrapper.onResponse: Running dio interceptor');
_refreshAPILock.acquireWrite();
logDebugMessage('SuperTokensInterceptorWrapper.onResponse: write acquired');
logDebugMessage('SuperTokensInterceptorWrapper.onResponse: saving tokens from headers');
await saveTokensFromHeaders(response);
String? frontTokenFromResponse =
response.headers.map[frontTokenHeaderKey]?.first.toString();
logDebugMessage('SuperTokensInterceptorWrapper.onResponse: frontTokenFromResponse: ${frontTokenFromResponse}');
SuperTokensUtils.fireSessionUpdateEventsIfNecessary(
wasLoggedIn:
_preRequestLocalSessionState.status == LocalSessionStateStatus.EXISTS,
status: response.statusCode!,
frontTokenFromResponse: frontTokenFromResponse,
);
List<dynamic>? setCookieFromResponse =
response.headers.map[HttpHeaders.setCookieHeader];
logDebugMessage('SuperTokensInterceptorWrapper.onResponse: setCookieFromResponse length: ${setCookieFromResponse?.length}');
setCookieFromResponse?.forEach((element) async {
await Client.cookieStore
?.saveFromSetCookieHeader(response.realUri, element);
});
try {
if (response.statusCode == SuperTokens.sessionExpiryStatusCode) {
/**
* An API may return a 401 error response even with a valid session, causing a session refresh loop in the interceptor.
* To prevent this infinite loop, we break out of the loop after retrying the original request a specified number of times.
* The maximum number of retry attempts is defined by maxRetryAttemptsForSessionRefresh config variable.
*/
logDebugMessage('SuperTokensInterceptorWrapper.onResponse: Got expiry status code');
RequestOptions requestOptions = response.requestOptions;
int sessionRefreshAttempts =
requestOptions.extra["__supertokensSessionRefreshAttempts"] ?? 0;
if (sessionRefreshAttempts >=
SuperTokens.config.maxRetryAttemptsForSessionRefresh) {
logDebugMessage('SuperTokensInterceptorWrapper.onResponse: Max attempts of ${SuperTokens.config.maxRetryAttemptsForSessionRefresh} reached for refreshing, cannot continue');
handler.reject(
DioException(
requestOptions: response.requestOptions,
type: DioExceptionType.unknown,
error: SuperTokensException(
"Received a 401 response from ${response.requestOptions.uri}. Attempted to refresh the session and retry the request with the updated session tokens ${SuperTokens.config.maxRetryAttemptsForSessionRefresh} times, but each attempt resulted in a 401 error. The maximum session refresh limit has been reached. Please investigate your API. To increase the session refresh attempts, update maxRetryAttemptsForSessionRefresh in the config."),
),
);
_refreshAPILock.release();
return;
}
logDebugMessage('SuperTokensInterceptorWrapper.onResponse: removing auth header if it matches token');
requestOptions =
await _removeAuthHeaderIfMatchesLocalToken(requestOptions);
UnauthorisedResponse shouldRetry =
await Client.onUnauthorisedResponse(_preRequestLocalSessionState);
if (shouldRetry.status == UnauthorisedStatus.RETRY) {
logDebugMessage('SuperTokensInterceptorWrapper.onResponse: Got RETRY status');
logDebugMessage('SuperTokensInterceptorWrapper.onResponse: Refreshing attempt: ${sessionRefreshAttempts + 1}');
requestOptions.headers[HttpHeaders.cookieHeader] = userSetCookie;
requestOptions.extra["__supertokensSessionRefreshAttempts"] =
sessionRefreshAttempts + 1;
Response<dynamic> res = await client.fetch(requestOptions);
List<dynamic>? setCookieFromResponse =
res.headers.map[HttpHeaders.setCookieHeader];
logDebugMessage('SuperTokensInterceptorWrapper.onResponse: setCookieFromResponse length: ${setCookieFromResponse?.length}');
setCookieFromResponse?.forEach((element) async {
await Client.cookieStore
?.saveFromSetCookieHeader(res.realUri, element);
});
logDebugMessage('SuperTokensInterceptorWrapper.onResponse: Saving tokens from headers');
await saveTokensFromHeaders(res);
logDebugMessage('SuperTokensInterceptorWrapper.onResponse: Calling next on handler');
return handler.next(res);
} else {
if (shouldRetry.exception != null) {
logDebugMessage('SuperTokensInterceptorWrapper.onResponse: Got non null exception');
handler.reject(
DioException(
requestOptions: response.requestOptions,
error: SuperTokensException(shouldRetry.exception!.message),
type: DioExceptionType.unknown),
);
return;
} else {
_refreshAPILock.release();
logDebugMessage('SuperTokensInterceptorWrapper.onResponse: Calling next on handler');
return handler.next(response);
}
}
} else {
_refreshAPILock.release();
logDebugMessage('SuperTokensInterceptorWrapper.onResponse: Calling next on handler');
return handler.next(response);
}
} on DioException catch (e) {
handler.reject(e);
} catch (e) {
handler.reject(
DioException(
requestOptions: response.requestOptions,
type: DioExceptionType.unknown,
error: e),
);
}
}