2
2
// for details. All rights reserved. Use of this source code is governed by a
3
3
// BSD-style license that can be found in the LICENSE file.
4
4
5
+ import 'dart:convert' ;
6
+ import 'dart:typed_data' ;
7
+
5
8
import 'package:_pub_shared/data/package_api.dart' ;
9
+ import 'package:clock/clock.dart' ;
6
10
import 'package:gcloud/service_scope.dart' ;
7
11
import 'package:http/http.dart' as http;
8
12
import 'package:meta/meta.dart' ;
9
13
10
14
import '../../frontend/handlers/pubapi.client.dart' ;
15
+ import '../../service/services.dart' ;
11
16
import '../../shared/configuration.dart' ;
12
-
13
17
import 'http.dart' ;
14
18
15
19
/// Creates an API client with [authToken] that uses the configured HTTP endpoints.
@@ -22,10 +26,60 @@ PubApiClient createPubApiClient({String? authToken}) {
22
26
registerScopeExitCallback (() async => httpClient.close ());
23
27
return PubApiClient (
24
28
activeConfiguration.primaryApiUri! .toString (),
25
- client: httpClient,
29
+ client: _FakeTimeClient ( httpClient) ,
26
30
);
27
31
}
28
32
33
+ class _FakeTimeClient implements http.Client {
34
+ final http.Client _client;
35
+ _FakeTimeClient (this ._client);
36
+
37
+ @override
38
+ Future <http.StreamedResponse > send (http.BaseRequest request) async {
39
+ request.headers[fakeClockHeaderName] = clock.now ().toIso8601String ();
40
+ return _client.send (request);
41
+ }
42
+
43
+ @override
44
+ void close () => _client.close ();
45
+
46
+ @override
47
+ Future <http.Response > delete (Uri url,
48
+ {Map <String , String >? headers, Object ? body, Encoding ? encoding}) =>
49
+ _client.delete (url, headers: headers, body: body, encoding: encoding);
50
+
51
+ @override
52
+ Future <http.Response > get (Uri url, {Map <String , String >? headers}) =>
53
+ _client.get (url, headers: headers);
54
+
55
+ @override
56
+ Future <http.Response > head (Uri url, {Map <String , String >? headers}) =>
57
+ _client.head (url, headers: headers);
58
+
59
+ @override
60
+ Future <http.Response > patch (Uri url,
61
+ {Map <String , String >? headers, Object ? body, Encoding ? encoding}) =>
62
+ _client.patch (url, headers: headers, body: body, encoding: encoding);
63
+
64
+ @override
65
+ Future <http.Response > post (Uri url,
66
+ {Map <String , String >? headers, Object ? body, Encoding ? encoding}) =>
67
+ _client.post (url, headers: headers, body: body, encoding: encoding);
68
+
69
+ @override
70
+ Future <http.Response > put (Uri url,
71
+ {Map <String , String >? headers, Object ? body, Encoding ? encoding}) =>
72
+ _client.put (url, headers: headers, body: body, encoding: encoding);
73
+
74
+ @override
75
+ Future <String > read (Uri url, {Map <String , String >? headers}) =>
76
+ _client.read (url, headers: headers);
77
+
78
+ @override
79
+ Future <Uint8List > readBytes (Uri url, {Map <String , String >? headers}) =>
80
+ _client.readBytes (url, headers: headers);
81
+ }
82
+
29
83
/// Creates a pub.dev API client and executes [fn] , making sure that the HTTP
30
84
/// resources are freed after the callback finishes.
31
85
///
@@ -55,6 +109,7 @@ extension PubApiClientExt on PubApiClient {
55
109
final uploadInfo = await getPackageUploadUrl ();
56
110
57
111
final request = http.MultipartRequest ('POST' , Uri .parse (uploadInfo.url))
112
+ ..headers[fakeClockHeaderName] = clock.now ().toIso8601String ()
58
113
..fields.addAll (uploadInfo.fields! )
59
114
..files.add (http.MultipartFile .fromBytes ('file' , bytes))
60
115
..followRedirects = false ;
0 commit comments