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
|
* Expose a stream for connection state changes on ClientChannel to address
|
||||||
[#428](https://github.com/grpc/grpc-dart/issues/428).
|
[#428](https://github.com/grpc/grpc-dart/issues/428).
|
||||||
This allows users to react to state changes in the connection.
|
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
|
## 3.0.2
|
||||||
|
|
||||||
|
|
|
@ -355,10 +355,23 @@ class _SocketTransportConnector implements ClientTransportConnector {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get authority {
|
String get authority {
|
||||||
final host =
|
return _options.credentials.authority ?? _makeAuthority();
|
||||||
_host is String ? _host as String : (_host as InternetAddress).host;
|
}
|
||||||
return _options.credentials.authority ??
|
|
||||||
(_port == 443 ? host : '$host:$_port');
|
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
|
@override
|
||||||
|
|
|
@ -16,6 +16,21 @@ import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:test/test.dart';
|
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.
|
/// Test functionality for both TCP and Unix domain sockets.
|
||||||
void testTcpAndUds(
|
void testTcpAndUds(
|
||||||
String name, FutureOr<void> Function(InternetAddress) testCase,
|
String name, FutureOr<void> Function(InternetAddress) testCase,
|
||||||
|
@ -25,15 +40,5 @@ void testTcpAndUds(
|
||||||
await testCase(address.first);
|
await testCase(address.first);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (Platform.isWindows) {
|
testUds('$name (over uds)', testCase);
|
||||||
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);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,10 +23,12 @@ class TestClient extends Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestService extends Service {
|
class TestService extends Service {
|
||||||
|
final String? expectedAuthority;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get $name => 'test.TestService';
|
String get $name => 'test.TestService';
|
||||||
|
|
||||||
TestService() {
|
TestService({this.expectedAuthority}) {
|
||||||
$addMethod(ServiceMethod<int, int>('stream', stream, false, true,
|
$addMethod(ServiceMethod<int, int>('stream', stream, false, true,
|
||||||
(List<int> value) => value[0], (int value) => [value]));
|
(List<int> value) => value[0], (int value) => [value]));
|
||||||
}
|
}
|
||||||
|
@ -35,12 +37,20 @@ class TestService extends Service {
|
||||||
static const requestInfiniteStream = 2;
|
static const requestInfiniteStream = 2;
|
||||||
|
|
||||||
Stream<int> stream(ServiceCall call, Future request) async* {
|
Stream<int> stream(ServiceCall call, Future request) async* {
|
||||||
|
checkMetadata(call.clientMetadata);
|
||||||
|
|
||||||
final isInfinite = 2 == await request;
|
final isInfinite = 2 == await request;
|
||||||
for (var i = 1; i <= 3 || isInfinite; i++) {
|
for (var i = 1; i <= 3 || isInfinite; i++) {
|
||||||
yield i;
|
yield i;
|
||||||
await Future.delayed(Duration(milliseconds: 100));
|
await Future.delayed(Duration(milliseconds: 100));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void checkMetadata(Map<String, String>? metadata) {
|
||||||
|
if (expectedAuthority != null) {
|
||||||
|
expect(metadata![':authority'], equals(expectedAuthority));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestServiceWithOnMetadataException extends TestService {
|
class TestServiceWithOnMetadataException extends TestService {
|
||||||
|
@ -93,6 +103,22 @@ Future<void> main() async {
|
||||||
server.shutdown();
|
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',
|
testTcpAndUds('round trip with outgoing and incoming compression',
|
||||||
(address) async {
|
(address) async {
|
||||||
final server = Server(
|
final server = Server(
|
||||||
|
|
Loading…
Reference in New Issue