fix: normalize bridge metadata authorization
This commit is contained in:
parent
b58b00f9d1
commit
9a8dac8c83
@ -27,7 +27,10 @@ Future<Map<String, dynamic>> loadBridgeMetadataForSettingsAbout({
|
||||
fragment: null,
|
||||
);
|
||||
final authorizationHeader = await authorizationResolver(pingEndpoint);
|
||||
if (authorizationHeader == null || authorizationHeader.trim().isEmpty) {
|
||||
final normalizedAuthorizationHeader = _normalizeAuthorizationHeader(
|
||||
authorizationHeader ?? '',
|
||||
);
|
||||
if (normalizedAuthorizationHeader.isEmpty) {
|
||||
return const <String, dynamic>{
|
||||
'status': 'unavailable',
|
||||
'version': '',
|
||||
@ -45,7 +48,7 @@ Future<Map<String, dynamic>> loadBridgeMetadataForSettingsAbout({
|
||||
.timeout(const Duration(seconds: 4));
|
||||
request.headers.set(
|
||||
HttpHeaders.authorizationHeader,
|
||||
'Bearer $authorizationHeader',
|
||||
normalizedAuthorizationHeader,
|
||||
);
|
||||
request.headers.set(HttpHeaders.acceptHeader, 'application/json');
|
||||
final response = await request.close().timeout(const Duration(seconds: 4));
|
||||
@ -88,6 +91,21 @@ Future<Map<String, dynamic>> loadBridgeMetadataForSettingsAbout({
|
||||
};
|
||||
}
|
||||
|
||||
String _normalizeAuthorizationHeader(String raw) {
|
||||
final trimmed = raw.trim();
|
||||
if (trimmed.isEmpty) {
|
||||
return '';
|
||||
}
|
||||
final separatorIndex = trimmed.indexOf(RegExp(r'\s'));
|
||||
if (separatorIndex > 0 && separatorIndex < trimmed.length - 1) {
|
||||
final scheme = trimmed.substring(0, separatorIndex);
|
||||
if (RegExp(r"^[A-Za-z][A-Za-z0-9!#$%&'*+.^_`|~-]*$").hasMatch(scheme)) {
|
||||
return trimmed;
|
||||
}
|
||||
}
|
||||
return 'Bearer $trimmed';
|
||||
}
|
||||
|
||||
class SettingsPage extends StatefulWidget {
|
||||
const SettingsPage({
|
||||
super.key,
|
||||
|
||||
@ -50,6 +50,39 @@ void main() {
|
||||
expect(metadata['buildDate'], '2026-04-21');
|
||||
});
|
||||
|
||||
test('preserves prebuilt bearer authorization', () async {
|
||||
final server = await HttpServer.bind(InternetAddress.loopbackIPv4, 0);
|
||||
addTearDown(() async {
|
||||
await server.close(force: true);
|
||||
});
|
||||
|
||||
var authorizationHeader = '';
|
||||
server.listen((request) async {
|
||||
authorizationHeader =
|
||||
request.headers.value(HttpHeaders.authorizationHeader) ?? '';
|
||||
request.response
|
||||
..statusCode = HttpStatus.ok
|
||||
..headers.contentType = ContentType.json
|
||||
..write(
|
||||
jsonEncode(<String, dynamic>{
|
||||
'status': 'ok',
|
||||
'version': '991ecb0',
|
||||
}),
|
||||
);
|
||||
await request.response.close();
|
||||
});
|
||||
|
||||
final metadata = await loadBridgeMetadataForSettingsAbout(
|
||||
bridgeEndpoint: Uri.parse(
|
||||
'http://${server.address.address}:${server.port}',
|
||||
),
|
||||
authorizationResolver: (_) async => 'Bearer bridge-token',
|
||||
);
|
||||
|
||||
expect(authorizationHeader, 'Bearer bridge-token');
|
||||
expect(metadata['status'], 'ok');
|
||||
});
|
||||
|
||||
test('returns unavailable when bridge authorization is missing', () async {
|
||||
final server = await HttpServer.bind(InternetAddress.loopbackIPv4, 0);
|
||||
addTearDown(() async {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user