mirror of https://github.com/grpc/grpc-dart.git
Change default authority for UDS connections. (#577)
We were using path to the UDS socket itself, which is incorrect `:authority` value. This was tripping checks in some HTTP2 protocol implementations. Instead default `:authority` to `localhost`, which in line with other gRPC implementations. Fixes #576
This commit is contained in:
parent
b8f872a3dc
commit
27a235976a
|
@ -3,6 +3,10 @@
|
|||
* Expose a stream for connection state changes on ClientChannel to address
|
||||
[#428](https://github.com/grpc/grpc-dart/issues/428).
|
||||
This allows users to react to state changes in the connection.
|
||||
* Fix [#576](https://github.com/grpc/grpc-dart/issues/576): set default
|
||||
`:authority` value for UDS connections to `localhost` instead of using
|
||||
UDS path. Using path triggers checks in HTTP2 servers which
|
||||
attempt to validate `:authority` value.
|
||||
|
||||
## 3.0.2
|
||||
|
||||
|
|
|
@ -355,10 +355,23 @@ class _SocketTransportConnector implements ClientTransportConnector {
|
|||
|
||||
@override
|
||||
String get authority {
|
||||
final host =
|
||||
_host is String ? _host as String : (_host as InternetAddress).host;
|
||||
return _options.credentials.authority ??
|
||||
(_port == 443 ? host : '$host:$_port');
|
||||
return _options.credentials.authority ?? _makeAuthority();
|
||||
}
|
||||
|
||||
String _makeAuthority() {
|
||||
final host = _host;
|
||||
final portSuffix = _port == 443 ? '' : ':$_port';
|
||||
final hostName;
|
||||
if (host is String) {
|
||||
hostName = '$host';
|
||||
} else {
|
||||
host as InternetAddress;
|
||||
if (host.type == InternetAddressType.unix) {
|
||||
return 'localhost'; // UDS don't have a meaningful authority.
|
||||
}
|
||||
hostName = host.host;
|
||||
}
|
||||
return '$hostName$portSuffix';
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -16,6 +16,21 @@ import 'dart:async';
|
|||
import 'dart:io';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
/// Test functionality for Unix domain socket.
|
||||
void testUds(String name, FutureOr<void> Function(InternetAddress) testCase) {
|
||||
if (Platform.isWindows) {
|
||||
return;
|
||||
}
|
||||
|
||||
test(name, () async {
|
||||
final tempDir = await Directory.systemTemp.createTemp();
|
||||
final address = InternetAddress(tempDir.path + '/socket',
|
||||
type: InternetAddressType.unix);
|
||||
addTearDown(() => tempDir.delete(recursive: true));
|
||||
await testCase(address);
|
||||
});
|
||||
}
|
||||
|
||||
/// Test functionality for both TCP and Unix domain sockets.
|
||||
void testTcpAndUds(
|
||||
String name, FutureOr<void> Function(InternetAddress) testCase,
|
||||
|
@ -25,15 +40,5 @@ void testTcpAndUds(
|
|||
await testCase(address.first);
|
||||
});
|
||||
|
||||
if (Platform.isWindows) {
|
||||
return;
|
||||
}
|
||||
|
||||
test('$name (over uds)', () async {
|
||||
final tempDir = await Directory.systemTemp.createTemp();
|
||||
final address = InternetAddress(tempDir.path + '/socket',
|
||||
type: InternetAddressType.unix);
|
||||
addTearDown(() => tempDir.delete(recursive: true));
|
||||
await testCase(address);
|
||||
});
|
||||
testUds('$name (over uds)', testCase);
|
||||
}
|
||||
|
|
|
@ -23,10 +23,12 @@ class TestClient extends Client {
|
|||
}
|
||||
|
||||
class TestService extends Service {
|
||||
final String? expectedAuthority;
|
||||
|
||||
@override
|
||||
String get $name => 'test.TestService';
|
||||
|
||||
TestService() {
|
||||
TestService({this.expectedAuthority}) {
|
||||
$addMethod(ServiceMethod<int, int>('stream', stream, false, true,
|
||||
(List<int> value) => value[0], (int value) => [value]));
|
||||
}
|
||||
|
@ -35,12 +37,20 @@ class TestService extends Service {
|
|||
static const requestInfiniteStream = 2;
|
||||
|
||||
Stream<int> stream(ServiceCall call, Future request) async* {
|
||||
checkMetadata(call.clientMetadata);
|
||||
|
||||
final isInfinite = 2 == await request;
|
||||
for (var i = 1; i <= 3 || isInfinite; i++) {
|
||||
yield i;
|
||||
await Future.delayed(Duration(milliseconds: 100));
|
||||
}
|
||||
}
|
||||
|
||||
void checkMetadata(Map<String, String>? metadata) {
|
||||
if (expectedAuthority != null) {
|
||||
expect(metadata![':authority'], equals(expectedAuthority));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TestServiceWithOnMetadataException extends TestService {
|
||||
|
@ -93,6 +103,22 @@ Future<void> main() async {
|
|||
server.shutdown();
|
||||
});
|
||||
|
||||
testUds('UDS provides valid default authority', (address) async {
|
||||
// round trip test of insecure connection.
|
||||
final server = Server([TestService(expectedAuthority: 'localhost')]);
|
||||
await server.serve(address: address, port: 0);
|
||||
|
||||
final channel = FixedConnectionClientChannel(Http2ClientConnection(
|
||||
address,
|
||||
server.port!,
|
||||
ChannelOptions(credentials: ChannelCredentials.insecure()),
|
||||
));
|
||||
final testClient = TestClient(channel);
|
||||
expect(await testClient.stream(TestService.requestFiniteStream).toList(),
|
||||
[1, 2, 3]);
|
||||
server.shutdown();
|
||||
});
|
||||
|
||||
testTcpAndUds('round trip with outgoing and incoming compression',
|
||||
(address) async {
|
||||
final server = Server(
|
||||
|
|
Loading…
Reference in New Issue