chore(shorebird_code_push_client): verbose log requests (#563)
This commit is contained in:
@@ -4,6 +4,7 @@ import 'dart:io';
|
||||
import 'package:cli_util/cli_util.dart';
|
||||
import 'package:googleapis_auth/auth_io.dart' as oauth2;
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:shorebird_cli/src/auth/jwt.dart';
|
||||
import 'package:shorebird_cli/src/command.dart';
|
||||
@@ -45,18 +46,34 @@ typedef OnRefreshCredentials = void Function(
|
||||
oauth2.AccessCredentials credentials,
|
||||
);
|
||||
|
||||
class AuthenticatedClient extends http.BaseClient {
|
||||
AuthenticatedClient({
|
||||
required oauth2.AccessCredentials credentials,
|
||||
class LoggingClient extends http.BaseClient {
|
||||
LoggingClient({
|
||||
required http.Client httpClient,
|
||||
required Logger logger,
|
||||
}) : _baseClient = httpClient,
|
||||
_logger = logger;
|
||||
|
||||
final http.Client _baseClient;
|
||||
final Logger _logger;
|
||||
|
||||
@override
|
||||
Future<http.StreamedResponse> send(http.BaseRequest request) async {
|
||||
_logger.detail('[HTTP] $request');
|
||||
return _baseClient.send(request);
|
||||
}
|
||||
}
|
||||
|
||||
class AuthenticatedClient extends LoggingClient {
|
||||
AuthenticatedClient({
|
||||
required super.httpClient,
|
||||
required super.logger,
|
||||
required oauth2.AccessCredentials credentials,
|
||||
required OnRefreshCredentials onRefreshCredentials,
|
||||
RefreshCredentials refreshCredentials = oauth2.refreshCredentials,
|
||||
}) : _credentials = credentials,
|
||||
_baseClient = httpClient,
|
||||
_onRefreshCredentials = onRefreshCredentials,
|
||||
_refreshCredentials = refreshCredentials;
|
||||
|
||||
final http.Client _baseClient;
|
||||
final OnRefreshCredentials _onRefreshCredentials;
|
||||
final RefreshCredentials _refreshCredentials;
|
||||
oauth2.AccessCredentials _credentials;
|
||||
@@ -73,17 +90,19 @@ class AuthenticatedClient extends http.BaseClient {
|
||||
}
|
||||
final token = _credentials.idToken;
|
||||
request.headers['Authorization'] = 'Bearer $token';
|
||||
return _baseClient.send(request);
|
||||
return super.send(request);
|
||||
}
|
||||
}
|
||||
|
||||
class Auth {
|
||||
Auth({
|
||||
Logger? logger,
|
||||
http.Client? httpClient,
|
||||
String? credentialsDir,
|
||||
ObtainAccessCredentials? obtainAccessCredentials,
|
||||
CodePushClientBuilder? buildCodePushClient,
|
||||
}) : _httpClient = httpClient ?? http.Client(),
|
||||
}) : logger = logger ?? Logger(),
|
||||
_httpClient = httpClient ?? http.Client(),
|
||||
_credentialsDir =
|
||||
credentialsDir ?? applicationConfigHome(executableName),
|
||||
_obtainAccessCredentials = obtainAccessCredentials ??
|
||||
@@ -96,6 +115,7 @@ class Auth {
|
||||
final String _credentialsDir;
|
||||
final ObtainAccessCredentials _obtainAccessCredentials;
|
||||
final CodePushClientBuilder _buildCodePushClient;
|
||||
final Logger logger;
|
||||
|
||||
String get credentialsFilePath {
|
||||
return p.join(_credentialsDir, 'credentials.json');
|
||||
@@ -108,6 +128,7 @@ class Auth {
|
||||
credentials: credentials,
|
||||
httpClient: _httpClient,
|
||||
onRefreshCredentials: _flushCredentials,
|
||||
logger: logger,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,12 +37,13 @@ abstract class ShorebirdCommand extends Command<int> {
|
||||
Cache? cache,
|
||||
CodePushClientBuilder? buildCodePushClient,
|
||||
List<Validator>? validators, // For mocking.
|
||||
}) : auth = auth ?? Auth(),
|
||||
cache = cache ?? Cache(),
|
||||
}) : cache = cache ?? Cache(),
|
||||
buildCodePushClient = buildCodePushClient ?? CodePushClient.new,
|
||||
validators = validators ?? _defaultValidators();
|
||||
validators = validators ?? _defaultValidators() {
|
||||
this.auth = auth ?? Auth(logger: logger);
|
||||
}
|
||||
|
||||
final Auth auth;
|
||||
late final Auth auth;
|
||||
final Cache cache;
|
||||
final CodePushClientBuilder buildCodePushClient;
|
||||
final Logger logger;
|
||||
|
||||
@@ -27,13 +27,18 @@ class ShorebirdCliCommandRunner extends CompletionCommandRunner<int> {
|
||||
argParser
|
||||
..addFlag(
|
||||
'version',
|
||||
abbr: 'v',
|
||||
negatable: false,
|
||||
help: 'Print the current version.',
|
||||
)
|
||||
..addFlag(
|
||||
'verbose',
|
||||
abbr: 'v',
|
||||
help: 'Noisy logging, including all shell commands executed.',
|
||||
callback: (verbose) {
|
||||
if (verbose) {
|
||||
_logger.level = Level.verbose;
|
||||
}
|
||||
},
|
||||
)
|
||||
..addOption(
|
||||
'local-engine-src-path',
|
||||
@@ -77,9 +82,6 @@ class ShorebirdCliCommandRunner extends CompletionCommandRunner<int> {
|
||||
Future<int> run(Iterable<String> args) async {
|
||||
try {
|
||||
final topLevelResults = parse(args);
|
||||
if (topLevelResults['verbose'] == true) {
|
||||
_logger.level = Level.verbose;
|
||||
}
|
||||
|
||||
// Set up our context before running the command.
|
||||
engineConfig = EngineConfig(
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'dart:io';
|
||||
|
||||
import 'package:googleapis_auth/googleapis_auth.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:shorebird_cli/src/auth/auth.dart';
|
||||
@@ -11,10 +12,12 @@ import 'package:test/test.dart';
|
||||
|
||||
class _FakeBaseRequest extends Fake implements http.BaseRequest {}
|
||||
|
||||
class _MockHttpClient extends Mock implements http.Client {}
|
||||
|
||||
class _MockCodePushClient extends Mock implements CodePushClient {}
|
||||
|
||||
class _MockLogger extends Mock implements Logger {}
|
||||
|
||||
class _MockHttpClient extends Mock implements http.Client {}
|
||||
|
||||
void main() {
|
||||
group('Auth', () {
|
||||
const idToken =
|
||||
@@ -40,6 +43,7 @@ void main() {
|
||||
late String credentialsDir;
|
||||
late http.Client httpClient;
|
||||
late CodePushClient codePushClient;
|
||||
late Logger logger;
|
||||
late Auth auth;
|
||||
|
||||
setUpAll(() {
|
||||
@@ -56,6 +60,7 @@ void main() {
|
||||
obtainAccessCredentials: (clientId, scopes, client, userPrompt) async {
|
||||
return accessCredentials;
|
||||
},
|
||||
logger: logger,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -68,11 +73,27 @@ void main() {
|
||||
credentialsDir = Directory.systemTemp.createTempSync().path;
|
||||
httpClient = _MockHttpClient();
|
||||
codePushClient = _MockCodePushClient();
|
||||
logger = _MockLogger();
|
||||
auth = buildAuth();
|
||||
|
||||
when(() => codePushClient.getCurrentUser()).thenAnswer((_) async => user);
|
||||
});
|
||||
|
||||
test('uses default logger if none is provided', () {
|
||||
final auth = Auth(
|
||||
credentialsDir: credentialsDir,
|
||||
httpClient: httpClient,
|
||||
buildCodePushClient: ({Uri? hostedUri, http.Client? httpClient}) {
|
||||
return codePushClient;
|
||||
},
|
||||
obtainAccessCredentials: (clientId, scopes, client, userPrompt) async {
|
||||
return accessCredentials;
|
||||
},
|
||||
);
|
||||
|
||||
expect(auth.logger, isA<Logger>());
|
||||
});
|
||||
|
||||
group('AuthenticatedClient', () {
|
||||
test('refreshes and uses new token when credentials are expired.',
|
||||
() async {
|
||||
@@ -101,6 +122,7 @@ void main() {
|
||||
onRefreshCredentials: onRefreshCredentialsCalls.add,
|
||||
refreshCredentials: (clientId, credentials, client) async =>
|
||||
accessCredentials,
|
||||
logger: logger,
|
||||
);
|
||||
|
||||
await client.get(Uri.parse('https://example.com'));
|
||||
@@ -129,6 +151,7 @@ void main() {
|
||||
credentials: accessCredentials,
|
||||
httpClient: httpClient,
|
||||
onRefreshCredentials: onRefreshCredentialsCalls.add,
|
||||
logger: logger,
|
||||
);
|
||||
|
||||
await client.get(Uri.parse('https://example.com'));
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:shorebird_cli/src/command.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group(ShorebirdCommand, () {
|
||||
test('passes logger to auth in default builder', () {
|
||||
final logger = Logger();
|
||||
final command = TestCommand(logger: logger);
|
||||
expect(command.auth.logger, logger);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
class TestCommand extends ShorebirdCommand {
|
||||
TestCommand({required super.logger});
|
||||
|
||||
@override
|
||||
String get description => 'A test command';
|
||||
|
||||
@override
|
||||
String get name => 'test';
|
||||
}
|
||||
Reference in New Issue
Block a user