Skip to content

Commit

Permalink
GrpcOrGrpcWeb: provide more flexible constructors (#484) (#485)
Browse files Browse the repository at this point in the history
  • Loading branch information
morgwai authored Jun 8, 2021
1 parent 7c8fca7 commit d4504da
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 45 deletions.
74 changes: 64 additions & 10 deletions lib/grpc_or_grpcweb.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,71 @@
// See the License for the specific language governing permissions and
// limitations under the License.

/// Exports [GrpcOrWebClientChannel] that underneath uses gRPC [ClientChannel]
/// on all platfroms except web, on which it uses [GrpcWebClientChannel].
import 'src/client/grpc_or_grpcweb_channel_grpc.dart'
if (dart.library.html) 'src/client/grpc_or_grpcweb_channel_web.dart';
import 'src/client/http2_channel.dart';
import 'src/client/options.dart';

/// A client channel that underneath uses gRPC [ClientChannel] on all platforms
/// except web, on which it uses [GrpcWebClientChannel].
///
/// Note that gRPC and gRPC-web are 2 different protocols and server must be
/// able to speak both of them for this to work.
/// As several existing implementations (such as in-process gRPC-web to gRPC
/// proxies or Envoy gRPC-web to gRPC proxy) expose gRPC and gRPC-web on
/// separate ports, the constructor requires 2 ports to be provided and
/// the channel will use the one for the actual protocol being used.
/// If the server supports both protocols on the same port (such as AspNetCore
/// implementation), then the same port value should be provided on both params.
/// Depending on its exact setup, the server may expose gRPC and gRPC-web on the
/// same port (this is the standard setup of AspNetCore implementation for
/// example), on separate ports of the same host (common setup of in-process
/// gRPC-web to gRPC proxies or colocated Envoy gRPC-web to gRPC proxy), or as
/// a completely separate endpoints (for example if Envoy and gRPC server are
/// exposed as different kubernetes services). A corresponding constructor is
/// provided for each case.
class GrpcOrGrpcWebClientChannel extends GrpcOrGrpcWebClientChannelInternal {
GrpcOrGrpcWebClientChannel.toSeparateEndpoints({
required String grpcHost,
required int grpcPort,
required bool grpcTransportSecure,
required String grpcWebHost,
required int grpcWebPort,
required bool grpcWebTransportSecure,
}) : super(
grpcHost: grpcHost,
grpcPort: grpcPort,
grpcTransportSecure: grpcTransportSecure,
grpcWebHost: grpcWebHost,
grpcWebPort: grpcWebPort,
grpcWebTransportSecure: grpcWebTransportSecure,
);

export 'src/client/grpc_or_grpcweb_channel_grpc.dart'
if (dart.library.html) 'src/client/grpc_or_grpcweb_channel_web.dart';
GrpcOrGrpcWebClientChannel.toSeparatePorts({
required String host,
required int grpcPort,
required bool grpcTransportSecure,
required int grpcWebPort,
required bool grpcWebTransportSecure,
}) : super(
grpcHost: host,
grpcPort: grpcPort,
grpcTransportSecure: grpcTransportSecure,
grpcWebHost: host,
grpcWebPort: grpcWebPort,
grpcWebTransportSecure: grpcWebTransportSecure,
);

GrpcOrGrpcWebClientChannel.toSingleEndpoint({
required String host,
required int port,
required bool transportSecure,
}) : super(
grpcHost: host,
grpcPort: port,
grpcTransportSecure: transportSecure,
grpcWebHost: host,
grpcWebPort: port,
grpcWebTransportSecure: transportSecure,
);

GrpcOrGrpcWebClientChannel.grpc(
Object host, {
int port = 443,
ChannelOptions options = const ChannelOptions(),
}) : super.grpc(host, port: port, options: options);
}
20 changes: 11 additions & 9 deletions lib/src/client/grpc_or_grpcweb_channel_grpc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,27 @@ import 'http2_channel.dart';
import 'options.dart';
import 'transport/http2_credentials.dart';

class GrpcOrGrpcWebClientChannel extends ClientChannel {
GrpcOrGrpcWebClientChannel({
required String host,
class GrpcOrGrpcWebClientChannelInternal extends ClientChannel {
GrpcOrGrpcWebClientChannelInternal({
required String grpcHost,
required int grpcPort,
required bool grpcTransportSecure,
required String grpcWebHost,
required int grpcWebPort,
required bool secure,
required bool grpcWebTransportSecure,
}) : super(
host,
grpcHost,
port: grpcPort,
options: ChannelOptions(
credentials: secure
credentials: grpcTransportSecure
? ChannelCredentials.secure()
: ChannelCredentials.insecure(),
),
);

GrpcOrGrpcWebClientChannel.grpc(
GrpcOrGrpcWebClientChannelInternal.grpc(
Object host, {
int port = 443,
ChannelOptions options = const ChannelOptions(),
required int port,
required ChannelOptions options,
}) : super(host, port: port, options: options);
}
21 changes: 13 additions & 8 deletions lib/src/client/grpc_or_grpcweb_channel_web.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,24 @@
import 'options.dart';
import 'web_channel.dart';

class GrpcOrGrpcWebClientChannel extends GrpcWebClientChannel {
GrpcOrGrpcWebClientChannel({
required String host,
class GrpcOrGrpcWebClientChannelInternal extends GrpcWebClientChannel {
GrpcOrGrpcWebClientChannelInternal({
required String grpcHost,
required int grpcPort,
required bool grpcTransportSecure,
required String grpcWebHost,
required int grpcWebPort,
required bool secure,
required bool grpcWebTransportSecure,
}) : super.xhr(Uri(
host: host, port: grpcWebPort, scheme: secure ? 'https' : 'http'));
host: grpcWebHost,
port: grpcWebPort,
scheme: grpcWebTransportSecure ? 'https' : 'http',
));

GrpcOrGrpcWebClientChannel.grpc(
GrpcOrGrpcWebClientChannelInternal.grpc(
Object host, {
int port = 443,
ChannelOptions options = const ChannelOptions(),
required int port,
required ChannelOptions options,
}) : super.xhr(
Uri(
host: host.toString(),
Expand Down
16 changes: 7 additions & 9 deletions test/client_tests/grpc_or_grpcweb_channel_grpc_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,32 +19,30 @@ import 'package:grpc/grpc_or_grpcweb.dart';
import 'package:test/test.dart';

const host = 'example.com';
const grpcPort = 9090;
const grpcWebPort = 8080;
const port = 8080;

void main() {
test('Channel on non-web uses gRPC ClientChannel with correct params', () {
final channel = GrpcOrGrpcWebClientChannel(
final channel = GrpcOrGrpcWebClientChannel.toSingleEndpoint(
host: host,
grpcPort: grpcPort,
grpcWebPort: grpcWebPort,
secure: false,
port: port,
transportSecure: false,
);
expect(channel is ClientChannel, isTrue);
expect(channel.host, equals(host));
expect(channel.port, equals(grpcPort));
expect(channel.port, equals(port));
expect(channel.options.credentials.isSecure, isFalse);
});

test('Constructor grpc on non-web passes params correctly', () {
final options = ChannelOptions(credentials: ChannelCredentials.insecure());
final channel = GrpcOrGrpcWebClientChannel.grpc(
host,
port: grpcPort,
port: port,
options: options,
);
expect(channel.host, equals(host));
expect(channel.port, equals(grpcPort));
expect(channel.port, equals(port));
expect(channel.options, same(options));
});
}
16 changes: 7 additions & 9 deletions test/client_tests/grpc_or_grpcweb_channel_web_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,23 @@ import 'package:grpc/grpc_web.dart';
import 'package:test/test.dart';

const host = 'example.com';
const grpcPort = 9090;
const grpcWebPort = 8080;
const port = 8080;

void main() {
test('Channel on web uses GrpcWebClientChannel with correct URI', () {
final channel = GrpcOrGrpcWebClientChannel(
final channel = GrpcOrGrpcWebClientChannel.toSingleEndpoint(
host: host,
grpcPort: grpcPort,
grpcWebPort: grpcWebPort,
secure: true,
port: port,
transportSecure: true,
);
expect(channel is GrpcWebClientChannel, isTrue);
final webChannel = channel as GrpcWebClientChannel;
expect(webChannel.uri,
equals(Uri(host: host, port: grpcWebPort, scheme: 'https')));
expect(
webChannel.uri, equals(Uri(host: host, port: port, scheme: 'https')));
});

test('Constructor grpc on web throws UnsupportedError', () {
expect(() => GrpcOrGrpcWebClientChannel.grpc(host, port: grpcPort),
expect(() => GrpcOrGrpcWebClientChannel.grpc(host, port: port),
throwsUnsupportedError);
});
}

0 comments on commit d4504da

Please sign in to comment.