-
Notifications
You must be signed in to change notification settings - Fork 119
/
http_auth_link.dart
93 lines (79 loc) · 2.22 KB
/
http_auth_link.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import "dart:async";
import "package:gql_error_link/gql_error_link.dart";
import "package:gql_exec/gql_exec.dart";
import "package:gql_http_link/gql_http_link.dart";
import "package:gql_link/gql_link.dart";
import "package:gql_transform_link/gql_transform_link.dart";
class HttpAuthLink extends Link {
late Link _link;
String? _token;
bool _isRefreshing = false;
final List<Completer> _tokenRefreshQueue = [];
HttpAuthLink() {
_link = Link.concat(
ErrorLink(onException: handleException),
TransformLink(requestTransformer: transformRequest),
);
}
Future<void> updateToken() async {
if (!_isRefreshing) {
try {
_isRefreshing = true;
_token = await Future.delayed(
Duration(milliseconds: 10),
() => "Valid token",
);
_tokenRefreshQueue.forEach((completer) {
completer.complete(_token!);
});
_tokenRefreshQueue.clear();
} finally {
_isRefreshing = false;
}
} else {
// If token refresh is already in progress, queue the request
final completer = Completer<String>();
_tokenRefreshQueue.add(completer);
_token = await completer.future;
}
}
Stream<Response> handleException(
Request request,
NextLink forward,
LinkException exception,
) async* {
if (exception is HttpLinkServerException &&
exception.response.statusCode == 401) {
await updateToken();
yield* forward(request);
return;
}
throw exception;
}
Request transformRequest(Request request) {
var updatedRequest = request.updateContextEntry<HttpLinkHeaders>(
(headers) => HttpLinkHeaders(
headers: <String, String>{
...headers?.headers ?? <String, String>{},
},
),
);
if (_token != null) {
updatedRequest = request.updateContextEntry<HttpLinkHeaders>(
(headers) => HttpLinkHeaders(
headers: <String, String>{
"Authorization": _token!,
},
),
);
}
return updatedRequest;
}
@override
Stream<Response> request(Request request, [forward]) async* {
if (_token == null) {
await updateToken();
}
yield* _link.request(request, forward);
}
}