From d7ae930e7fc05c07550fae8ca937806a2b6da210 Mon Sep 17 00:00:00 2001 From: Sigurd Meldgaard Date: Mon, 18 Mar 2019 13:46:50 +0100 Subject: [PATCH] Revert "Support grpc-web" (#159) This reverts commit d58659507c0de38de596411ca2890050b6d525f8. Development of grpc-web will continue on the branch https://github.com/grpc/grpc-dart/tree/grpc-web until it is ready. --- .gitignore | 1 - .travis.yml | 9 +- CHANGELOG.md | 5 - build.yaml | 5 - example/grpc-web/README.md | 62 -- example/grpc-web/lib/app.dart | 47 -- .../grpc-web/lib/src/generated/echo.pb.dart | 131 ---- .../lib/src/generated/echo.pbenum.dart | 6 - .../lib/src/generated/echo.pbgrpc.dart | 79 --- .../lib/src/generated/echo.pbjson.dart | 36 - example/grpc-web/protos/echo.proto | 41 -- example/grpc-web/pubspec.yaml | 15 - example/grpc-web/web/index.html | 42 -- example/grpc-web/web/main.dart | 48 -- .../lib/src/generated/helloworld.pbgrpc.dart | 2 +- example/helloworld/pubspec.yaml | 1 - interop/bin/server.dart | 6 - interop/lib/src/client.dart | 8 +- interop/lib/src/generated/empty.pb.dart | 36 +- interop/lib/src/generated/messages.pb.dart | 628 ++++++++++++------ .../lib/src/generated/messages.pbenum.dart | 20 +- interop/lib/src/generated/test.pb.dart | 7 +- interop/lib/src/generated/test.pbgrpc.dart | 362 +++++----- lib/grpc.dart | 6 +- lib/grpc_web.dart | 30 - lib/service_api.dart | 1 + lib/src/client/call.dart | 24 +- lib/src/client/channel.dart | 11 +- lib/src/client/connection.dart | 87 ++- lib/src/client/http2_channel.dart | 33 - lib/src/client/options.dart | 62 +- .../client/transport/http2_credentials.dart | 63 -- lib/src/client/transport/http2_transport.dart | 169 ----- lib/src/client/transport/transport.dart | 39 -- lib/src/client/transport/web_streams.dart | 160 ----- lib/src/client/transport/xhr_transport.dart | 140 ---- lib/src/client/web_channel.dart | 32 - lib/src/server/handler.dart | 3 +- lib/src/shared/message.dart | 63 -- lib/src/shared/streams.dart | 64 +- pubspec.yaml | 6 +- test/{client_tests => }/client_test.dart | 35 +- .../client_http2_transport_test.dart | 162 ----- .../client_xhr_transport_test.dart | 214 ------ test/options_test.dart | 7 +- test/server_test.dart | 1 - test/src/client_utils.dart | 80 +-- test/src/server_utils.dart | 6 +- test/src/utils.dart | 24 +- test/timeout_test.dart | 8 +- 50 files changed, 910 insertions(+), 2217 deletions(-) delete mode 100644 build.yaml delete mode 100644 example/grpc-web/README.md delete mode 100644 example/grpc-web/lib/app.dart delete mode 100644 example/grpc-web/lib/src/generated/echo.pb.dart delete mode 100644 example/grpc-web/lib/src/generated/echo.pbenum.dart delete mode 100644 example/grpc-web/lib/src/generated/echo.pbgrpc.dart delete mode 100644 example/grpc-web/lib/src/generated/echo.pbjson.dart delete mode 100644 example/grpc-web/protos/echo.proto delete mode 100644 example/grpc-web/pubspec.yaml delete mode 100644 example/grpc-web/web/index.html delete mode 100644 example/grpc-web/web/main.dart delete mode 100644 lib/grpc_web.dart delete mode 100644 lib/src/client/http2_channel.dart delete mode 100644 lib/src/client/transport/http2_credentials.dart delete mode 100644 lib/src/client/transport/http2_transport.dart delete mode 100644 lib/src/client/transport/transport.dart delete mode 100644 lib/src/client/transport/web_streams.dart delete mode 100644 lib/src/client/transport/xhr_transport.dart delete mode 100644 lib/src/client/web_channel.dart delete mode 100644 lib/src/shared/message.dart rename test/{client_tests => }/client_test.dart (93%) delete mode 100644 test/client_tests/client_http2_transport_test.dart delete mode 100644 test/client_tests/client_xhr_transport_test.dart diff --git a/.gitignore b/.gitignore index fdf3620..e851cc5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,6 @@ .dart_tool/ .packages .pub/ -.vscode/ build/ # Remove the following pattern if you wish to check in your lock file diff --git a/.travis.yml b/.travis.yml index a179581..4be7114 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,7 @@ language: dart +sudo: false -# necessary to avoid chrome sandboxing issues -sudo: required -addons: - chrome: stable - -# Run against both the dev and stable channel. +# Run against both the dev and channel. dart: - stable - dev @@ -13,7 +9,6 @@ dart: # Define test tasks to run. dart_task: - test: --platform vm - - test: --platform chrome # Only run one instance of the formatter and the analyzer, rather than running # them against each Dart version. diff --git a/CHANGELOG.md b/CHANGELOG.md index f9190db..38d5e9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,3 @@ -## 1.1.0 - -* Add initial support for grpc-web. - See `example/grpc-web` for an example of this working. - ## 1.0.1 * Add `service_api.dart` that only contains the minimal imports needed by the code generated by diff --git a/build.yaml b/build.yaml deleted file mode 100644 index 2a9825b..0000000 --- a/build.yaml +++ /dev/null @@ -1,5 +0,0 @@ -targets: - $default: - sources: - exclude: - - example/** diff --git a/example/grpc-web/README.md b/example/grpc-web/README.md deleted file mode 100644 index db9d82d..0000000 --- a/example/grpc-web/README.md +++ /dev/null @@ -1,62 +0,0 @@ -# Description -The grpc-web example shows how to use the Dart gRPC library with a gRPC-Web capable server. - -This is meant to be used with the echo example provided by the grpc-web repository. The definition of the service is given in echo.proto. - -# Prerequistes -You will need a clone of the [grpc-web](https://github.com/grpc/grpc-web) repository to run the example server. - -You will also need the dart 'webdev' tool, which you can get by running: - -```sh -$ pub global activate webdev -``` - -# Run the sample code -Follow the instructions for starting the grpc-web example server. The simplest version of this involves running the grpc-web server in a docker container with: - -```sh -$ docker-compose up echo-server envoy -``` - -To compile and run the example, assuming you are in the root of the grpc-web -folder, i.e., .../example/grpc-web/, first get the dependencies by running: - -```sh -$ pub get -``` - -Compile and run the website with: - -```sh -$ webdev serve web:9000 -``` - -Note that the alternate port (9000) is necessary because the grpc-web server runs the grpc server on port 8080 by default (the save as webdev). - -You can then navigate to http://localhost:9000/ to try out the example. - -# Regenerate the stubs - -If you have made changes to the message or service definition in -`protos/echo.proto` and need to regenerate the corresponding Dart files, -you will need to have protoc version 3.0.0 or higher and the Dart protoc plugin -version 16.0.0 or higher on your PATH. - -To install protoc, see the instructions on -[the Protocol Buffers website](https://developers.google.com/protocol-buffers/). - -The easiest way to get the Dart protoc plugin is by running - -```sh -$ pub global activate protoc_plugin -``` - -and follow the directions to add `~/.pub-cache/bin` to your PATH, if you haven't -already done so. - -You can now regenerate the Dart files by running - -```sh -$ protoc --dart_out=grpc:lib/src/generated -Iprotos protos/echo.proto -``` diff --git a/example/grpc-web/lib/app.dart b/example/grpc-web/lib/app.dart deleted file mode 100644 index 651e7a5..0000000 --- a/example/grpc-web/lib/app.dart +++ /dev/null @@ -1,47 +0,0 @@ -import 'dart:async'; -import 'dart:html'; - -import 'package:grpc_web/src/generated/echo.pbgrpc.dart'; - -class EchoApp { - final EchoServiceClient _service; - - EchoApp(this._service); - - Future echo(String message) async { - _addLeftMessage(message); - - final response = await _service.echo(new EchoRequest()..message = message); - _addRightMessage(response.message); - } - - void repeatEcho(String message, int count) { - _addLeftMessage(message); - final request = ServerStreamingEchoRequest() - ..message = message - ..messageCount = count - ..messageInterval = 500; - _service.serverStreamingEcho(request).listen((response) { - _addRightMessage(response.message); - }, onDone: () => print('Closed connection to server.')); - } - - void _addLeftMessage(String message) { - _addMessage(message, "label-primary pull-left"); - } - - void _addRightMessage(String message) { - _addMessage(message, "label-default pull-right"); - } - - void _addMessage(String message, String cssClass) { - final classes = cssClass.split(' '); - querySelector('#first').after(DivElement() - ..classes.add('row') - ..append(Element.tag('h2') - ..append(SpanElement() - ..classes.add('label') - ..classes.addAll(classes) - ..text = message))); - } -} diff --git a/example/grpc-web/lib/src/generated/echo.pb.dart b/example/grpc-web/lib/src/generated/echo.pb.dart deleted file mode 100644 index d349333..0000000 --- a/example/grpc-web/lib/src/generated/echo.pb.dart +++ /dev/null @@ -1,131 +0,0 @@ -/// -// Generated code. Do not modify. -// source: echo.proto -/// -// ignore_for_file: non_constant_identifier_names,library_prefixes,unused_import - -// ignore: UNUSED_SHOWN_NAME -import 'dart:core' show int, bool, double, String, List, Map, override; - -import 'package:protobuf/protobuf.dart' as $pb; - -class EchoRequest extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = new $pb.BuilderInfo('EchoRequest', package: const $pb.PackageName('grpc.gateway.testing')) - ..aOS(1, 'message') - ..hasRequiredFields = false - ; - - EchoRequest() : super(); - EchoRequest.fromBuffer(List i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromBuffer(i, r); - EchoRequest.fromJson(String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromJson(i, r); - EchoRequest clone() => new EchoRequest()..mergeFromMessage(this); - EchoRequest copyWith(void Function(EchoRequest) updates) => super.copyWith((message) => updates(message as EchoRequest)); - $pb.BuilderInfo get info_ => _i; - static EchoRequest create() => new EchoRequest(); - EchoRequest createEmptyInstance() => create(); - static $pb.PbList createRepeated() => new $pb.PbList(); - static EchoRequest getDefault() => _defaultInstance ??= create()..freeze(); - static EchoRequest _defaultInstance; - static void $checkItem(EchoRequest v) { - if (v is! EchoRequest) $pb.checkItemFailed(v, _i.qualifiedMessageName); - } - - String get message => $_getS(0, ''); - set message(String v) { $_setString(0, v); } - bool hasMessage() => $_has(0); - void clearMessage() => clearField(1); -} - -class EchoResponse extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = new $pb.BuilderInfo('EchoResponse', package: const $pb.PackageName('grpc.gateway.testing')) - ..aOS(1, 'message') - ..hasRequiredFields = false - ; - - EchoResponse() : super(); - EchoResponse.fromBuffer(List i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromBuffer(i, r); - EchoResponse.fromJson(String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromJson(i, r); - EchoResponse clone() => new EchoResponse()..mergeFromMessage(this); - EchoResponse copyWith(void Function(EchoResponse) updates) => super.copyWith((message) => updates(message as EchoResponse)); - $pb.BuilderInfo get info_ => _i; - static EchoResponse create() => new EchoResponse(); - EchoResponse createEmptyInstance() => create(); - static $pb.PbList createRepeated() => new $pb.PbList(); - static EchoResponse getDefault() => _defaultInstance ??= create()..freeze(); - static EchoResponse _defaultInstance; - static void $checkItem(EchoResponse v) { - if (v is! EchoResponse) $pb.checkItemFailed(v, _i.qualifiedMessageName); - } - - String get message => $_getS(0, ''); - set message(String v) { $_setString(0, v); } - bool hasMessage() => $_has(0); - void clearMessage() => clearField(1); -} - -class ServerStreamingEchoRequest extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = new $pb.BuilderInfo('ServerStreamingEchoRequest', package: const $pb.PackageName('grpc.gateway.testing')) - ..aOS(1, 'message') - ..a(2, 'messageCount', $pb.PbFieldType.O3) - ..a(3, 'messageInterval', $pb.PbFieldType.O3) - ..hasRequiredFields = false - ; - - ServerStreamingEchoRequest() : super(); - ServerStreamingEchoRequest.fromBuffer(List i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromBuffer(i, r); - ServerStreamingEchoRequest.fromJson(String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromJson(i, r); - ServerStreamingEchoRequest clone() => new ServerStreamingEchoRequest()..mergeFromMessage(this); - ServerStreamingEchoRequest copyWith(void Function(ServerStreamingEchoRequest) updates) => super.copyWith((message) => updates(message as ServerStreamingEchoRequest)); - $pb.BuilderInfo get info_ => _i; - static ServerStreamingEchoRequest create() => new ServerStreamingEchoRequest(); - ServerStreamingEchoRequest createEmptyInstance() => create(); - static $pb.PbList createRepeated() => new $pb.PbList(); - static ServerStreamingEchoRequest getDefault() => _defaultInstance ??= create()..freeze(); - static ServerStreamingEchoRequest _defaultInstance; - static void $checkItem(ServerStreamingEchoRequest v) { - if (v is! ServerStreamingEchoRequest) $pb.checkItemFailed(v, _i.qualifiedMessageName); - } - - String get message => $_getS(0, ''); - set message(String v) { $_setString(0, v); } - bool hasMessage() => $_has(0); - void clearMessage() => clearField(1); - - int get messageCount => $_get(1, 0); - set messageCount(int v) { $_setSignedInt32(1, v); } - bool hasMessageCount() => $_has(1); - void clearMessageCount() => clearField(2); - - int get messageInterval => $_get(2, 0); - set messageInterval(int v) { $_setSignedInt32(2, v); } - bool hasMessageInterval() => $_has(2); - void clearMessageInterval() => clearField(3); -} - -class ServerStreamingEchoResponse extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = new $pb.BuilderInfo('ServerStreamingEchoResponse', package: const $pb.PackageName('grpc.gateway.testing')) - ..aOS(1, 'message') - ..hasRequiredFields = false - ; - - ServerStreamingEchoResponse() : super(); - ServerStreamingEchoResponse.fromBuffer(List i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromBuffer(i, r); - ServerStreamingEchoResponse.fromJson(String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromJson(i, r); - ServerStreamingEchoResponse clone() => new ServerStreamingEchoResponse()..mergeFromMessage(this); - ServerStreamingEchoResponse copyWith(void Function(ServerStreamingEchoResponse) updates) => super.copyWith((message) => updates(message as ServerStreamingEchoResponse)); - $pb.BuilderInfo get info_ => _i; - static ServerStreamingEchoResponse create() => new ServerStreamingEchoResponse(); - ServerStreamingEchoResponse createEmptyInstance() => create(); - static $pb.PbList createRepeated() => new $pb.PbList(); - static ServerStreamingEchoResponse getDefault() => _defaultInstance ??= create()..freeze(); - static ServerStreamingEchoResponse _defaultInstance; - static void $checkItem(ServerStreamingEchoResponse v) { - if (v is! ServerStreamingEchoResponse) $pb.checkItemFailed(v, _i.qualifiedMessageName); - } - - String get message => $_getS(0, ''); - set message(String v) { $_setString(0, v); } - bool hasMessage() => $_has(0); - void clearMessage() => clearField(1); -} - diff --git a/example/grpc-web/lib/src/generated/echo.pbenum.dart b/example/grpc-web/lib/src/generated/echo.pbenum.dart deleted file mode 100644 index 11c02fb..0000000 --- a/example/grpc-web/lib/src/generated/echo.pbenum.dart +++ /dev/null @@ -1,6 +0,0 @@ -/// -// Generated code. Do not modify. -// source: echo.proto -/// -// ignore_for_file: non_constant_identifier_names,library_prefixes,unused_import - diff --git a/example/grpc-web/lib/src/generated/echo.pbgrpc.dart b/example/grpc-web/lib/src/generated/echo.pbgrpc.dart deleted file mode 100644 index 56fe21a..0000000 --- a/example/grpc-web/lib/src/generated/echo.pbgrpc.dart +++ /dev/null @@ -1,79 +0,0 @@ -/// -// Generated code. Do not modify. -// source: echo.proto -/// -// ignore_for_file: non_constant_identifier_names,library_prefixes,unused_import - -import 'dart:async' as $async; - -import 'package:grpc/service_api.dart' as $grpc; -import 'echo.pb.dart'; -export 'echo.pb.dart'; - -class EchoServiceClient extends $grpc.Client { - static final _$echo = new $grpc.ClientMethod( - '/grpc.gateway.testing.EchoService/Echo', - (EchoRequest value) => value.writeToBuffer(), - (List value) => new EchoResponse.fromBuffer(value)); - static final _$serverStreamingEcho = new $grpc.ClientMethod< - ServerStreamingEchoRequest, ServerStreamingEchoResponse>( - '/grpc.gateway.testing.EchoService/ServerStreamingEcho', - (ServerStreamingEchoRequest value) => value.writeToBuffer(), - (List value) => new ServerStreamingEchoResponse.fromBuffer(value)); - - EchoServiceClient($grpc.ClientChannel channel, {$grpc.CallOptions options}) - : super(channel, options: options); - - $grpc.ResponseFuture echo(EchoRequest request, - {$grpc.CallOptions options}) { - final call = $createCall(_$echo, new $async.Stream.fromIterable([request]), - options: options); - return new $grpc.ResponseFuture(call); - } - - $grpc.ResponseStream serverStreamingEcho( - ServerStreamingEchoRequest request, - {$grpc.CallOptions options}) { - final call = $createCall( - _$serverStreamingEcho, new $async.Stream.fromIterable([request]), - options: options); - return new $grpc.ResponseStream(call); - } -} - -abstract class EchoServiceBase extends $grpc.Service { - String get $name => 'grpc.gateway.testing.EchoService'; - - EchoServiceBase() { - $addMethod(new $grpc.ServiceMethod( - 'Echo', - echo_Pre, - false, - false, - (List value) => new EchoRequest.fromBuffer(value), - (EchoResponse value) => value.writeToBuffer())); - $addMethod(new $grpc.ServiceMethod( - 'ServerStreamingEcho', - serverStreamingEcho_Pre, - false, - true, - (List value) => new ServerStreamingEchoRequest.fromBuffer(value), - (ServerStreamingEchoResponse value) => value.writeToBuffer())); - } - - $async.Future echo_Pre( - $grpc.ServiceCall call, $async.Future request) async { - return echo(call, await request); - } - - $async.Stream serverStreamingEcho_Pre( - $grpc.ServiceCall call, $async.Future request) async* { - yield* serverStreamingEcho( - call, (await request) as ServerStreamingEchoRequest); - } - - $async.Future echo($grpc.ServiceCall call, EchoRequest request); - $async.Stream serverStreamingEcho( - $grpc.ServiceCall call, ServerStreamingEchoRequest request); -} diff --git a/example/grpc-web/lib/src/generated/echo.pbjson.dart b/example/grpc-web/lib/src/generated/echo.pbjson.dart deleted file mode 100644 index 0db13c7..0000000 --- a/example/grpc-web/lib/src/generated/echo.pbjson.dart +++ /dev/null @@ -1,36 +0,0 @@ -/// -// Generated code. Do not modify. -// source: echo.proto -/// -// ignore_for_file: non_constant_identifier_names,library_prefixes,unused_import - -const EchoRequest$json = const { - '1': 'EchoRequest', - '2': const [ - const {'1': 'message', '3': 1, '4': 1, '5': 9, '10': 'message'}, - ], -}; - -const EchoResponse$json = const { - '1': 'EchoResponse', - '2': const [ - const {'1': 'message', '3': 1, '4': 1, '5': 9, '10': 'message'}, - ], -}; - -const ServerStreamingEchoRequest$json = const { - '1': 'ServerStreamingEchoRequest', - '2': const [ - const {'1': 'message', '3': 1, '4': 1, '5': 9, '10': 'message'}, - const {'1': 'message_count', '3': 2, '4': 1, '5': 5, '10': 'messageCount'}, - const {'1': 'message_interval', '3': 3, '4': 1, '5': 5, '10': 'messageInterval'}, - ], -}; - -const ServerStreamingEchoResponse$json = const { - '1': 'ServerStreamingEchoResponse', - '2': const [ - const {'1': 'message', '3': 1, '4': 1, '5': 9, '10': 'message'}, - ], -}; - diff --git a/example/grpc-web/protos/echo.proto b/example/grpc-web/protos/echo.proto deleted file mode 100644 index 80a9507..0000000 --- a/example/grpc-web/protos/echo.proto +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2018 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package grpc.gateway.testing; - -message EchoRequest { - string message = 1; -} - -message EchoResponse { - string message = 1; -} - -message ServerStreamingEchoRequest { - string message = 1; - int32 message_count = 2; - int32 message_interval = 3; -} - -message ServerStreamingEchoResponse { - string message = 1; -} - -service EchoService { - rpc Echo(EchoRequest) returns (EchoResponse); - rpc ServerStreamingEcho(ServerStreamingEchoRequest) - returns (stream ServerStreamingEchoResponse); -} diff --git a/example/grpc-web/pubspec.yaml b/example/grpc-web/pubspec.yaml deleted file mode 100644 index 918f37f..0000000 --- a/example/grpc-web/pubspec.yaml +++ /dev/null @@ -1,15 +0,0 @@ -name: grpc_web -description: Dart gRPC-Web sample client -homepage: https://github.com/dart-lang/grpc-dart - -environment: - sdk: '>=2.0.0 <3.0.0' - -dependencies: - grpc: - path: ../../ - protobuf: ^0.13.4 - -dev_dependencies: - build_runner: ^0.10.0 - build_web_compilers: '^0.4.1' diff --git a/example/grpc-web/web/index.html b/example/grpc-web/web/index.html deleted file mode 100644 index a457cd2..0000000 --- a/example/grpc-web/web/index.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - Echo Example - - - - -
-
-
-
- - - - -
-

Example: "Hello", "4 Hello"

-
-
-
- - diff --git a/example/grpc-web/web/main.dart b/example/grpc-web/web/main.dart deleted file mode 100644 index 80dcf72..0000000 --- a/example/grpc-web/web/main.dart +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2018, the gRPC project authors. Please see the AUTHORS file -// for details. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -import 'dart:html'; - -import 'package:grpc/grpc_web.dart'; -import 'package:grpc_web/app.dart'; -import 'package:grpc_web/src/generated/echo.pbgrpc.dart'; - -void main() { - final channel = new GrpcWebClientChannel.xhr('http://localhost', - port: 8080); - final service = EchoServiceClient(channel); - final app = EchoApp(service); - - final button = querySelector('#send') as ButtonElement; - button.onClick.listen((e) async { - final msg = querySelector('#msg') as TextInputElement; - final value = msg.value.trim(); - msg.value = ''; - - if (value.isEmpty) return false; - - if (value.indexOf(' ') > 0) { - final countStr = value.substring(0, value.indexOf(' ')); - final count = int.tryParse(countStr); - - if (count != null) { - app.repeatEcho(value.substring(value.indexOf(' ') + 1), count); - } else { - app.echo(value); - } - } else { - app.echo(value); - } - }); -} diff --git a/example/helloworld/lib/src/generated/helloworld.pbgrpc.dart b/example/helloworld/lib/src/generated/helloworld.pbgrpc.dart index d29fb41..c390483 100644 --- a/example/helloworld/lib/src/generated/helloworld.pbgrpc.dart +++ b/example/helloworld/lib/src/generated/helloworld.pbgrpc.dart @@ -20,7 +20,7 @@ class GreeterClient extends Client { GreeterClient(ClientChannel channel, {CallOptions options}) : super(channel, options: options); - Future sayHello(HelloRequest request, + ResponseFuture sayHello(HelloRequest request, {CallOptions options}) { final call = $createCall(_$sayHello, new Stream.fromIterable([request]), options: options); diff --git a/example/helloworld/pubspec.yaml b/example/helloworld/pubspec.yaml index 8440e7b..9f14b4a 100644 --- a/example/helloworld/pubspec.yaml +++ b/example/helloworld/pubspec.yaml @@ -13,4 +13,3 @@ dependencies: dev_dependencies: test: ^1.3.0 - \ No newline at end of file diff --git a/interop/bin/server.dart b/interop/bin/server.dart index 7516338..9cd7ca2 100644 --- a/interop/bin/server.dart +++ b/interop/bin/server.dart @@ -114,12 +114,6 @@ class TestService extends TestServiceBase { final bufferedResponses = await request.map(_responseForRequest).toList(); yield* new Stream.fromIterable(bufferedResponses); } - - @override - Future unimplementedCall(ServiceCall call, Empty request) { - // TODO: implement unimplementedCall - return null; - } } Future main(List args) async { diff --git a/interop/lib/src/client.dart b/interop/lib/src/client.dart index c0571b6..d47895f 100644 --- a/interop/lib/src/client.dart +++ b/interop/lib/src/client.dart @@ -19,9 +19,9 @@ import 'dart:typed_data'; import 'package:collection/collection.dart'; import 'package:grpc/grpc.dart'; -import 'generated/empty.pb.dart'; -import 'generated/messages.pb.dart'; -import 'generated/test.pbgrpc.dart'; +import 'package:interop/src/generated/empty.pb.dart'; +import 'package:interop/src/generated/messages.pb.dart'; +import 'package:interop/src/generated/test.pbgrpc.dart'; const _headerEchoKey = 'x-grpc-test-echo-initial'; const _headerEchoData = 'test_initial_metadata_value'; @@ -95,7 +95,7 @@ class Tester { if (_useTestCA) { trustedRoot = new File('ca.pem').readAsBytesSync(); } - credentials = new Http2ChannelCredentials.secure( + credentials = new ChannelCredentials.secure( certificates: trustedRoot, authority: serverHostOverride); } else { credentials = const ChannelCredentials.insecure(); diff --git a/interop/lib/src/generated/empty.pb.dart b/interop/lib/src/generated/empty.pb.dart index 796cc61..4b040c7 100644 --- a/interop/lib/src/generated/empty.pb.dart +++ b/interop/lib/src/generated/empty.pb.dart @@ -1,32 +1,36 @@ /// // Generated code. Do not modify. -// source: empty.proto /// -// ignore_for_file: non_constant_identifier_names,library_prefixes,unused_import +// ignore_for_file: non_constant_identifier_names,library_prefixes +library grpc.testing_empty; // ignore: UNUSED_SHOWN_NAME -import 'dart:core' show int, bool, double, String, List, Map, override; +import 'dart:core' show int, bool, double, String, List, override; -import 'package:protobuf/protobuf.dart' as $pb; +import 'package:protobuf/protobuf.dart'; -class Empty extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = new $pb.BuilderInfo('Empty', package: const $pb.PackageName('grpc.testing')) - ..hasRequiredFields = false - ; +class Empty extends GeneratedMessage { + static final BuilderInfo _i = new BuilderInfo('Empty') + ..hasRequiredFields = false; Empty() : super(); - Empty.fromBuffer(List i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromBuffer(i, r); - Empty.fromJson(String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromJson(i, r); + Empty.fromBuffer(List i, [ExtensionRegistry r = ExtensionRegistry.EMPTY]) + : super.fromBuffer(i, r); + Empty.fromJson(String i, [ExtensionRegistry r = ExtensionRegistry.EMPTY]) + : super.fromJson(i, r); Empty clone() => new Empty()..mergeFromMessage(this); - Empty copyWith(void Function(Empty) updates) => super.copyWith((message) => updates(message as Empty)); - $pb.BuilderInfo get info_ => _i; + BuilderInfo get info_ => _i; static Empty create() => new Empty(); - Empty createEmptyInstance() => create(); - static $pb.PbList createRepeated() => new $pb.PbList(); - static Empty getDefault() => _defaultInstance ??= create()..freeze(); + static PbList createRepeated() => new PbList(); + static Empty getDefault() { + if (_defaultInstance == null) _defaultInstance = new _ReadonlyEmpty(); + return _defaultInstance; + } + static Empty _defaultInstance; static void $checkItem(Empty v) { - if (v is! Empty) $pb.checkItemFailed(v, _i.qualifiedMessageName); + if (v is! Empty) checkItemFailed(v, 'Empty'); } } +class _ReadonlyEmpty extends Empty with ReadonlyMessageMixin {} diff --git a/interop/lib/src/generated/messages.pb.dart b/interop/lib/src/generated/messages.pb.dart index 9f2d8e6..fe00e19 100644 --- a/interop/lib/src/generated/messages.pb.dart +++ b/interop/lib/src/generated/messages.pb.dart @@ -1,441 +1,655 @@ /// // Generated code. Do not modify. -// source: messages.proto /// -// ignore_for_file: non_constant_identifier_names,library_prefixes,unused_import +// ignore_for_file: non_constant_identifier_names,library_prefixes +library grpc.testing_messages; // ignore: UNUSED_SHOWN_NAME -import 'dart:core' show int, bool, double, String, List, Map, override; +import 'dart:core' show int, bool, double, String, List, override; -import 'package:protobuf/protobuf.dart' as $pb; +import 'package:protobuf/protobuf.dart'; import 'messages.pbenum.dart'; export 'messages.pbenum.dart'; -class BoolValue extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = new $pb.BuilderInfo('BoolValue', package: const $pb.PackageName('grpc.testing')) +class BoolValue extends GeneratedMessage { + static final BuilderInfo _i = new BuilderInfo('BoolValue') ..aOB(1, 'value') - ..hasRequiredFields = false - ; + ..hasRequiredFields = false; BoolValue() : super(); - BoolValue.fromBuffer(List i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromBuffer(i, r); - BoolValue.fromJson(String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromJson(i, r); + BoolValue.fromBuffer(List i, + [ExtensionRegistry r = ExtensionRegistry.EMPTY]) + : super.fromBuffer(i, r); + BoolValue.fromJson(String i, [ExtensionRegistry r = ExtensionRegistry.EMPTY]) + : super.fromJson(i, r); BoolValue clone() => new BoolValue()..mergeFromMessage(this); - BoolValue copyWith(void Function(BoolValue) updates) => super.copyWith((message) => updates(message as BoolValue)); - $pb.BuilderInfo get info_ => _i; + BuilderInfo get info_ => _i; static BoolValue create() => new BoolValue(); - BoolValue createEmptyInstance() => create(); - static $pb.PbList createRepeated() => new $pb.PbList(); - static BoolValue getDefault() => _defaultInstance ??= create()..freeze(); + static PbList createRepeated() => new PbList(); + static BoolValue getDefault() { + if (_defaultInstance == null) _defaultInstance = new _ReadonlyBoolValue(); + return _defaultInstance; + } + static BoolValue _defaultInstance; static void $checkItem(BoolValue v) { - if (v is! BoolValue) $pb.checkItemFailed(v, _i.qualifiedMessageName); + if (v is! BoolValue) checkItemFailed(v, 'BoolValue'); } bool get value => $_get(0, false); - set value(bool v) { $_setBool(0, v); } + set value(bool v) { + $_setBool(0, v); + } + bool hasValue() => $_has(0); void clearValue() => clearField(1); } -class Payload extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = new $pb.BuilderInfo('Payload', package: const $pb.PackageName('grpc.testing')) - ..e(1, 'type', $pb.PbFieldType.OE, PayloadType.COMPRESSABLE, PayloadType.valueOf, PayloadType.values) - ..a>(2, 'body', $pb.PbFieldType.OY) - ..hasRequiredFields = false - ; +class _ReadonlyBoolValue extends BoolValue with ReadonlyMessageMixin {} + +class Payload extends GeneratedMessage { + static final BuilderInfo _i = new BuilderInfo('Payload') + ..e(1, 'type', PbFieldType.OE, PayloadType.COMPRESSABLE, + PayloadType.valueOf, PayloadType.values) + ..a>(2, 'body', PbFieldType.OY) + ..hasRequiredFields = false; Payload() : super(); - Payload.fromBuffer(List i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromBuffer(i, r); - Payload.fromJson(String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromJson(i, r); + Payload.fromBuffer(List i, + [ExtensionRegistry r = ExtensionRegistry.EMPTY]) + : super.fromBuffer(i, r); + Payload.fromJson(String i, [ExtensionRegistry r = ExtensionRegistry.EMPTY]) + : super.fromJson(i, r); Payload clone() => new Payload()..mergeFromMessage(this); - Payload copyWith(void Function(Payload) updates) => super.copyWith((message) => updates(message as Payload)); - $pb.BuilderInfo get info_ => _i; + BuilderInfo get info_ => _i; static Payload create() => new Payload(); - Payload createEmptyInstance() => create(); - static $pb.PbList createRepeated() => new $pb.PbList(); - static Payload getDefault() => _defaultInstance ??= create()..freeze(); + static PbList createRepeated() => new PbList(); + static Payload getDefault() { + if (_defaultInstance == null) _defaultInstance = new _ReadonlyPayload(); + return _defaultInstance; + } + static Payload _defaultInstance; static void $checkItem(Payload v) { - if (v is! Payload) $pb.checkItemFailed(v, _i.qualifiedMessageName); + if (v is! Payload) checkItemFailed(v, 'Payload'); } PayloadType get type => $_getN(0); - set type(PayloadType v) { setField(1, v); } + set type(PayloadType v) { + setField(1, v); + } + bool hasType() => $_has(0); void clearType() => clearField(1); List get body => $_getN(1); - set body(List v) { $_setBytes(1, v); } + set body(List v) { + $_setBytes(1, v); + } + bool hasBody() => $_has(1); void clearBody() => clearField(2); } -class EchoStatus extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = new $pb.BuilderInfo('EchoStatus', package: const $pb.PackageName('grpc.testing')) - ..a(1, 'code', $pb.PbFieldType.O3) +class _ReadonlyPayload extends Payload with ReadonlyMessageMixin {} + +class EchoStatus extends GeneratedMessage { + static final BuilderInfo _i = new BuilderInfo('EchoStatus') + ..a(1, 'code', PbFieldType.O3) ..aOS(2, 'message') - ..hasRequiredFields = false - ; + ..hasRequiredFields = false; EchoStatus() : super(); - EchoStatus.fromBuffer(List i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromBuffer(i, r); - EchoStatus.fromJson(String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromJson(i, r); + EchoStatus.fromBuffer(List i, + [ExtensionRegistry r = ExtensionRegistry.EMPTY]) + : super.fromBuffer(i, r); + EchoStatus.fromJson(String i, [ExtensionRegistry r = ExtensionRegistry.EMPTY]) + : super.fromJson(i, r); EchoStatus clone() => new EchoStatus()..mergeFromMessage(this); - EchoStatus copyWith(void Function(EchoStatus) updates) => super.copyWith((message) => updates(message as EchoStatus)); - $pb.BuilderInfo get info_ => _i; + BuilderInfo get info_ => _i; static EchoStatus create() => new EchoStatus(); - EchoStatus createEmptyInstance() => create(); - static $pb.PbList createRepeated() => new $pb.PbList(); - static EchoStatus getDefault() => _defaultInstance ??= create()..freeze(); + static PbList createRepeated() => new PbList(); + static EchoStatus getDefault() { + if (_defaultInstance == null) _defaultInstance = new _ReadonlyEchoStatus(); + return _defaultInstance; + } + static EchoStatus _defaultInstance; static void $checkItem(EchoStatus v) { - if (v is! EchoStatus) $pb.checkItemFailed(v, _i.qualifiedMessageName); + if (v is! EchoStatus) checkItemFailed(v, 'EchoStatus'); } int get code => $_get(0, 0); - set code(int v) { $_setSignedInt32(0, v); } + set code(int v) { + $_setUnsignedInt32(0, v); + } + bool hasCode() => $_has(0); void clearCode() => clearField(1); String get message => $_getS(1, ''); - set message(String v) { $_setString(1, v); } + set message(String v) { + $_setString(1, v); + } + bool hasMessage() => $_has(1); void clearMessage() => clearField(2); } -class SimpleRequest extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = new $pb.BuilderInfo('SimpleRequest', package: const $pb.PackageName('grpc.testing')) - ..e(1, 'responseType', $pb.PbFieldType.OE, PayloadType.COMPRESSABLE, PayloadType.valueOf, PayloadType.values) - ..a(2, 'responseSize', $pb.PbFieldType.O3) - ..a(3, 'payload', $pb.PbFieldType.OM, Payload.getDefault, Payload.create) +class _ReadonlyEchoStatus extends EchoStatus with ReadonlyMessageMixin {} + +class SimpleRequest extends GeneratedMessage { + static final BuilderInfo _i = new BuilderInfo('SimpleRequest') + ..e(1, 'responseType', PbFieldType.OE, + PayloadType.COMPRESSABLE, PayloadType.valueOf, PayloadType.values) + ..a(2, 'responseSize', PbFieldType.O3) + ..a( + 3, 'payload', PbFieldType.OM, Payload.getDefault, Payload.create) ..aOB(4, 'fillUsername') ..aOB(5, 'fillOauthScope') - ..a(6, 'responseCompressed', $pb.PbFieldType.OM, BoolValue.getDefault, BoolValue.create) - ..a(7, 'responseStatus', $pb.PbFieldType.OM, EchoStatus.getDefault, EchoStatus.create) - ..a(8, 'expectCompressed', $pb.PbFieldType.OM, BoolValue.getDefault, BoolValue.create) - ..hasRequiredFields = false - ; + ..a(6, 'responseCompressed', PbFieldType.OM, + BoolValue.getDefault, BoolValue.create) + ..a(7, 'responseStatus', PbFieldType.OM, EchoStatus.getDefault, + EchoStatus.create) + ..a(8, 'expectCompressed', PbFieldType.OM, BoolValue.getDefault, + BoolValue.create) + ..hasRequiredFields = false; SimpleRequest() : super(); - SimpleRequest.fromBuffer(List i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromBuffer(i, r); - SimpleRequest.fromJson(String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromJson(i, r); + SimpleRequest.fromBuffer(List i, + [ExtensionRegistry r = ExtensionRegistry.EMPTY]) + : super.fromBuffer(i, r); + SimpleRequest.fromJson(String i, + [ExtensionRegistry r = ExtensionRegistry.EMPTY]) + : super.fromJson(i, r); SimpleRequest clone() => new SimpleRequest()..mergeFromMessage(this); - SimpleRequest copyWith(void Function(SimpleRequest) updates) => super.copyWith((message) => updates(message as SimpleRequest)); - $pb.BuilderInfo get info_ => _i; + BuilderInfo get info_ => _i; static SimpleRequest create() => new SimpleRequest(); - SimpleRequest createEmptyInstance() => create(); - static $pb.PbList createRepeated() => new $pb.PbList(); - static SimpleRequest getDefault() => _defaultInstance ??= create()..freeze(); + static PbList createRepeated() => new PbList(); + static SimpleRequest getDefault() { + if (_defaultInstance == null) + _defaultInstance = new _ReadonlySimpleRequest(); + return _defaultInstance; + } + static SimpleRequest _defaultInstance; static void $checkItem(SimpleRequest v) { - if (v is! SimpleRequest) $pb.checkItemFailed(v, _i.qualifiedMessageName); + if (v is! SimpleRequest) checkItemFailed(v, 'SimpleRequest'); } PayloadType get responseType => $_getN(0); - set responseType(PayloadType v) { setField(1, v); } + set responseType(PayloadType v) { + setField(1, v); + } + bool hasResponseType() => $_has(0); void clearResponseType() => clearField(1); int get responseSize => $_get(1, 0); - set responseSize(int v) { $_setSignedInt32(1, v); } + set responseSize(int v) { + $_setUnsignedInt32(1, v); + } + bool hasResponseSize() => $_has(1); void clearResponseSize() => clearField(2); Payload get payload => $_getN(2); - set payload(Payload v) { setField(3, v); } + set payload(Payload v) { + setField(3, v); + } + bool hasPayload() => $_has(2); void clearPayload() => clearField(3); bool get fillUsername => $_get(3, false); - set fillUsername(bool v) { $_setBool(3, v); } + set fillUsername(bool v) { + $_setBool(3, v); + } + bool hasFillUsername() => $_has(3); void clearFillUsername() => clearField(4); bool get fillOauthScope => $_get(4, false); - set fillOauthScope(bool v) { $_setBool(4, v); } + set fillOauthScope(bool v) { + $_setBool(4, v); + } + bool hasFillOauthScope() => $_has(4); void clearFillOauthScope() => clearField(5); BoolValue get responseCompressed => $_getN(5); - set responseCompressed(BoolValue v) { setField(6, v); } + set responseCompressed(BoolValue v) { + setField(6, v); + } + bool hasResponseCompressed() => $_has(5); void clearResponseCompressed() => clearField(6); EchoStatus get responseStatus => $_getN(6); - set responseStatus(EchoStatus v) { setField(7, v); } + set responseStatus(EchoStatus v) { + setField(7, v); + } + bool hasResponseStatus() => $_has(6); void clearResponseStatus() => clearField(7); BoolValue get expectCompressed => $_getN(7); - set expectCompressed(BoolValue v) { setField(8, v); } + set expectCompressed(BoolValue v) { + setField(8, v); + } + bool hasExpectCompressed() => $_has(7); void clearExpectCompressed() => clearField(8); } -class SimpleResponse extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = new $pb.BuilderInfo('SimpleResponse', package: const $pb.PackageName('grpc.testing')) - ..a(1, 'payload', $pb.PbFieldType.OM, Payload.getDefault, Payload.create) +class _ReadonlySimpleRequest extends SimpleRequest with ReadonlyMessageMixin {} + +class SimpleResponse extends GeneratedMessage { + static final BuilderInfo _i = new BuilderInfo('SimpleResponse') + ..a( + 1, 'payload', PbFieldType.OM, Payload.getDefault, Payload.create) ..aOS(2, 'username') ..aOS(3, 'oauthScope') - ..hasRequiredFields = false - ; + ..hasRequiredFields = false; SimpleResponse() : super(); - SimpleResponse.fromBuffer(List i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromBuffer(i, r); - SimpleResponse.fromJson(String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromJson(i, r); + SimpleResponse.fromBuffer(List i, + [ExtensionRegistry r = ExtensionRegistry.EMPTY]) + : super.fromBuffer(i, r); + SimpleResponse.fromJson(String i, + [ExtensionRegistry r = ExtensionRegistry.EMPTY]) + : super.fromJson(i, r); SimpleResponse clone() => new SimpleResponse()..mergeFromMessage(this); - SimpleResponse copyWith(void Function(SimpleResponse) updates) => super.copyWith((message) => updates(message as SimpleResponse)); - $pb.BuilderInfo get info_ => _i; + BuilderInfo get info_ => _i; static SimpleResponse create() => new SimpleResponse(); - SimpleResponse createEmptyInstance() => create(); - static $pb.PbList createRepeated() => new $pb.PbList(); - static SimpleResponse getDefault() => _defaultInstance ??= create()..freeze(); + static PbList createRepeated() => + new PbList(); + static SimpleResponse getDefault() { + if (_defaultInstance == null) + _defaultInstance = new _ReadonlySimpleResponse(); + return _defaultInstance; + } + static SimpleResponse _defaultInstance; static void $checkItem(SimpleResponse v) { - if (v is! SimpleResponse) $pb.checkItemFailed(v, _i.qualifiedMessageName); + if (v is! SimpleResponse) checkItemFailed(v, 'SimpleResponse'); } Payload get payload => $_getN(0); - set payload(Payload v) { setField(1, v); } + set payload(Payload v) { + setField(1, v); + } + bool hasPayload() => $_has(0); void clearPayload() => clearField(1); String get username => $_getS(1, ''); - set username(String v) { $_setString(1, v); } + set username(String v) { + $_setString(1, v); + } + bool hasUsername() => $_has(1); void clearUsername() => clearField(2); String get oauthScope => $_getS(2, ''); - set oauthScope(String v) { $_setString(2, v); } + set oauthScope(String v) { + $_setString(2, v); + } + bool hasOauthScope() => $_has(2); void clearOauthScope() => clearField(3); } -class StreamingInputCallRequest extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = new $pb.BuilderInfo('StreamingInputCallRequest', package: const $pb.PackageName('grpc.testing')) - ..a(1, 'payload', $pb.PbFieldType.OM, Payload.getDefault, Payload.create) - ..a(2, 'expectCompressed', $pb.PbFieldType.OM, BoolValue.getDefault, BoolValue.create) - ..hasRequiredFields = false - ; +class _ReadonlySimpleResponse extends SimpleResponse with ReadonlyMessageMixin { +} + +class StreamingInputCallRequest extends GeneratedMessage { + static final BuilderInfo _i = new BuilderInfo('StreamingInputCallRequest') + ..a( + 1, 'payload', PbFieldType.OM, Payload.getDefault, Payload.create) + ..a(2, 'expectCompressed', PbFieldType.OM, BoolValue.getDefault, + BoolValue.create) + ..hasRequiredFields = false; StreamingInputCallRequest() : super(); - StreamingInputCallRequest.fromBuffer(List i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromBuffer(i, r); - StreamingInputCallRequest.fromJson(String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromJson(i, r); - StreamingInputCallRequest clone() => new StreamingInputCallRequest()..mergeFromMessage(this); - StreamingInputCallRequest copyWith(void Function(StreamingInputCallRequest) updates) => super.copyWith((message) => updates(message as StreamingInputCallRequest)); - $pb.BuilderInfo get info_ => _i; + StreamingInputCallRequest.fromBuffer(List i, + [ExtensionRegistry r = ExtensionRegistry.EMPTY]) + : super.fromBuffer(i, r); + StreamingInputCallRequest.fromJson(String i, + [ExtensionRegistry r = ExtensionRegistry.EMPTY]) + : super.fromJson(i, r); + StreamingInputCallRequest clone() => + new StreamingInputCallRequest()..mergeFromMessage(this); + BuilderInfo get info_ => _i; static StreamingInputCallRequest create() => new StreamingInputCallRequest(); - StreamingInputCallRequest createEmptyInstance() => create(); - static $pb.PbList createRepeated() => new $pb.PbList(); - static StreamingInputCallRequest getDefault() => _defaultInstance ??= create()..freeze(); + static PbList createRepeated() => + new PbList(); + static StreamingInputCallRequest getDefault() { + if (_defaultInstance == null) + _defaultInstance = new _ReadonlyStreamingInputCallRequest(); + return _defaultInstance; + } + static StreamingInputCallRequest _defaultInstance; static void $checkItem(StreamingInputCallRequest v) { - if (v is! StreamingInputCallRequest) $pb.checkItemFailed(v, _i.qualifiedMessageName); + if (v is! StreamingInputCallRequest) + checkItemFailed(v, 'StreamingInputCallRequest'); } Payload get payload => $_getN(0); - set payload(Payload v) { setField(1, v); } + set payload(Payload v) { + setField(1, v); + } + bool hasPayload() => $_has(0); void clearPayload() => clearField(1); BoolValue get expectCompressed => $_getN(1); - set expectCompressed(BoolValue v) { setField(2, v); } + set expectCompressed(BoolValue v) { + setField(2, v); + } + bool hasExpectCompressed() => $_has(1); void clearExpectCompressed() => clearField(2); } -class StreamingInputCallResponse extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = new $pb.BuilderInfo('StreamingInputCallResponse', package: const $pb.PackageName('grpc.testing')) - ..a(1, 'aggregatedPayloadSize', $pb.PbFieldType.O3) - ..hasRequiredFields = false - ; +class _ReadonlyStreamingInputCallRequest extends StreamingInputCallRequest + with ReadonlyMessageMixin {} + +class StreamingInputCallResponse extends GeneratedMessage { + static final BuilderInfo _i = new BuilderInfo('StreamingInputCallResponse') + ..a(1, 'aggregatedPayloadSize', PbFieldType.O3) + ..hasRequiredFields = false; StreamingInputCallResponse() : super(); - StreamingInputCallResponse.fromBuffer(List i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromBuffer(i, r); - StreamingInputCallResponse.fromJson(String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromJson(i, r); - StreamingInputCallResponse clone() => new StreamingInputCallResponse()..mergeFromMessage(this); - StreamingInputCallResponse copyWith(void Function(StreamingInputCallResponse) updates) => super.copyWith((message) => updates(message as StreamingInputCallResponse)); - $pb.BuilderInfo get info_ => _i; - static StreamingInputCallResponse create() => new StreamingInputCallResponse(); - StreamingInputCallResponse createEmptyInstance() => create(); - static $pb.PbList createRepeated() => new $pb.PbList(); - static StreamingInputCallResponse getDefault() => _defaultInstance ??= create()..freeze(); + StreamingInputCallResponse.fromBuffer(List i, + [ExtensionRegistry r = ExtensionRegistry.EMPTY]) + : super.fromBuffer(i, r); + StreamingInputCallResponse.fromJson(String i, + [ExtensionRegistry r = ExtensionRegistry.EMPTY]) + : super.fromJson(i, r); + StreamingInputCallResponse clone() => + new StreamingInputCallResponse()..mergeFromMessage(this); + BuilderInfo get info_ => _i; + static StreamingInputCallResponse create() => + new StreamingInputCallResponse(); + static PbList createRepeated() => + new PbList(); + static StreamingInputCallResponse getDefault() { + if (_defaultInstance == null) + _defaultInstance = new _ReadonlyStreamingInputCallResponse(); + return _defaultInstance; + } + static StreamingInputCallResponse _defaultInstance; static void $checkItem(StreamingInputCallResponse v) { - if (v is! StreamingInputCallResponse) $pb.checkItemFailed(v, _i.qualifiedMessageName); + if (v is! StreamingInputCallResponse) + checkItemFailed(v, 'StreamingInputCallResponse'); } int get aggregatedPayloadSize => $_get(0, 0); - set aggregatedPayloadSize(int v) { $_setSignedInt32(0, v); } + set aggregatedPayloadSize(int v) { + $_setUnsignedInt32(0, v); + } + bool hasAggregatedPayloadSize() => $_has(0); void clearAggregatedPayloadSize() => clearField(1); } -class ResponseParameters extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = new $pb.BuilderInfo('ResponseParameters', package: const $pb.PackageName('grpc.testing')) - ..a(1, 'size', $pb.PbFieldType.O3) - ..a(2, 'intervalUs', $pb.PbFieldType.O3) - ..a(3, 'compressed', $pb.PbFieldType.OM, BoolValue.getDefault, BoolValue.create) - ..hasRequiredFields = false - ; +class _ReadonlyStreamingInputCallResponse extends StreamingInputCallResponse + with ReadonlyMessageMixin {} + +class ResponseParameters extends GeneratedMessage { + static final BuilderInfo _i = new BuilderInfo('ResponseParameters') + ..a(1, 'size', PbFieldType.O3) + ..a(2, 'intervalUs', PbFieldType.O3) + ..a( + 3, 'compressed', PbFieldType.OM, BoolValue.getDefault, BoolValue.create) + ..hasRequiredFields = false; ResponseParameters() : super(); - ResponseParameters.fromBuffer(List i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromBuffer(i, r); - ResponseParameters.fromJson(String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromJson(i, r); - ResponseParameters clone() => new ResponseParameters()..mergeFromMessage(this); - ResponseParameters copyWith(void Function(ResponseParameters) updates) => super.copyWith((message) => updates(message as ResponseParameters)); - $pb.BuilderInfo get info_ => _i; + ResponseParameters.fromBuffer(List i, + [ExtensionRegistry r = ExtensionRegistry.EMPTY]) + : super.fromBuffer(i, r); + ResponseParameters.fromJson(String i, + [ExtensionRegistry r = ExtensionRegistry.EMPTY]) + : super.fromJson(i, r); + ResponseParameters clone() => + new ResponseParameters()..mergeFromMessage(this); + BuilderInfo get info_ => _i; static ResponseParameters create() => new ResponseParameters(); - ResponseParameters createEmptyInstance() => create(); - static $pb.PbList createRepeated() => new $pb.PbList(); - static ResponseParameters getDefault() => _defaultInstance ??= create()..freeze(); + static PbList createRepeated() => + new PbList(); + static ResponseParameters getDefault() { + if (_defaultInstance == null) + _defaultInstance = new _ReadonlyResponseParameters(); + return _defaultInstance; + } + static ResponseParameters _defaultInstance; static void $checkItem(ResponseParameters v) { - if (v is! ResponseParameters) $pb.checkItemFailed(v, _i.qualifiedMessageName); + if (v is! ResponseParameters) checkItemFailed(v, 'ResponseParameters'); } int get size => $_get(0, 0); - set size(int v) { $_setSignedInt32(0, v); } + set size(int v) { + $_setUnsignedInt32(0, v); + } + bool hasSize() => $_has(0); void clearSize() => clearField(1); int get intervalUs => $_get(1, 0); - set intervalUs(int v) { $_setSignedInt32(1, v); } + set intervalUs(int v) { + $_setUnsignedInt32(1, v); + } + bool hasIntervalUs() => $_has(1); void clearIntervalUs() => clearField(2); BoolValue get compressed => $_getN(2); - set compressed(BoolValue v) { setField(3, v); } + set compressed(BoolValue v) { + setField(3, v); + } + bool hasCompressed() => $_has(2); void clearCompressed() => clearField(3); } -class StreamingOutputCallRequest extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = new $pb.BuilderInfo('StreamingOutputCallRequest', package: const $pb.PackageName('grpc.testing')) - ..e(1, 'responseType', $pb.PbFieldType.OE, PayloadType.COMPRESSABLE, PayloadType.valueOf, PayloadType.values) - ..pp(2, 'responseParameters', $pb.PbFieldType.PM, ResponseParameters.$checkItem, ResponseParameters.create) - ..a(3, 'payload', $pb.PbFieldType.OM, Payload.getDefault, Payload.create) - ..a(7, 'responseStatus', $pb.PbFieldType.OM, EchoStatus.getDefault, EchoStatus.create) - ..hasRequiredFields = false - ; +class _ReadonlyResponseParameters extends ResponseParameters + with ReadonlyMessageMixin {} + +class StreamingOutputCallRequest extends GeneratedMessage { + static final BuilderInfo _i = new BuilderInfo('StreamingOutputCallRequest') + ..e(1, 'responseType', PbFieldType.OE, + PayloadType.COMPRESSABLE, PayloadType.valueOf, PayloadType.values) + ..pp(2, 'responseParameters', PbFieldType.PM, + ResponseParameters.$checkItem, ResponseParameters.create) + ..a( + 3, 'payload', PbFieldType.OM, Payload.getDefault, Payload.create) + ..a(7, 'responseStatus', PbFieldType.OM, EchoStatus.getDefault, + EchoStatus.create) + ..hasRequiredFields = false; StreamingOutputCallRequest() : super(); - StreamingOutputCallRequest.fromBuffer(List i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromBuffer(i, r); - StreamingOutputCallRequest.fromJson(String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromJson(i, r); - StreamingOutputCallRequest clone() => new StreamingOutputCallRequest()..mergeFromMessage(this); - StreamingOutputCallRequest copyWith(void Function(StreamingOutputCallRequest) updates) => super.copyWith((message) => updates(message as StreamingOutputCallRequest)); - $pb.BuilderInfo get info_ => _i; - static StreamingOutputCallRequest create() => new StreamingOutputCallRequest(); - StreamingOutputCallRequest createEmptyInstance() => create(); - static $pb.PbList createRepeated() => new $pb.PbList(); - static StreamingOutputCallRequest getDefault() => _defaultInstance ??= create()..freeze(); + StreamingOutputCallRequest.fromBuffer(List i, + [ExtensionRegistry r = ExtensionRegistry.EMPTY]) + : super.fromBuffer(i, r); + StreamingOutputCallRequest.fromJson(String i, + [ExtensionRegistry r = ExtensionRegistry.EMPTY]) + : super.fromJson(i, r); + StreamingOutputCallRequest clone() => + new StreamingOutputCallRequest()..mergeFromMessage(this); + BuilderInfo get info_ => _i; + static StreamingOutputCallRequest create() => + new StreamingOutputCallRequest(); + static PbList createRepeated() => + new PbList(); + static StreamingOutputCallRequest getDefault() { + if (_defaultInstance == null) + _defaultInstance = new _ReadonlyStreamingOutputCallRequest(); + return _defaultInstance; + } + static StreamingOutputCallRequest _defaultInstance; static void $checkItem(StreamingOutputCallRequest v) { - if (v is! StreamingOutputCallRequest) $pb.checkItemFailed(v, _i.qualifiedMessageName); + if (v is! StreamingOutputCallRequest) + checkItemFailed(v, 'StreamingOutputCallRequest'); } PayloadType get responseType => $_getN(0); - set responseType(PayloadType v) { setField(1, v); } + set responseType(PayloadType v) { + setField(1, v); + } + bool hasResponseType() => $_has(0); void clearResponseType() => clearField(1); List get responseParameters => $_getList(1); Payload get payload => $_getN(2); - set payload(Payload v) { setField(3, v); } + set payload(Payload v) { + setField(3, v); + } + bool hasPayload() => $_has(2); void clearPayload() => clearField(3); EchoStatus get responseStatus => $_getN(3); - set responseStatus(EchoStatus v) { setField(7, v); } + set responseStatus(EchoStatus v) { + setField(7, v); + } + bool hasResponseStatus() => $_has(3); void clearResponseStatus() => clearField(7); } -class StreamingOutputCallResponse extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = new $pb.BuilderInfo('StreamingOutputCallResponse', package: const $pb.PackageName('grpc.testing')) - ..a(1, 'payload', $pb.PbFieldType.OM, Payload.getDefault, Payload.create) - ..hasRequiredFields = false - ; +class _ReadonlyStreamingOutputCallRequest extends StreamingOutputCallRequest + with ReadonlyMessageMixin {} + +class StreamingOutputCallResponse extends GeneratedMessage { + static final BuilderInfo _i = new BuilderInfo('StreamingOutputCallResponse') + ..a( + 1, 'payload', PbFieldType.OM, Payload.getDefault, Payload.create) + ..hasRequiredFields = false; StreamingOutputCallResponse() : super(); - StreamingOutputCallResponse.fromBuffer(List i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromBuffer(i, r); - StreamingOutputCallResponse.fromJson(String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromJson(i, r); - StreamingOutputCallResponse clone() => new StreamingOutputCallResponse()..mergeFromMessage(this); - StreamingOutputCallResponse copyWith(void Function(StreamingOutputCallResponse) updates) => super.copyWith((message) => updates(message as StreamingOutputCallResponse)); - $pb.BuilderInfo get info_ => _i; - static StreamingOutputCallResponse create() => new StreamingOutputCallResponse(); - StreamingOutputCallResponse createEmptyInstance() => create(); - static $pb.PbList createRepeated() => new $pb.PbList(); - static StreamingOutputCallResponse getDefault() => _defaultInstance ??= create()..freeze(); + StreamingOutputCallResponse.fromBuffer(List i, + [ExtensionRegistry r = ExtensionRegistry.EMPTY]) + : super.fromBuffer(i, r); + StreamingOutputCallResponse.fromJson(String i, + [ExtensionRegistry r = ExtensionRegistry.EMPTY]) + : super.fromJson(i, r); + StreamingOutputCallResponse clone() => + new StreamingOutputCallResponse()..mergeFromMessage(this); + BuilderInfo get info_ => _i; + static StreamingOutputCallResponse create() => + new StreamingOutputCallResponse(); + static PbList createRepeated() => + new PbList(); + static StreamingOutputCallResponse getDefault() { + if (_defaultInstance == null) + _defaultInstance = new _ReadonlyStreamingOutputCallResponse(); + return _defaultInstance; + } + static StreamingOutputCallResponse _defaultInstance; static void $checkItem(StreamingOutputCallResponse v) { - if (v is! StreamingOutputCallResponse) $pb.checkItemFailed(v, _i.qualifiedMessageName); + if (v is! StreamingOutputCallResponse) + checkItemFailed(v, 'StreamingOutputCallResponse'); } Payload get payload => $_getN(0); - set payload(Payload v) { setField(1, v); } + set payload(Payload v) { + setField(1, v); + } + bool hasPayload() => $_has(0); void clearPayload() => clearField(1); } -class ReconnectParams extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = new $pb.BuilderInfo('ReconnectParams', package: const $pb.PackageName('grpc.testing')) - ..a(1, 'maxReconnectBackoffMs', $pb.PbFieldType.O3) - ..hasRequiredFields = false - ; +class _ReadonlyStreamingOutputCallResponse extends StreamingOutputCallResponse + with ReadonlyMessageMixin {} + +class ReconnectParams extends GeneratedMessage { + static final BuilderInfo _i = new BuilderInfo('ReconnectParams') + ..a(1, 'maxReconnectBackoffMs', PbFieldType.O3) + ..hasRequiredFields = false; ReconnectParams() : super(); - ReconnectParams.fromBuffer(List i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromBuffer(i, r); - ReconnectParams.fromJson(String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromJson(i, r); + ReconnectParams.fromBuffer(List i, + [ExtensionRegistry r = ExtensionRegistry.EMPTY]) + : super.fromBuffer(i, r); + ReconnectParams.fromJson(String i, + [ExtensionRegistry r = ExtensionRegistry.EMPTY]) + : super.fromJson(i, r); ReconnectParams clone() => new ReconnectParams()..mergeFromMessage(this); - ReconnectParams copyWith(void Function(ReconnectParams) updates) => super.copyWith((message) => updates(message as ReconnectParams)); - $pb.BuilderInfo get info_ => _i; + BuilderInfo get info_ => _i; static ReconnectParams create() => new ReconnectParams(); - ReconnectParams createEmptyInstance() => create(); - static $pb.PbList createRepeated() => new $pb.PbList(); - static ReconnectParams getDefault() => _defaultInstance ??= create()..freeze(); + static PbList createRepeated() => + new PbList(); + static ReconnectParams getDefault() { + if (_defaultInstance == null) + _defaultInstance = new _ReadonlyReconnectParams(); + return _defaultInstance; + } + static ReconnectParams _defaultInstance; static void $checkItem(ReconnectParams v) { - if (v is! ReconnectParams) $pb.checkItemFailed(v, _i.qualifiedMessageName); + if (v is! ReconnectParams) checkItemFailed(v, 'ReconnectParams'); } int get maxReconnectBackoffMs => $_get(0, 0); - set maxReconnectBackoffMs(int v) { $_setSignedInt32(0, v); } + set maxReconnectBackoffMs(int v) { + $_setUnsignedInt32(0, v); + } + bool hasMaxReconnectBackoffMs() => $_has(0); void clearMaxReconnectBackoffMs() => clearField(1); } -class ReconnectInfo extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = new $pb.BuilderInfo('ReconnectInfo', package: const $pb.PackageName('grpc.testing')) +class _ReadonlyReconnectParams extends ReconnectParams + with ReadonlyMessageMixin {} + +class ReconnectInfo extends GeneratedMessage { + static final BuilderInfo _i = new BuilderInfo('ReconnectInfo') ..aOB(1, 'passed') - ..p(2, 'backoffMs', $pb.PbFieldType.P3) - ..hasRequiredFields = false - ; + ..p(2, 'backoffMs', PbFieldType.P3) + ..hasRequiredFields = false; ReconnectInfo() : super(); - ReconnectInfo.fromBuffer(List i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromBuffer(i, r); - ReconnectInfo.fromJson(String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) : super.fromJson(i, r); + ReconnectInfo.fromBuffer(List i, + [ExtensionRegistry r = ExtensionRegistry.EMPTY]) + : super.fromBuffer(i, r); + ReconnectInfo.fromJson(String i, + [ExtensionRegistry r = ExtensionRegistry.EMPTY]) + : super.fromJson(i, r); ReconnectInfo clone() => new ReconnectInfo()..mergeFromMessage(this); - ReconnectInfo copyWith(void Function(ReconnectInfo) updates) => super.copyWith((message) => updates(message as ReconnectInfo)); - $pb.BuilderInfo get info_ => _i; + BuilderInfo get info_ => _i; static ReconnectInfo create() => new ReconnectInfo(); - ReconnectInfo createEmptyInstance() => create(); - static $pb.PbList createRepeated() => new $pb.PbList(); - static ReconnectInfo getDefault() => _defaultInstance ??= create()..freeze(); + static PbList createRepeated() => new PbList(); + static ReconnectInfo getDefault() { + if (_defaultInstance == null) + _defaultInstance = new _ReadonlyReconnectInfo(); + return _defaultInstance; + } + static ReconnectInfo _defaultInstance; static void $checkItem(ReconnectInfo v) { - if (v is! ReconnectInfo) $pb.checkItemFailed(v, _i.qualifiedMessageName); + if (v is! ReconnectInfo) checkItemFailed(v, 'ReconnectInfo'); } bool get passed => $_get(0, false); - set passed(bool v) { $_setBool(0, v); } + set passed(bool v) { + $_setBool(0, v); + } + bool hasPassed() => $_has(0); void clearPassed() => clearField(1); List get backoffMs => $_getList(1); } +class _ReadonlyReconnectInfo extends ReconnectInfo with ReadonlyMessageMixin {} diff --git a/interop/lib/src/generated/messages.pbenum.dart b/interop/lib/src/generated/messages.pbenum.dart index 0830356..964d000 100644 --- a/interop/lib/src/generated/messages.pbenum.dart +++ b/interop/lib/src/generated/messages.pbenum.dart @@ -1,26 +1,26 @@ /// // Generated code. Do not modify. -// source: messages.proto /// -// ignore_for_file: non_constant_identifier_names,library_prefixes,unused_import +// ignore_for_file: non_constant_identifier_names,library_prefixes +library grpc.testing_messages_pbenum; // ignore_for_file: UNDEFINED_SHOWN_NAME,UNUSED_SHOWN_NAME import 'dart:core' show int, dynamic, String, List, Map; -import 'package:protobuf/protobuf.dart' as $pb; +import 'package:protobuf/protobuf.dart'; -class PayloadType extends $pb.ProtobufEnum { - static const PayloadType COMPRESSABLE = const PayloadType._(0, 'COMPRESSABLE'); +class PayloadType extends ProtobufEnum { + static const PayloadType COMPRESSABLE = + const PayloadType._(0, 'COMPRESSABLE'); - static const List values = const [ + static const List values = const [ COMPRESSABLE, ]; - static final Map _byValue = $pb.ProtobufEnum.initByValue(values); - static PayloadType valueOf(int value) => _byValue[value]; + static final Map _byValue = ProtobufEnum.initByValue(values); + static PayloadType valueOf(int value) => _byValue[value] as PayloadType; static void $checkItem(PayloadType v) { - if (v is! PayloadType) $pb.checkItemFailed(v, 'PayloadType'); + if (v is! PayloadType) checkItemFailed(v, 'PayloadType'); } const PayloadType._(int v, String n) : super(v, n); } - diff --git a/interop/lib/src/generated/test.pb.dart b/interop/lib/src/generated/test.pb.dart index d30adf9..d64b754 100644 --- a/interop/lib/src/generated/test.pb.dart +++ b/interop/lib/src/generated/test.pb.dart @@ -1,9 +1,8 @@ /// // Generated code. Do not modify. -// source: test.proto /// -// ignore_for_file: non_constant_identifier_names,library_prefixes,unused_import +// ignore_for_file: non_constant_identifier_names,library_prefixes +library grpc.testing_test; // ignore: UNUSED_SHOWN_NAME -import 'dart:core' show int, bool, double, String, List, Map, override; - +import 'dart:core' show int, bool, double, String, List, override; diff --git a/interop/lib/src/generated/test.pbgrpc.dart b/interop/lib/src/generated/test.pbgrpc.dart index 47f7d37..f7ba4db 100644 --- a/interop/lib/src/generated/test.pbgrpc.dart +++ b/interop/lib/src/generated/test.pbgrpc.dart @@ -1,343 +1,307 @@ /// // Generated code. Do not modify. -// source: test.proto /// -// ignore_for_file: non_constant_identifier_names,library_prefixes,unused_import +// ignore_for_file: non_constant_identifier_names,library_prefixes +library grpc.testing_test_pbgrpc; -import 'dart:async' as $async; +import 'dart:async'; -import 'package:grpc/service_api.dart' as $grpc; -import 'empty.pb.dart' as $0; -import 'messages.pb.dart' as $1; +import 'package:grpc/grpc.dart'; + +import 'empty.pb.dart'; +import 'messages.pb.dart'; export 'test.pb.dart'; -class TestServiceClient extends $grpc.Client { - static final _$emptyCall = new $grpc.ClientMethod<$0.Empty, $0.Empty>( +class TestServiceClient extends Client { + static final _$emptyCall = new ClientMethod( '/grpc.testing.TestService/EmptyCall', - ($0.Empty value) => value.writeToBuffer(), - (List value) => new $0.Empty.fromBuffer(value)); - static final _$unaryCall = - new $grpc.ClientMethod<$1.SimpleRequest, $1.SimpleResponse>( - '/grpc.testing.TestService/UnaryCall', - ($1.SimpleRequest value) => value.writeToBuffer(), - (List value) => new $1.SimpleResponse.fromBuffer(value)); + (Empty value) => value.writeToBuffer(), + (List value) => new Empty.fromBuffer(value)); + static final _$unaryCall = new ClientMethod( + '/grpc.testing.TestService/UnaryCall', + (SimpleRequest value) => value.writeToBuffer(), + (List value) => new SimpleResponse.fromBuffer(value)); static final _$cacheableUnaryCall = - new $grpc.ClientMethod<$1.SimpleRequest, $1.SimpleResponse>( + new ClientMethod( '/grpc.testing.TestService/CacheableUnaryCall', - ($1.SimpleRequest value) => value.writeToBuffer(), - (List value) => new $1.SimpleResponse.fromBuffer(value)); - static final _$streamingOutputCall = new $grpc.ClientMethod< - $1.StreamingOutputCallRequest, $1.StreamingOutputCallResponse>( - '/grpc.testing.TestService/StreamingOutputCall', - ($1.StreamingOutputCallRequest value) => value.writeToBuffer(), - (List value) => - new $1.StreamingOutputCallResponse.fromBuffer(value)); - static final _$streamingInputCall = new $grpc.ClientMethod< - $1.StreamingInputCallRequest, $1.StreamingInputCallResponse>( - '/grpc.testing.TestService/StreamingInputCall', - ($1.StreamingInputCallRequest value) => value.writeToBuffer(), - (List value) => new $1.StreamingInputCallResponse.fromBuffer(value)); - static final _$fullDuplexCall = new $grpc.ClientMethod< - $1.StreamingOutputCallRequest, $1.StreamingOutputCallResponse>( - '/grpc.testing.TestService/FullDuplexCall', - ($1.StreamingOutputCallRequest value) => value.writeToBuffer(), - (List value) => - new $1.StreamingOutputCallResponse.fromBuffer(value)); - static final _$halfDuplexCall = new $grpc.ClientMethod< - $1.StreamingOutputCallRequest, $1.StreamingOutputCallResponse>( - '/grpc.testing.TestService/HalfDuplexCall', - ($1.StreamingOutputCallRequest value) => value.writeToBuffer(), - (List value) => - new $1.StreamingOutputCallResponse.fromBuffer(value)); - static final _$unimplementedCall = new $grpc.ClientMethod<$0.Empty, $0.Empty>( + (SimpleRequest value) => value.writeToBuffer(), + (List value) => new SimpleResponse.fromBuffer(value)); + static final _$streamingOutputCall = + new ClientMethod( + '/grpc.testing.TestService/StreamingOutputCall', + (StreamingOutputCallRequest value) => value.writeToBuffer(), + (List value) => + new StreamingOutputCallResponse.fromBuffer(value)); + static final _$streamingInputCall = + new ClientMethod( + '/grpc.testing.TestService/StreamingInputCall', + (StreamingInputCallRequest value) => value.writeToBuffer(), + (List value) => + new StreamingInputCallResponse.fromBuffer(value)); + static final _$fullDuplexCall = + new ClientMethod( + '/grpc.testing.TestService/FullDuplexCall', + (StreamingOutputCallRequest value) => value.writeToBuffer(), + (List value) => + new StreamingOutputCallResponse.fromBuffer(value)); + static final _$halfDuplexCall = + new ClientMethod( + '/grpc.testing.TestService/HalfDuplexCall', + (StreamingOutputCallRequest value) => value.writeToBuffer(), + (List value) => + new StreamingOutputCallResponse.fromBuffer(value)); + static final _$unimplementedCall = new ClientMethod( '/grpc.testing.TestService/UnimplementedCall', - ($0.Empty value) => value.writeToBuffer(), - (List value) => new $0.Empty.fromBuffer(value)); + (Empty value) => value.writeToBuffer(), + (List value) => new Empty.fromBuffer(value)); - TestServiceClient($grpc.ClientChannel channel, {$grpc.CallOptions options}) + TestServiceClient(ClientChannel channel, {CallOptions options}) : super(channel, options: options); - $grpc.ResponseFuture<$0.Empty> emptyCall($0.Empty request, - {$grpc.CallOptions options}) { - final call = $createCall( - _$emptyCall, new $async.Stream.fromIterable([request]), + ResponseFuture emptyCall(Empty request, {CallOptions options}) { + final call = $createCall(_$emptyCall, new Stream.fromIterable([request]), options: options); - return new $grpc.ResponseFuture(call); + return new ResponseFuture(call); } - $grpc.ResponseFuture<$1.SimpleResponse> unaryCall($1.SimpleRequest request, - {$grpc.CallOptions options}) { - final call = $createCall( - _$unaryCall, new $async.Stream.fromIterable([request]), + ResponseFuture unaryCall(SimpleRequest request, + {CallOptions options}) { + final call = $createCall(_$unaryCall, new Stream.fromIterable([request]), options: options); - return new $grpc.ResponseFuture(call); + return new ResponseFuture(call); } - $grpc.ResponseFuture<$1.SimpleResponse> cacheableUnaryCall( - $1.SimpleRequest request, - {$grpc.CallOptions options}) { + ResponseFuture cacheableUnaryCall(SimpleRequest request, + {CallOptions options}) { final call = $createCall( - _$cacheableUnaryCall, new $async.Stream.fromIterable([request]), + _$cacheableUnaryCall, new Stream.fromIterable([request]), options: options); - return new $grpc.ResponseFuture(call); + return new ResponseFuture(call); } - $grpc.ResponseStream<$1.StreamingOutputCallResponse> streamingOutputCall( - $1.StreamingOutputCallRequest request, - {$grpc.CallOptions options}) { + ResponseStream streamingOutputCall( + StreamingOutputCallRequest request, + {CallOptions options}) { final call = $createCall( - _$streamingOutputCall, new $async.Stream.fromIterable([request]), + _$streamingOutputCall, new Stream.fromIterable([request]), options: options); - return new $grpc.ResponseStream(call); + return new ResponseStream(call); } - $grpc.ResponseFuture<$1.StreamingInputCallResponse> streamingInputCall( - $async.Stream<$1.StreamingInputCallRequest> request, - {$grpc.CallOptions options}) { + ResponseFuture streamingInputCall( + Stream request, + {CallOptions options}) { final call = $createCall(_$streamingInputCall, request, options: options); - return new $grpc.ResponseFuture(call); + return new ResponseFuture(call); } - $grpc.ResponseStream<$1.StreamingOutputCallResponse> fullDuplexCall( - $async.Stream<$1.StreamingOutputCallRequest> request, - {$grpc.CallOptions options}) { + ResponseStream fullDuplexCall( + Stream request, + {CallOptions options}) { final call = $createCall(_$fullDuplexCall, request, options: options); - return new $grpc.ResponseStream(call); + return new ResponseStream(call); } - $grpc.ResponseStream<$1.StreamingOutputCallResponse> halfDuplexCall( - $async.Stream<$1.StreamingOutputCallRequest> request, - {$grpc.CallOptions options}) { + ResponseStream halfDuplexCall( + Stream request, + {CallOptions options}) { final call = $createCall(_$halfDuplexCall, request, options: options); - return new $grpc.ResponseStream(call); + return new ResponseStream(call); } - $grpc.ResponseFuture<$0.Empty> unimplementedCall($0.Empty request, - {$grpc.CallOptions options}) { + ResponseFuture unimplementedCall(Empty request, + {CallOptions options}) { final call = $createCall( - _$unimplementedCall, new $async.Stream.fromIterable([request]), + _$unimplementedCall, new Stream.fromIterable([request]), options: options); - return new $grpc.ResponseFuture(call); + return new ResponseFuture(call); } } -abstract class TestServiceBase extends $grpc.Service { +abstract class TestServiceBase extends Service { String get $name => 'grpc.testing.TestService'; TestServiceBase() { - $addMethod(new $grpc.ServiceMethod<$0.Empty, $0.Empty>( + $addMethod(new ServiceMethod( 'EmptyCall', emptyCall_Pre, false, false, - (List value) => new $0.Empty.fromBuffer(value), - ($0.Empty value) => value.writeToBuffer())); - $addMethod(new $grpc.ServiceMethod<$1.SimpleRequest, $1.SimpleResponse>( + (List value) => new Empty.fromBuffer(value), + (Empty value) => value.writeToBuffer())); + $addMethod(new ServiceMethod( 'UnaryCall', unaryCall_Pre, false, false, - (List value) => new $1.SimpleRequest.fromBuffer(value), - ($1.SimpleResponse value) => value.writeToBuffer())); - $addMethod(new $grpc.ServiceMethod<$1.SimpleRequest, $1.SimpleResponse>( + (List value) => new SimpleRequest.fromBuffer(value), + (SimpleResponse value) => value.writeToBuffer())); + $addMethod(new ServiceMethod( 'CacheableUnaryCall', cacheableUnaryCall_Pre, false, false, - (List value) => new $1.SimpleRequest.fromBuffer(value), - ($1.SimpleResponse value) => value.writeToBuffer())); - $addMethod(new $grpc.ServiceMethod<$1.StreamingOutputCallRequest, - $1.StreamingOutputCallResponse>( + (List value) => new SimpleRequest.fromBuffer(value), + (SimpleResponse value) => value.writeToBuffer())); + $addMethod(new ServiceMethod( 'StreamingOutputCall', streamingOutputCall_Pre, false, true, - (List value) => - new $1.StreamingOutputCallRequest.fromBuffer(value), - ($1.StreamingOutputCallResponse value) => value.writeToBuffer())); - $addMethod(new $grpc.ServiceMethod<$1.StreamingInputCallRequest, - $1.StreamingInputCallResponse>( + (List value) => new StreamingOutputCallRequest.fromBuffer(value), + (StreamingOutputCallResponse value) => value.writeToBuffer())); + $addMethod(new ServiceMethod( 'StreamingInputCall', streamingInputCall, true, false, - (List value) => new $1.StreamingInputCallRequest.fromBuffer(value), - ($1.StreamingInputCallResponse value) => value.writeToBuffer())); - $addMethod(new $grpc.ServiceMethod<$1.StreamingOutputCallRequest, - $1.StreamingOutputCallResponse>( + (List value) => new StreamingInputCallRequest.fromBuffer(value), + (StreamingInputCallResponse value) => value.writeToBuffer())); + $addMethod(new ServiceMethod( 'FullDuplexCall', fullDuplexCall, true, true, - (List value) => - new $1.StreamingOutputCallRequest.fromBuffer(value), - ($1.StreamingOutputCallResponse value) => value.writeToBuffer())); - $addMethod(new $grpc.ServiceMethod<$1.StreamingOutputCallRequest, - $1.StreamingOutputCallResponse>( + (List value) => new StreamingOutputCallRequest.fromBuffer(value), + (StreamingOutputCallResponse value) => value.writeToBuffer())); + $addMethod(new ServiceMethod( 'HalfDuplexCall', halfDuplexCall, true, true, - (List value) => - new $1.StreamingOutputCallRequest.fromBuffer(value), - ($1.StreamingOutputCallResponse value) => value.writeToBuffer())); - $addMethod(new $grpc.ServiceMethod<$0.Empty, $0.Empty>( - 'UnimplementedCall', - unimplementedCall_Pre, - false, - false, - (List value) => new $0.Empty.fromBuffer(value), - ($0.Empty value) => value.writeToBuffer())); + (List value) => new StreamingOutputCallRequest.fromBuffer(value), + (StreamingOutputCallResponse value) => value.writeToBuffer())); } - $async.Future<$0.Empty> emptyCall_Pre( - $grpc.ServiceCall call, $async.Future request) async { + Future emptyCall_Pre(ServiceCall call, Future request) async { return emptyCall(call, await request); } - $async.Future<$1.SimpleResponse> unaryCall_Pre( - $grpc.ServiceCall call, $async.Future request) async { + Future unaryCall_Pre(ServiceCall call, Future request) async { return unaryCall(call, await request); } - $async.Future<$1.SimpleResponse> cacheableUnaryCall_Pre( - $grpc.ServiceCall call, $async.Future request) async { + Future cacheableUnaryCall_Pre( + ServiceCall call, Future request) async { return cacheableUnaryCall(call, await request); } - $async.Stream<$1.StreamingOutputCallResponse> streamingOutputCall_Pre( - $grpc.ServiceCall call, $async.Future request) async* { + Stream streamingOutputCall_Pre( + ServiceCall call, Future request) async* { yield* streamingOutputCall( - call, (await request) as $1.StreamingOutputCallRequest); + call, (await request) as StreamingOutputCallRequest); } - $async.Future<$0.Empty> unimplementedCall_Pre( - $grpc.ServiceCall call, $async.Future request) async { - return unimplementedCall(call, await request); - } - - $async.Future<$0.Empty> emptyCall($grpc.ServiceCall call, $0.Empty request); - $async.Future<$1.SimpleResponse> unaryCall( - $grpc.ServiceCall call, $1.SimpleRequest request); - $async.Future<$1.SimpleResponse> cacheableUnaryCall( - $grpc.ServiceCall call, $1.SimpleRequest request); - $async.Stream<$1.StreamingOutputCallResponse> streamingOutputCall( - $grpc.ServiceCall call, $1.StreamingOutputCallRequest request); - $async.Future<$1.StreamingInputCallResponse> streamingInputCall( - $grpc.ServiceCall call, - $async.Stream<$1.StreamingInputCallRequest> request); - $async.Stream<$1.StreamingOutputCallResponse> fullDuplexCall( - $grpc.ServiceCall call, - $async.Stream<$1.StreamingOutputCallRequest> request); - $async.Stream<$1.StreamingOutputCallResponse> halfDuplexCall( - $grpc.ServiceCall call, - $async.Stream<$1.StreamingOutputCallRequest> request); - $async.Future<$0.Empty> unimplementedCall( - $grpc.ServiceCall call, $0.Empty request); + Future emptyCall(ServiceCall call, Empty request); + Future unaryCall(ServiceCall call, SimpleRequest request); + Future cacheableUnaryCall( + ServiceCall call, SimpleRequest request); + Stream streamingOutputCall( + ServiceCall call, StreamingOutputCallRequest request); + Future streamingInputCall( + ServiceCall call, Stream request); + Stream fullDuplexCall( + ServiceCall call, Stream request); + Stream halfDuplexCall( + ServiceCall call, Stream request); } -class UnimplementedServiceClient extends $grpc.Client { - static final _$unimplementedCall = new $grpc.ClientMethod<$0.Empty, $0.Empty>( +class UnimplementedServiceClient extends Client { + static final _$unimplementedCall = new ClientMethod( '/grpc.testing.UnimplementedService/UnimplementedCall', - ($0.Empty value) => value.writeToBuffer(), - (List value) => new $0.Empty.fromBuffer(value)); + (Empty value) => value.writeToBuffer(), + (List value) => new Empty.fromBuffer(value)); - UnimplementedServiceClient($grpc.ClientChannel channel, - {$grpc.CallOptions options}) + UnimplementedServiceClient(ClientChannel channel, {CallOptions options}) : super(channel, options: options); - $grpc.ResponseFuture<$0.Empty> unimplementedCall($0.Empty request, - {$grpc.CallOptions options}) { + ResponseFuture unimplementedCall(Empty request, + {CallOptions options}) { final call = $createCall( - _$unimplementedCall, new $async.Stream.fromIterable([request]), + _$unimplementedCall, new Stream.fromIterable([request]), options: options); - return new $grpc.ResponseFuture(call); + return new ResponseFuture(call); } } -abstract class UnimplementedServiceBase extends $grpc.Service { +abstract class UnimplementedServiceBase extends Service { String get $name => 'grpc.testing.UnimplementedService'; UnimplementedServiceBase() { - $addMethod(new $grpc.ServiceMethod<$0.Empty, $0.Empty>( + $addMethod(new ServiceMethod( 'UnimplementedCall', unimplementedCall_Pre, false, false, - (List value) => new $0.Empty.fromBuffer(value), - ($0.Empty value) => value.writeToBuffer())); + (List value) => new Empty.fromBuffer(value), + (Empty value) => value.writeToBuffer())); } - $async.Future<$0.Empty> unimplementedCall_Pre( - $grpc.ServiceCall call, $async.Future request) async { + Future unimplementedCall_Pre(ServiceCall call, Future request) async { return unimplementedCall(call, await request); } - $async.Future<$0.Empty> unimplementedCall( - $grpc.ServiceCall call, $0.Empty request); + Future unimplementedCall(ServiceCall call, Empty request); } -class ReconnectServiceClient extends $grpc.Client { - static final _$start = new $grpc.ClientMethod<$1.ReconnectParams, $0.Empty>( +class ReconnectServiceClient extends Client { + static final _$start = new ClientMethod( '/grpc.testing.ReconnectService/Start', - ($1.ReconnectParams value) => value.writeToBuffer(), - (List value) => new $0.Empty.fromBuffer(value)); - static final _$stop = new $grpc.ClientMethod<$0.Empty, $1.ReconnectInfo>( + (ReconnectParams value) => value.writeToBuffer(), + (List value) => new Empty.fromBuffer(value)); + static final _$stop = new ClientMethod( '/grpc.testing.ReconnectService/Stop', - ($0.Empty value) => value.writeToBuffer(), - (List value) => new $1.ReconnectInfo.fromBuffer(value)); + (Empty value) => value.writeToBuffer(), + (List value) => new ReconnectInfo.fromBuffer(value)); - ReconnectServiceClient($grpc.ClientChannel channel, - {$grpc.CallOptions options}) + ReconnectServiceClient(ClientChannel channel, {CallOptions options}) : super(channel, options: options); - $grpc.ResponseFuture<$0.Empty> start($1.ReconnectParams request, - {$grpc.CallOptions options}) { - final call = $createCall(_$start, new $async.Stream.fromIterable([request]), + ResponseFuture start(ReconnectParams request, {CallOptions options}) { + final call = $createCall(_$start, new Stream.fromIterable([request]), options: options); - return new $grpc.ResponseFuture(call); + return new ResponseFuture(call); } - $grpc.ResponseFuture<$1.ReconnectInfo> stop($0.Empty request, - {$grpc.CallOptions options}) { - final call = $createCall(_$stop, new $async.Stream.fromIterable([request]), + ResponseFuture stop(Empty request, {CallOptions options}) { + final call = $createCall(_$stop, new Stream.fromIterable([request]), options: options); - return new $grpc.ResponseFuture(call); + return new ResponseFuture(call); } } -abstract class ReconnectServiceBase extends $grpc.Service { +abstract class ReconnectServiceBase extends Service { String get $name => 'grpc.testing.ReconnectService'; ReconnectServiceBase() { - $addMethod(new $grpc.ServiceMethod<$1.ReconnectParams, $0.Empty>( + $addMethod(new ServiceMethod( 'Start', start_Pre, false, false, - (List value) => new $1.ReconnectParams.fromBuffer(value), - ($0.Empty value) => value.writeToBuffer())); - $addMethod(new $grpc.ServiceMethod<$0.Empty, $1.ReconnectInfo>( + (List value) => new ReconnectParams.fromBuffer(value), + (Empty value) => value.writeToBuffer())); + $addMethod(new ServiceMethod( 'Stop', stop_Pre, false, false, - (List value) => new $0.Empty.fromBuffer(value), - ($1.ReconnectInfo value) => value.writeToBuffer())); + (List value) => new Empty.fromBuffer(value), + (ReconnectInfo value) => value.writeToBuffer())); } - $async.Future<$0.Empty> start_Pre( - $grpc.ServiceCall call, $async.Future request) async { + Future start_Pre(ServiceCall call, Future request) async { return start(call, await request); } - $async.Future<$1.ReconnectInfo> stop_Pre( - $grpc.ServiceCall call, $async.Future request) async { + Future stop_Pre(ServiceCall call, Future request) async { return stop(call, await request); } - $async.Future<$0.Empty> start( - $grpc.ServiceCall call, $1.ReconnectParams request); - $async.Future<$1.ReconnectInfo> stop( - $grpc.ServiceCall call, $0.Empty request); + Future start(ServiceCall call, ReconnectParams request); + Future stop(ServiceCall call, Empty request); } diff --git a/lib/grpc.dart b/lib/grpc.dart index b2f6398..28f2ae9 100644 --- a/lib/grpc.dart +++ b/lib/grpc.dart @@ -16,15 +16,12 @@ export 'src/auth/auth.dart'; export 'src/client/call.dart'; -export 'src/client/channel.dart' hide ClientChannel; +export 'src/client/channel.dart'; export 'src/client/client.dart'; export 'src/client/common.dart'; export 'src/client/connection.dart'; -export 'src/client/http2_channel.dart' show ClientChannel; export 'src/client/method.dart'; export 'src/client/options.dart'; -export 'src/client/transport/http2_credentials.dart'; -export 'src/client/transport/transport.dart'; export 'src/server/call.dart'; export 'src/server/handler.dart'; @@ -32,7 +29,6 @@ export 'src/server/interceptor.dart'; export 'src/server/server.dart'; export 'src/server/service.dart'; -export 'src/shared/message.dart'; export 'src/shared/security.dart'; export 'src/shared/status.dart'; export 'src/shared/streams.dart'; diff --git a/lib/grpc_web.dart b/lib/grpc_web.dart deleted file mode 100644 index 7d11de9..0000000 --- a/lib/grpc_web.dart +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2019, the gRPC project authors. Please see the AUTHORS file -// for details. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -export 'src/auth/auth.dart'; - -export 'src/client/call.dart'; -export 'src/client/channel.dart' hide ClientChannel; -export 'src/client/client.dart'; -export 'src/client/common.dart'; -export 'src/client/connection.dart'; -export 'src/client/method.dart'; -export 'src/client/options.dart'; -export 'src/client/transport/transport.dart'; -export 'src/client/web_channel.dart' show GrpcWebClientChannel; - -export 'src/shared/status.dart'; -export 'src/shared/streams.dart'; -export 'src/shared/timeout.dart'; diff --git a/lib/service_api.dart b/lib/service_api.dart index 19e5224..54a455a 100644 --- a/lib/service_api.dart +++ b/lib/service_api.dart @@ -24,4 +24,5 @@ export 'src/client/common.dart' show ResponseFuture, ResponseStream; export 'src/client/method.dart' show ClientMethod; export 'src/client/options.dart' show CallOptions; export 'src/server/call.dart' show ServiceCall; +export 'src/server/server.dart' show Server; export 'src/server/service.dart' show Service, ServiceMethod; diff --git a/lib/src/client/call.dart b/lib/src/client/call.dart index d7c6a38..b1c890f 100644 --- a/lib/src/client/call.dart +++ b/lib/src/client/call.dart @@ -1,4 +1,4 @@ -// Copyright (c) 2018, the gRPC project authors. Please see the AUTHORS file +// Copyright (c) 2017, the gRPC project authors. Please see the AUTHORS file // for details. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,14 +15,15 @@ import 'dart:async'; +import 'package:http2/transport.dart'; + import '../shared/status.dart'; -import '../shared/message.dart'; +import '../shared/streams.dart'; import 'common.dart'; import 'connection.dart'; import 'method.dart'; import 'options.dart'; -import 'transport/transport.dart'; const _reservedHeaders = const [ 'content-type', @@ -44,9 +45,9 @@ class ClientCall implements Response { Map _headerMetadata; - GrpcTransportStream _stream; + TransportStream _stream; StreamController _responses; - StreamSubscription> _requestSubscription; + StreamSubscription _requestSubscription; StreamSubscription _responseSubscription; bool isCancelled = false; @@ -119,6 +120,8 @@ class ClientCall implements Response { } _requestSubscription = _requests .map(_method.requestSerializer) + .map(GrpcHttpEncoder.frame) + .map((bytes) => new DataStreamMessage(bytes)) .handleError(_onRequestError) .listen(_stream.outgoingMessages.add, onError: _stream.outgoingMessages.addError, @@ -140,10 +143,13 @@ class ClientCall implements Response { if (_stream != null && _responses.hasListener && _responseSubscription == null) { - _responseSubscription = _stream.incomingMessages.listen(_onResponseData, - onError: _onResponseError, - onDone: _onResponseDone, - cancelOnError: true); + _responseSubscription = _stream.incomingMessages + .transform(new GrpcHttpDecoder()) + .transform(grpcDecompressor()) + .listen(_onResponseData, + onError: _onResponseError, + onDone: _onResponseDone, + cancelOnError: true); if (_responses.isPaused) { _responseSubscription.pause(); } diff --git a/lib/src/client/channel.dart b/lib/src/client/channel.dart index f1cb39e..68bd22f 100644 --- a/lib/src/client/channel.dart +++ b/lib/src/client/channel.dart @@ -21,28 +21,23 @@ import 'call.dart'; import 'connection.dart'; import 'method.dart'; import 'options.dart'; -import 'transport/transport.dart'; - -typedef ConnectTransport = Future Function( - String host, int port, ChannelOptions options); /// A channel to a virtual RPC endpoint. /// /// For each RPC, the channel picks a [ClientConnection] to dispatch the call. /// RPCs on the same channel may be sent to different connections, depending on /// load balancing settings. -abstract class ClientChannel { +class ClientChannel { final String host; final int port; final ChannelOptions options; - final ConnectTransport connectTransport; // TODO(jakobr): Multiple connections, load balancing. ClientConnection _connection; bool _isShutdown = false; - ClientChannel(this.host, this.connectTransport, + ClientChannel(this.host, {this.port = 443, this.options = const ChannelOptions()}); /// Shuts down this channel. @@ -69,7 +64,7 @@ abstract class ClientChannel { /// The connection may be shared between multiple RPCs. Future getConnection() async { if (_isShutdown) throw new GrpcError.unavailable('Channel shutting down.'); - return _connection ??= new ClientConnection(host, port, options, connectTransport); + return _connection ??= new ClientConnection(host, port, options); } /// Initiates a new RPC on this connection. diff --git a/lib/src/client/connection.dart b/lib/src/client/connection.dart index 67243c3..de002ac 100644 --- a/lib/src/client/connection.dart +++ b/lib/src/client/connection.dart @@ -14,16 +14,17 @@ // limitations under the License. import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; -import 'package:grpc/src/client/channel.dart'; +import 'package:http2/transport.dart'; import 'package:meta/meta.dart'; -import '../shared/status.dart'; +import '../shared/timeout.dart'; + import 'call.dart'; import 'options.dart'; -import 'transport/transport.dart'; - enum ConnectionState { /// Actively trying to connect. connecting, @@ -45,38 +46,98 @@ enum ConnectionState { /// /// RPCs made on a connection are always sent to the same endpoint. class ClientConnection { + static final _methodPost = new Header.ascii(':method', 'POST'); + static final _schemeHttp = new Header.ascii(':scheme', 'http'); + static final _schemeHttps = new Header.ascii(':scheme', 'https'); + static final _contentTypeGrpc = + new Header.ascii('content-type', 'application/grpc'); + static final _teTrailers = new Header.ascii('te', 'trailers'); + static final _grpcAcceptEncoding = + new Header.ascii('grpc-accept-encoding', 'identity'); + static final _userAgent = new Header.ascii('user-agent', 'dart-grpc/0.2.0'); + final String host; final int port; final ChannelOptions options; - final ConnectTransport connectTransport; ConnectionState _state = ConnectionState.idle; void Function(ClientConnection connection) onStateChanged; final _pendingCalls = []; - Transport _transport; + ClientTransportConnection _transport; /// Used for idle and reconnect timeout, depending on [_state]. Timer _timer; Duration _currentReconnectDelay; - ClientConnection(this.host, this.port, this.options, this.connectTransport); + ClientConnection(this.host, this.port, this.options); ConnectionState get state => _state; + static List
createCallHeaders(bool useTls, String authority, + String path, Duration timeout, Map metadata) { + final headers = [ + _methodPost, + useTls ? _schemeHttps : _schemeHttp, + new Header(ascii.encode(':path'), utf8.encode(path)), + new Header(ascii.encode(':authority'), utf8.encode(authority)), + ]; + if (timeout != null) { + headers.add(new Header.ascii('grpc-timeout', toTimeoutString(timeout))); + } + headers.addAll([ + _contentTypeGrpc, + _teTrailers, + _grpcAcceptEncoding, + _userAgent, + ]); + metadata?.forEach((key, value) { + headers.add(new Header(ascii.encode(key), utf8.encode(value))); + }); + return headers; + } + String get authority => options.credentials.authority ?? host; + @visibleForTesting + Future connectTransport() async { + final securityContext = options.credentials.securityContext; + + var socket = await Socket.connect(host, port); + if (_state == ConnectionState.shutdown) { + socket.destroy(); + throw 'Shutting down'; + } + if (securityContext != null) { + socket = await SecureSocket.secure(socket, + host: authority, + context: securityContext, + onBadCertificate: _validateBadCertificate); + if (_state == ConnectionState.shutdown) { + socket.destroy(); + throw 'Shutting down'; + } + } + socket.done.then(_handleSocketClosed); + return new ClientTransportConnection.viaSocket(socket); + } + + bool _validateBadCertificate(X509Certificate certificate) { + final validator = options.credentials.onBadCertificate; + if (validator == null) return false; + return validator(certificate, authority); + } + void _connect() { if (_state != ConnectionState.idle && _state != ConnectionState.transientFailure) { return; } _setState(ConnectionState.connecting); - connectTransport(host, port, options).then((transport) { + connectTransport().then((transport) { _currentReconnectDelay = null; _transport = transport; _transport.onActiveStateChanged = _handleActiveStateChanged; - _transport.onSocketClosed = _handleSocketClosed; _setState(ConnectionState.ready); _pendingCalls.forEach(_startCall); _pendingCalls.clear(); @@ -99,9 +160,11 @@ class ClientConnection { } } - GrpcTransportStream makeRequest( + ClientTransportStream makeRequest( String path, Duration timeout, Map metadata) { - return _transport.makeRequest(path, timeout, metadata); + final headers = createCallHeaders( + options.credentials.isSecure, authority, path, timeout, metadata); + return _transport.makeRequest(headers); } void _startCall(ClientCall call) { @@ -198,7 +261,7 @@ class ClientConnection { _connect(); } - void _handleSocketClosed() { + void _handleSocketClosed(_) { _cancelTimer(); _transport = null; diff --git a/lib/src/client/http2_channel.dart b/lib/src/client/http2_channel.dart deleted file mode 100644 index 9fc5710..0000000 --- a/lib/src/client/http2_channel.dart +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2019, the gRPC project authors. Please see the AUTHORS file -// for details. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:meta/meta.dart'; - -import 'channel.dart' as channel; -import 'options.dart'; -import 'transport/transport.dart'; -import 'transport/http2_transport.dart'; - -@visibleForTesting -Future connectTransport( - String host, int port, ChannelOptions options) async { - return Http2Transport(host, port, options)..connect(); -} - -class ClientChannel extends channel.ClientChannel { - ClientChannel(String host, - {int port = 443, ChannelOptions options = const ChannelOptions()}) - : super(host, connectTransport, port: port, options: options); -} diff --git a/lib/src/client/options.dart b/lib/src/client/options.dart index fb8c651..5daa61f 100644 --- a/lib/src/client/options.dart +++ b/lib/src/client/options.dart @@ -14,15 +14,18 @@ // limitations under the License. import 'dart:async'; -import 'package:meta/meta.dart'; +import 'dart:io'; import 'dart:math'; +import '../shared/security.dart'; + const defaultIdleTimeout = const Duration(minutes: 5); typedef Duration BackoffStrategy(Duration lastBackoff); // Backoff algorithm from https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md +const _minConnectTimeout = const Duration(seconds: 20); const _initialBackoff = const Duration(seconds: 1); const _maxBackoff = const Duration(seconds: 120); const _multiplier = 1.6; @@ -36,16 +39,54 @@ Duration defaultBackoffStrategy(Duration lastBackoff) { return nextBackoff < _maxBackoff ? nextBackoff : _maxBackoff; } +/// Handler for checking certificates that fail validation. If this handler +/// returns `true`, the bad certificate is allowed, and the TLS handshake can +/// continue. If the handler returns `false`, the TLS handshake fails, and the +/// connection is aborted. +typedef bool BadCertificateHandler(X509Certificate certificate, String host); + +/// Bad certificate handler that disables all certificate checks. +/// DO NOT USE IN PRODUCTION! +/// Can be used during development and testing to accept self-signed +/// certificates, etc. +bool allowBadCertificates(X509Certificate certificate, String host) => true; + /// Options controlling TLS security settings on a [ClientChannel]. class ChannelCredentials { final bool isSecure; + final List _certificateBytes; + final String _certificatePassword; final String authority; + final BadCertificateHandler onBadCertificate; - @visibleForOverriding - const ChannelCredentials(this.isSecure, this.authority); + const ChannelCredentials._(this.isSecure, this._certificateBytes, + this._certificatePassword, this.authority, this.onBadCertificate); /// Disable TLS. RPCs are sent in clear text. - const ChannelCredentials.insecure() : this(false, null); + const ChannelCredentials.insecure() : this._(false, null, null, null, null); + + /// Enable TLS and optionally specify the [certificates] to trust. If + /// [certificates] is not provided, the default trust store is used. + const ChannelCredentials.secure( + {List certificates, + String password, + String authority, + BadCertificateHandler onBadCertificate}) + : this._(true, certificates, password, authority, onBadCertificate); + + SecurityContext get securityContext { + if (!isSecure) return null; + if (_certificateBytes != null) { + return createSecurityContext(false) + ..setTrustedCertificatesBytes(_certificateBytes, + password: _certificatePassword); + } + final context = new SecurityContext(withTrustedRoots: true); + if (SecurityContext.alpnSupported) { + context.setAlpnProtocols(supportedAlpnProtocols, false); + } + return context; + } } /// Options controlling how connections are made on a [ClientChannel]. @@ -54,11 +95,14 @@ class ChannelOptions { final Duration idleTimeout; final BackoffStrategy backoffStrategy; - const ChannelOptions({ - ChannelCredentials credentials, - this.idleTimeout = defaultIdleTimeout, - this.backoffStrategy = defaultBackoffStrategy, - }) : this.credentials = credentials ?? const ChannelCredentials.insecure(); + const ChannelOptions( + {ChannelCredentials credentials, + Duration idleTimeout, + BackoffStrategy backoffStrategy = + defaultBackoffStrategy}) // Remove when dart-lang/sdk#31066 is fixed. + : this.credentials = credentials ?? const ChannelCredentials.secure(), + this.idleTimeout = idleTimeout ?? defaultIdleTimeout, + this.backoffStrategy = backoffStrategy ?? defaultBackoffStrategy; } /// Provides per-RPC metadata. diff --git a/lib/src/client/transport/http2_credentials.dart b/lib/src/client/transport/http2_credentials.dart deleted file mode 100644 index 729dc7c..0000000 --- a/lib/src/client/transport/http2_credentials.dart +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2018, the gRPC project authors. Please see the AUTHORS file -// for details. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'dart:io'; - -import '../../shared/security.dart'; -import '../options.dart'; - -/// Handler for checking certificates that fail validation. If this handler -/// returns `true`, the bad certificate is allowed, and the TLS handshake can -/// continue. If the handler returns `false`, the TLS handshake fails, and the -/// connection is aborted. -typedef bool BadCertificateHandler(X509Certificate certificate, String host); - -/// Bad certificate handler that disables all certificate checks. -/// DO NOT USE IN PRODUCTION! -/// Can be used during development and testing to accept self-signed -/// certificates, etc. -bool allowBadCertificates(X509Certificate certificate, String host) => true; - -class Http2ChannelCredentials extends ChannelCredentials { - final List _certificateBytes; - final String _certificatePassword; - final BadCertificateHandler onBadCertificate; - - const Http2ChannelCredentials._(bool isSecure, String authority, - this._certificateBytes, this._certificatePassword, this.onBadCertificate) - : super(isSecure, authority); - - /// Enable TLS and optionally specify the [certificates] to trust. If - /// [certificates] is not provided, the default trust store is used. - const Http2ChannelCredentials.secure( - {List certificates, - String password, - String authority, - BadCertificateHandler onBadCertificate}) - : this._(true, authority, certificates, password, onBadCertificate); - - SecurityContext get securityContext { - if (!isSecure) return null; - if (_certificateBytes != null) { - return createSecurityContext(false) - ..setTrustedCertificatesBytes(_certificateBytes, - password: _certificatePassword); - } - final context = new SecurityContext(withTrustedRoots: true); - context.setAlpnProtocols(supportedAlpnProtocols, false); - - return context; - } -} diff --git a/lib/src/client/transport/http2_transport.dart b/lib/src/client/transport/http2_transport.dart deleted file mode 100644 index f84dbc9..0000000 --- a/lib/src/client/transport/http2_transport.dart +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright (c) 2018, the gRPC project authors. Please see the AUTHORS file -// for details. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'dart:async'; -import 'dart:convert'; -import 'dart:io'; - -import 'package:http2/transport.dart'; -import 'package:meta/meta.dart'; - -import '../../shared/message.dart'; -import '../../shared/streams.dart'; -import '../../shared/timeout.dart'; - -import '../options.dart'; - -import 'http2_credentials.dart'; -import 'transport.dart'; - -class Http2TransportStream extends GrpcTransportStream { - TransportStream _transportStream; - StreamController _incomingMessages; - StreamController> _outgoingMessages; - - Stream get incomingMessages => _incomingMessages.stream; - StreamSink> get outgoingMessages => _outgoingMessages.sink; - - Http2TransportStream(this._transportStream) { - _incomingMessages = new StreamController(); - _outgoingMessages = new StreamController(); - - _transportStream.incomingMessages - .transform(new GrpcHttpDecoder()) - .transform(grpcDecompressor()) - .pipe(_incomingMessages); - - _outgoingMessages.stream - .map(frame) - .map((bytes) => new DataStreamMessage(bytes)) - .handleError(_onRequestError) - .listen(_transportStream.outgoingMessages.add, - onError: _transportStream.outgoingMessages.addError, - onDone: _transportStream.outgoingMessages.close, - cancelOnError: true); - } - - void _onRequestError() { - // TODO: Implement errors on requests - } - - @override - Future terminate() async { - await _incomingMessages.close(); - await _outgoingMessages.close(); - _transportStream.terminate(); - } -} - -class Http2Transport extends Transport { - static final _methodPost = new Header.ascii(':method', 'POST'); - static final _schemeHttp = new Header.ascii(':scheme', 'http'); - static final _schemeHttps = new Header.ascii(':scheme', 'https'); - static final _contentTypeGrpc = - new Header.ascii('content-type', 'application/grpc'); - static final _teTrailers = new Header.ascii('te', 'trailers'); - static final _grpcAcceptEncoding = - new Header.ascii('grpc-accept-encoding', 'identity'); - static final _userAgent = new Header.ascii('user-agent', 'dart-grpc/0.2.0'); - - final String host; - final int port; - final ChannelOptions options; - - @visibleForTesting - ClientTransportConnection transportConnection; - - Http2Transport(this.host, this.port, this.options); - - String get authority => options.credentials.authority ?? host; - - static List
createCallHeaders(bool useTls, String authority, - String path, Duration timeout, Map metadata) { - final headers = [ - _methodPost, - useTls ? _schemeHttps : _schemeHttp, - new Header(ascii.encode(':path'), utf8.encode(path)), - new Header(ascii.encode(':authority'), utf8.encode(authority)), - ]; - if (timeout != null) { - headers.add(new Header.ascii('grpc-timeout', toTimeoutString(timeout))); - } - headers.addAll([ - _contentTypeGrpc, - _teTrailers, - _grpcAcceptEncoding, - _userAgent, - ]); - metadata?.forEach((key, value) { - headers.add(new Header(ascii.encode(key), utf8.encode(value))); - }); - return headers; - } - - @override - Future connect() async { - var socket = await Socket.connect(host, port); - - final credentials = options.credentials; - if (credentials is Http2ChannelCredentials) { - final securityContext = credentials.securityContext; - if (securityContext != null) { - socket = await SecureSocket.secure(socket, - host: authority, - context: securityContext, - onBadCertificate: _validateBadCertificate); - } - } - socket.done.then(_handleSocketClosed); - transportConnection = ClientTransportConnection.viaSocket(socket); - } - - @override - GrpcTransportStream makeRequest( - String path, Duration timeout, Map metadata) { - final headers = createCallHeaders( - options.credentials.isSecure, authority, path, timeout, metadata); - final stream = transportConnection.makeRequest(headers); - return new Http2TransportStream(stream); - } - - @override - Future finish() async { - await transportConnection.finish(); - } - - @override - Future terminate() async { - await transportConnection.terminate(); - } - - bool _validateBadCertificate(X509Certificate certificate) { - final credentials = options.credentials; - if (credentials is Http2ChannelCredentials) { - final validator = credentials.onBadCertificate; - - if (validator == null) return false; - return validator(certificate, authority); - } - return false; - } - - void _handleSocketClosed(_) { - if (onSocketClosed != null) { - onSocketClosed(); - } - } -} diff --git a/lib/src/client/transport/transport.dart b/lib/src/client/transport/transport.dart deleted file mode 100644 index f33f233..0000000 --- a/lib/src/client/transport/transport.dart +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2018, the gRPC project authors. Please see the AUTHORS file -// for details. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'dart:async'; - -import '../../shared/message.dart'; - -typedef void SocketClosedHandler(); -typedef void ActiveStateHandler(bool isActive); - -abstract class GrpcTransportStream { - Stream get incomingMessages; - StreamSink> get outgoingMessages; - - Future terminate(); -} - -abstract class Transport { - ActiveStateHandler onActiveStateChanged; - SocketClosedHandler onSocketClosed; - - Future connect(); - GrpcTransportStream makeRequest( - String path, Duration timeout, Map metadata); - Future finish(); - Future terminate(); -} diff --git a/lib/src/client/transport/web_streams.dart b/lib/src/client/transport/web_streams.dart deleted file mode 100644 index 56918f1..0000000 --- a/lib/src/client/transport/web_streams.dart +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright (c) 2019, the gRPC project authors. Please see the AUTHORS file -// for details. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - - -import 'dart:convert'; -import 'dart:math'; -import 'dart:typed_data'; - -import '../../shared/message.dart'; -import '../../shared/status.dart'; - -enum _GrpcWebParseState { Init, Length, Message } - -class GrpcWebDecoder extends Converter { - @override - GrpcMessage convert(ByteBuffer input) { - final sink = GrpcMessageSink(); - startChunkedConversion(sink) - ..add(input) - ..close(); - return sink.message; - } - - @override - Sink startChunkedConversion(Sink sink) { - return _GrpcWebConversionSink(sink); - } -} - -class _GrpcWebConversionSink extends ChunkedConversionSink { - static const int frameTypeData = 0x00; - static const int frameTypeTrailers = 0x80; - - final Sink _out; - - final _dataHeader = new Uint8List(4); - - _GrpcWebParseState _state = _GrpcWebParseState.Init; - int _chunkOffset; - int _frameType; - int _dataOffset = 0; - Uint8List _data; - - _GrpcWebConversionSink(this._out); - - int _parseFrameType(List chunkData) { - final frameType = chunkData[_chunkOffset]; - _chunkOffset++; - if (frameType != frameTypeData && frameType != frameTypeTrailers) { - throw GrpcError.unimplemented('Invalid frame type: ${frameType}'); - } - _state = _GrpcWebParseState.Length; - return frameType; - } - - void _parseLength(List chunkData) { - final chunkLength = chunkData.length; - - final headerRemaining = _dataHeader.lengthInBytes - _dataOffset; - final chunkRemaining = chunkLength - _chunkOffset; - final toCopy = min(headerRemaining, chunkRemaining); - _dataHeader.setRange( - _dataOffset, _dataOffset + toCopy, chunkData, _chunkOffset); - _dataOffset += toCopy; - _chunkOffset += toCopy; - if (_dataOffset == _dataHeader.lengthInBytes) { - final dataLength = _dataHeader.buffer.asByteData().getUint32(0); - _dataOffset = 0; - _state = _GrpcWebParseState.Message; - if (dataLength == 0) { - // empty message - _finishMessage(); - } - - _data = new Uint8List(dataLength); - } - } - - void _parseMessage(List chunkData) { - final dataRemaining = _data.lengthInBytes - _dataOffset; - if (dataRemaining > 0) { - final chunkRemaining = chunkData.length - _chunkOffset; - final toCopy = min(dataRemaining, chunkRemaining); - _data.setRange( - _dataOffset, _dataOffset + toCopy, chunkData, _chunkOffset); - _dataOffset += toCopy; - _chunkOffset += toCopy; - } - if (_dataOffset == _data.lengthInBytes) { - _finishMessage(); - } - } - - void _finishMessage() { - switch (_frameType) { - case frameTypeData: - _out.add(new GrpcData(_data, isCompressed: false)); - break; - case frameTypeTrailers: - final stringData = String.fromCharCodes(_data); - final headers = _parseHttp1Headers(stringData); - _out.add(new GrpcMetadata(headers)); - break; - } - _state = _GrpcWebParseState.Init; - _data = null; - _dataOffset = 0; - } - - Map _parseHttp1Headers(String stringData) { - final chunks = stringData.trim().split('\r\n'); - final headers = {}; - for (final chunk in chunks) { - final pos = chunk.indexOf(':'); - headers[chunk.substring(0, pos).trim()] = chunk.substring(pos + 1).trim(); - } - return headers; - } - - @override - void add(ByteBuffer chunk) { - _chunkOffset = 0; - final chunkData = chunk.asUint8List(); - while (_chunkOffset < chunk.lengthInBytes) { - switch (_state) { - case _GrpcWebParseState.Init: - _frameType = _parseFrameType(chunkData); - break; - case _GrpcWebParseState.Length: - _parseLength(chunkData); - break; - case _GrpcWebParseState.Message: - _parseMessage(chunkData); - break; - } - } - _chunkOffset = 0; - } - - @override - void close() { - if (_data != null || _dataOffset != 0) { - throw new GrpcError.unavailable('Closed in non-idle state'); - } - _out.close(); - } -} - diff --git a/lib/src/client/transport/xhr_transport.dart b/lib/src/client/transport/xhr_transport.dart deleted file mode 100644 index dd23dc3..0000000 --- a/lib/src/client/transport/xhr_transport.dart +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) 2018, the gRPC project authors. Please see the AUTHORS file -// for details. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'dart:async'; -import 'dart:html'; -import 'dart:typed_data'; - -import 'package:meta/meta.dart'; - -import '../../shared/message.dart'; -import 'transport.dart'; -import 'web_streams.dart'; - -class XhrTransportStream implements GrpcTransportStream { - HttpRequest _request; - int _requestBytesRead = 0; - StreamController _incomingProcessor; - StreamController _incomingMessages; - StreamController> _outgoingMessages; - - @override - Stream get incomingMessages => _incomingMessages.stream; - - @override - StreamSink> get outgoingMessages => _outgoingMessages.sink; - - XhrTransportStream(this._request) { - _incomingProcessor = StreamController(); - _incomingMessages = StreamController(); - _outgoingMessages = StreamController(); - - _incomingProcessor.stream - .transform(GrpcWebDecoder()) - .transform(grpcDecompressor()) - .listen(_incomingMessages.add, - onError: _incomingMessages.addError, - onDone: _incomingMessages.close); - - _outgoingMessages.stream - .map(frame) - .listen((data) => _request.send(data)); - - _request.onReadyStateChange.listen((data) { - final contentType = _request.getResponseHeader('Content-Type'); - if (contentType == null) { - return; - } - - if (_request.readyState == HttpRequest.HEADERS_RECEIVED) { - if (contentType.startsWith('application/grpc')) { - if (_request.response == null) { - return; - } - - // Force a metadata message with headers - final headers = GrpcMetadata(_request.responseHeaders); - _incomingMessages.add(headers); - } - } - - if (_request.readyState == HttpRequest.DONE) { - _incomingProcessor.close(); - _outgoingMessages.close(); - } - }); - - _request.onProgress.listen((_) { - // use response over responseText as most browsers don't support - // using responseText during an onProgress event. - final responseString = _request.response as String; - final bytes = Uint8List.fromList( - responseString.substring(_requestBytesRead).codeUnits) - .buffer; - _requestBytesRead = responseString.length; - _incomingProcessor.add(bytes); - }); - } - - @override - Future terminate() async { - await _incomingProcessor.close(); - await _outgoingMessages.close(); - _request.abort(); - } -} - -class XhrTransport extends Transport { - final String host; - final int port; - - HttpRequest _request; - - XhrTransport(this.host, this.port); - - @override - Future connect() async {} - - @override - Future finish() async {} - - @visibleForTesting - void initializeRequest(HttpRequest request, Map metadata) { - for (final header in metadata.keys) { - request.setRequestHeader(header, metadata[header]); - } - request.setRequestHeader('Content-Type', 'application/grpc-web+proto'); - request.setRequestHeader('X-User-Agent', 'grpc-web-dart/0.1'); - request.setRequestHeader('X-Grpc-Web', '1'); - // Overriding the mimetype allows us to stream and parse the data - request.overrideMimeType('text/plain; charset=x-user-defined'); - request.responseType = 'text'; - } - - @override - GrpcTransportStream makeRequest( - String path, Duration timeout, Map metadata) { - _request = HttpRequest(); - _request.open('POST', '${host}:${port}${path}'); - - initializeRequest(_request, metadata); - - return XhrTransportStream(_request); - } - - @override - Future terminate() async {} -} - diff --git a/lib/src/client/web_channel.dart b/lib/src/client/web_channel.dart deleted file mode 100644 index 1eedbd4..0000000 --- a/lib/src/client/web_channel.dart +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2019, the gRPC project authors. Please see the AUTHORS file -// for details. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:grpc/src/client/options.dart'; -import 'package:grpc/src/client/transport/transport.dart'; -import 'package:grpc/src/client/transport/xhr_transport.dart'; -import 'package:meta/meta.dart'; - -import 'channel.dart'; - -@visibleForTesting -Future connectXhrTransport( - String host, int port, ChannelOptions _) async { - return XhrTransport(host, port)..connect(); -} - -class GrpcWebClientChannel extends ClientChannel { - GrpcWebClientChannel.xhr(String host, - {int port = 443}) : super(host, connectXhrTransport, port: port); -} \ No newline at end of file diff --git a/lib/src/server/handler.dart b/lib/src/server/handler.dart index e7ae05c..bf38734 100644 --- a/lib/src/server/handler.dart +++ b/lib/src/server/handler.dart @@ -18,7 +18,6 @@ import 'dart:convert'; import 'package:http2/transport.dart'; -import '../shared/message.dart'; import '../shared/status.dart'; import '../shared/streams.dart'; import '../shared/timeout.dart'; @@ -229,7 +228,7 @@ class ServerHandler extends ServiceCall { if (!_headersSent) { sendHeaders(); } - _stream.sendData(frame(bytes)); + _stream.sendData(GrpcHttpEncoder.frame(bytes)); } catch (error) { final grpcError = new GrpcError.internal('Error sending response: $error'); diff --git a/lib/src/shared/message.dart b/lib/src/shared/message.dart deleted file mode 100644 index d2ff06b..0000000 --- a/lib/src/shared/message.dart +++ /dev/null @@ -1,63 +0,0 @@ -import 'dart:async'; -import 'dart:typed_data'; - -abstract class GrpcMessage {} - -class GrpcMetadata extends GrpcMessage { - final Map metadata; - GrpcMetadata(this.metadata); - - @override - String toString() => 'gRPC Metadata ($metadata)'; -} - -class GrpcData extends GrpcMessage { - final List data; - final bool isCompressed; - GrpcData(this.data, {this.isCompressed}); - - @override - String toString() => 'gRPC Data (${data.length} bytes)'; -} - -class GrpcMessageSink extends Sink { - GrpcMessage message; - - @override - void add(GrpcMessage data) { - if (message != null) { - throw 'Too many messages received!'; - } - message = data; - } - - @override - void close() { - if (message == null) { - throw 'No messages received!'; - } - } -} - -List frame(List payload) { - final payloadLength = payload.length; - final bytes = new Uint8List(payloadLength + 5); - final header = bytes.buffer.asByteData(0, 5); - header.setUint8(0, 0); // TODO(dart-lang/grpc-dart#6): Handle compression - header.setUint32(1, payloadLength); - bytes.setRange(5, bytes.length, payload); - return bytes; -} - -StreamTransformer grpcDecompressor() => - new StreamTransformer.fromHandlers( - handleData: (GrpcMessage value, EventSink sink) { - if (value is GrpcData) { - if (value.isCompressed) { - // TODO(dart-lang/grpc-dart#6): Actually handle decompression. - sink.add(new GrpcData(value.data, isCompressed: false)); - return; - } - } - sink.add(value); - }); diff --git a/lib/src/shared/streams.dart b/lib/src/shared/streams.dart index 2e78245..7e3148b 100644 --- a/lib/src/shared/streams.dart +++ b/lib/src/shared/streams.dart @@ -20,9 +20,40 @@ import 'dart:typed_data'; import 'package:http2/transport.dart'; -import 'message.dart'; import 'status.dart'; +abstract class GrpcMessage {} + +class GrpcMetadata extends GrpcMessage { + final Map metadata; + GrpcMetadata(this.metadata); + + @override + String toString() => 'gRPC Metadata ($metadata)'; +} + +class GrpcData extends GrpcMessage { + final List data; + final bool isCompressed; + GrpcData(this.data, {this.isCompressed}); + + @override + String toString() => 'gRPC Data (${data.length} bytes)'; +} + +StreamTransformer grpcDecompressor() => + new StreamTransformer.fromHandlers( + handleData: (GrpcMessage value, EventSink sink) { + if (value is GrpcData) { + if (value.isCompressed) { + // TODO(dart-lang/grpc-dart#6): Actually handle decompression. + sink.add(new GrpcData(value.data, isCompressed: false)); + return; + } + } + sink.add(value); + }); + class GrpcHttpEncoder extends Converter { @override StreamMessage convert(GrpcMessage input) { @@ -37,12 +68,22 @@ class GrpcHttpEncoder extends Converter { } throw new GrpcError.internal('Unexpected message type'); } + + static List frame(List payload) { + final payloadLength = payload.length; + final bytes = new Uint8List(payloadLength + 5); + final header = bytes.buffer.asByteData(0, 5); + header.setUint8(0, 0); // TODO(dart-lang/grpc-dart#6): Handle compression + header.setUint32(1, payloadLength); + bytes.setRange(5, bytes.length, payload); + return bytes; + } } class GrpcHttpDecoder extends Converter { @override GrpcMessage convert(StreamMessage input) { - final sink = new GrpcMessageSink(); + final sink = new _GrpcMessageSink(); startChunkedConversion(sink) ..add(input) ..close(); @@ -142,3 +183,22 @@ class _GrpcMessageConversionSink extends ChunkedConversionSink { _out.close(); } } + +class _GrpcMessageSink extends Sink { + GrpcMessage message; + + @override + void add(GrpcMessage data) { + if (message != null) { + throw 'Too many messages received!'; + } + message = data; + } + + @override + void close() { + if (message == null) { + throw 'No messages received!'; + } + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 3faa2ca..e9703ca 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: grpc description: Dart implementation of gRPC, a high performance, open-source universal RPC framework. -version: 1.1.0 +version: 1.0.1 author: Dart Team homepage: https://github.com/dart-lang/grpc-dart @@ -8,14 +8,12 @@ environment: sdk: '>=2.0.0 <3.0.0' dependencies: + async: '>=1.13.3 <3.0.0' googleapis_auth: ^0.2.5+3 meta: ^1.0.5 http: '>=0.11.3+17 <0.13.0' http2: '>=0.1.7 <2.0.0' dev_dependencies: - build_runner: ^0.10.0 - build_test: ^0.10.3 - build_web_compilers: ^0.4.3 mockito: ^4.0.0 test: ^1.5.0 diff --git a/test/client_tests/client_test.dart b/test/client_test.dart similarity index 93% rename from test/client_tests/client_test.dart rename to test/client_test.dart index 9689961..2fe33bd 100644 --- a/test/client_tests/client_test.dart +++ b/test/client_test.dart @@ -16,11 +16,11 @@ import 'dart:async'; import 'package:grpc/grpc.dart'; -import 'package:grpc/src/shared/message.dart'; +import 'package:http2/transport.dart'; import 'package:test/test.dart'; -import '../src/client_utils.dart'; -import '../src/utils.dart'; +import 'src/client_utils.dart'; +import 'src/utils.dart'; void main() { const dummyValue = 0; @@ -39,8 +39,8 @@ void main() { const requestValue = 17; const responseValue = 19; - void handleRequest(List message) { - final data = validateClientDataMessage(message); + void handleRequest(StreamMessage message) { + final data = validateDataMessage(message); expect(mockDecode(data.data), requestValue); harness @@ -63,8 +63,8 @@ void main() { var index = 0; - void handleRequest(List message) { - final data = validateClientDataMessage(message); + void handleRequest(StreamMessage message) { + final data = validateDataMessage(message); expect(mockDecode(data.data), requests[index++]); } @@ -89,8 +89,8 @@ void main() { const request = 4; const responses = const [3, 17, 9]; - void handleRequest(List message) { - final data = validateClientDataMessage(message); + void handleRequest(StreamMessage message) { + final data = validateDataMessage(message); expect(mockDecode(data.data), request); harness.sendResponseHeader(); @@ -112,8 +112,8 @@ void main() { var index = 0; - void handleRequest(List message) { - final data = validateClientDataMessage(message); + void handleRequest(StreamMessage message) { + final data = validateDataMessage(message); expect(mockDecode(data.data), requests[index]); if (index == 0) { @@ -244,11 +244,10 @@ void main() { const customStatusMessage = 'Custom message'; void handleRequest(_) { - final headers = { - 'grpc-status': '$customStatusCode', - 'grpc-message': customStatusMessage - }; - harness.toClient.add(new GrpcMetadata(headers)); + harness.toClient.add(new HeadersStreamMessage([ + new Header.ascii('grpc-status', '$customStatusCode'), + new Header.ascii('grpc-message', customStatusMessage) + ], endStream: true)); harness.toClient.close(); } @@ -313,8 +312,8 @@ void main() { ); }); - Future makeUnaryCall() async { - void handleRequest(List message) { + Future makeUnaryCall() async { + void handleRequest(StreamMessage message) { harness ..sendResponseHeader() ..sendResponseValue(1) diff --git a/test/client_tests/client_http2_transport_test.dart b/test/client_tests/client_http2_transport_test.dart deleted file mode 100644 index fa7d745..0000000 --- a/test/client_tests/client_http2_transport_test.dart +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright (c) 2017, the gRPC project authors. Please see the AUTHORS file -// for details. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -@TestOn('vm') - -import 'dart:async'; - -import 'package:grpc/grpc.dart'; -import 'package:grpc/src/client/transport/http2_credentials.dart'; -import 'package:grpc/src/client/transport/http2_transport.dart'; - -import 'package:http2/transport.dart'; -import 'package:mockito/mockito.dart'; -import 'package:test/test.dart'; - -import '../src/utils.dart'; - -class MockTransport extends Mock implements ClientTransportConnection {} - -class MockStream extends Mock implements ClientTransportStream {} - -typedef void VerifyHeadersCallback(List
headers); - -class MockHttp2Transport extends Http2Transport { - MockStream mockClientStream; - VerifyHeadersCallback onVerifyHeaders; - - StreamController fromClient; - StreamController toClient; - - MockHttp2Transport(String host, int port, ChannelOptions options) - : super(host, port, options); - - @override - Future connect() async { - transportConnection = MockTransport(); - - when(transportConnection.makeRequest(any)).thenAnswer((call) { - if (onVerifyHeaders != null) { - onVerifyHeaders(call.positionalArguments[0]); - } - mockClientStream = new MockStream(); - fromClient = StreamController(); - toClient = StreamController(); - when(mockClientStream.outgoingMessages) - .thenAnswer((_) => fromClient.sink); - when(mockClientStream.incomingMessages) - .thenAnswer((_) => toClient.stream); - - return mockClientStream; - }); - } - - @override - Future terminate() async { - fromClient.close(); - toClient.close(); - } -} - -void main() { - final MockHttp2Transport transport = new MockHttp2Transport( - 'host', - 9999, - ChannelOptions( - credentials: new Http2ChannelCredentials.secure(authority: 'test'))); - - setUp(() { - transport.connect(); - }); - - tearDown(() { - transport.terminate(); - }); - - test('Make request passes proper headers', () async { - final metadata = { - "parameter_1": "value_1", - "parameter_2": "value_2" - }; - - transport.onVerifyHeaders = (headers) { - final headerMap = headersToMap(headers); - validateRequestHeaders(headerMap, - path: 'test_path', - customHeaders: metadata, - timeout: toTimeoutString(Duration(seconds: 10))); - }; - - transport.makeRequest('test_path', Duration(seconds: 10), metadata); - }); - - test('Sent data converted to StreamMessages properly', () async { - final metadata = { - "parameter_1": "value_1", - "parameter_2": "value_2" - }; - - final stream = - transport.makeRequest('test_path', Duration(seconds: 10), metadata); - - transport.fromClient.stream.listen((message) { - final dataMessage = validateDataMessage(message); - expect(dataMessage.data.length, 10); - }); - - stream.outgoingMessages.add(List.filled(10, 0)); - }); - - test('StreamMessages deserializes headers properly', () async { - final metadata = { - "parameter_1": "value_1", - "parameter_2": "value_2" - }; - - final stream = - transport.makeRequest('test_path', Duration(seconds: 10), metadata); - - stream.incomingMessages.listen((message) { - expect(message, TypeMatcher()); - if (message is GrpcMetadata) { - message.metadata.forEach((key, value) { - expect(value, metadata[key]); - }); - } - }); - - final httpMessage = GrpcHttpEncoder().convert(GrpcMetadata(metadata)); - transport.toClient.add(httpMessage); - }); - - test('StreamMessages deserializes data properly', () async { - final metadata = { - "parameter_1": "value_1", - "parameter_2": "value_2" - }; - - final stream = - transport.makeRequest('test_path', Duration(seconds: 10), metadata); - final data = List.filled(10, 0); - stream.incomingMessages.listen((message) { - expect(message, TypeMatcher()); - if (message is GrpcData) { - expect(message.data, equals(data)); - } - }); - - final httpMessage = GrpcHttpEncoder().convert(GrpcData(data)); - transport.toClient.add(httpMessage); - }); -} diff --git a/test/client_tests/client_xhr_transport_test.dart b/test/client_tests/client_xhr_transport_test.dart deleted file mode 100644 index b3b3641..0000000 --- a/test/client_tests/client_xhr_transport_test.dart +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright (c) 2017, the gRPC project authors. Please see the AUTHORS file -// for details. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -@TestOn('browser') - -import 'dart:async'; - -import 'dart:html'; - -import 'package:grpc/grpc.dart'; -import 'package:grpc/src/client/transport/xhr_transport.dart'; -import 'package:grpc/src/shared/message.dart'; -import 'package:mockito/mockito.dart'; - -import 'package:test/test.dart'; - -class MockHttpRequest extends Mock implements HttpRequest {} - -class MockXhrTransport extends XhrTransport { - StreamController readyStateChangeStream = StreamController(); - StreamController progressStream = - StreamController(); - - MockHttpRequest mockRequest; - - MockXhrTransport(this.mockRequest) : super('test', 8080) {} - - @override - GrpcTransportStream makeRequest( - String path, Duration timeout, Map metadata) { - when(mockRequest.onReadyStateChange) - .thenAnswer((_) => readyStateChangeStream.stream); - when(mockRequest.onProgress).thenAnswer((_) => progressStream.stream); - - initializeRequest(mockRequest, metadata); - - return XhrTransportStream(mockRequest); - } - - @override - Future terminate() async { - readyStateChangeStream.close(); - progressStream.close(); - } -} - -void main() { - test('Make request sends correct headers', () async { - final metadata = { - 'parameter_1': 'value_1', - 'parameter_2': 'value_2' - }; - - final mockRequest = MockHttpRequest(); - final transport = MockXhrTransport(mockRequest); - - transport.makeRequest('path', Duration(seconds: 10), metadata); - - verify(mockRequest.setRequestHeader( - 'Content-Type', 'application/grpc-web+proto')); - verify(mockRequest.setRequestHeader('X-User-Agent', 'grpc-web-dart/0.1')); - verify(mockRequest.setRequestHeader('X-Grpc-Web', '1')); - verify(mockRequest.overrideMimeType('text/plain; charset=x-user-defined')); - verify(mockRequest.responseType = 'text'); - }); - - test('Sent data converted to stream properly', () async { - final metadata = { - 'parameter_1': 'value_1', - 'parameter_2': 'value_2' - }; - - final mockRequest = MockHttpRequest(); - final transport = MockXhrTransport(mockRequest); - - final stream = - transport.makeRequest('path', Duration(seconds: 10), metadata); - - final data = List.filled(10, 0); - stream.outgoingMessages.add(data); - await stream.terminate(); - - final expectedData = frame(data); - expect(verify(mockRequest.send(captureAny)).captured.single, expectedData); - }); - - test('Stream handles headers properly', () async { - final metadata = { - 'parameter_1': 'value_1', - 'parameter_2': 'value_2' - }; - - final mockRequest = MockHttpRequest(); - final transport = MockXhrTransport(mockRequest); - - final stream = - transport.makeRequest('test_path', Duration(seconds: 10), metadata); - - stream.incomingMessages.listen((message) { - expect(message, TypeMatcher()); - if (message is GrpcMetadata) { - message.metadata.forEach((key, value) { - expect(value, metadata[key]); - }); - } - }); - }); - - test('Stream deserializes data properly', () async { - final metadata = { - 'parameter_1': 'value_1', - 'parameter_2': 'value_2' - }; - - final mockRequest = MockHttpRequest(); - final transport = MockXhrTransport(mockRequest); - - final stream = - transport.makeRequest('test_path', Duration(seconds: 10), metadata); - final data = List.filled(10, 224); - final encoded = frame(data); - final encodedString = String.fromCharCodes(encoded); - - bool dataVerified = false; - stream.incomingMessages.listen((message) { - if (message is GrpcData) { - dataVerified = true; - expect(message.data, equals(data)); - } - }); - - when(mockRequest.getResponseHeader('Content-Type')) - .thenReturn('application/grpc+proto'); - when(mockRequest.responseHeaders).thenReturn(metadata); - when(mockRequest.readyState).thenReturn(HttpRequest.HEADERS_RECEIVED); - when(mockRequest.response).thenReturn(encodedString); - transport.readyStateChangeStream.add(null); - transport.progressStream.add(null); - - // Wait for all streams to process - await Future.sync(() {}); - - await stream.terminate(); - expect(dataVerified, true); - }); - - test('Stream recieves multiple messages', () async { - final metadata = { - 'parameter_1': 'value_1', - 'parameter_2': 'value_2' - }; - - final mockRequest = MockHttpRequest(); - final transport = MockXhrTransport(mockRequest); - - final stream = - transport.makeRequest('test_path', Duration(seconds: 10), metadata); - - final data = >[ - List.filled(10, 224), - List.filled(5, 124) - ]; - final encoded = data.map((d) => frame(d)); - final encodedStrings = encoded.map((e) => String.fromCharCodes(e)).toList(); - // to start - expected response is the first message - var expectedResponse = encodedStrings[0]; - - final expectedMessages = [ - GrpcMetadata(metadata), - GrpcData(data[0]), - GrpcData(data[1]) - ]; - stream.incomingMessages.listen((message) { - final expectedMessage = expectedMessages.removeAt(0); - expect(message.runtimeType, expectedMessage.runtimeType); - if (message is GrpcMetadata) { - expect(message.metadata, (expectedMessage as GrpcMetadata).metadata); - } else if (message is GrpcData) { - expect(message.data, (expectedMessage as GrpcData).data); - } - }); - - when(mockRequest.getResponseHeader('Content-Type')) - .thenReturn('application/grpc+proto'); - when(mockRequest.responseHeaders).thenReturn(metadata); - when(mockRequest.readyState).thenReturn(HttpRequest.HEADERS_RECEIVED); - when(mockRequest.response).thenAnswer((_) => expectedResponse); - transport.readyStateChangeStream.add(null); - transport.progressStream.add(null); - // Wait for all streams to process - await Future.sync(() {}); - - // After the first call, expected response should now be both responses together - expectedResponse = encodedStrings[0] + encodedStrings[1]; - transport.progressStream.add(null); - - // Wait for all streams to process - await Future.sync(() {}); - - await stream.terminate(); - expect(expectedMessages.isEmpty, isTrue); - }); -} diff --git a/test/options_test.dart b/test/options_test.dart index 94a36d9..0b90958 100644 --- a/test/options_test.dart +++ b/test/options_test.dart @@ -12,7 +12,6 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -@TestOn('vm') import 'dart:io'; @@ -28,14 +27,14 @@ void main() { await new File('test/data/certstore.p12').readAsBytes(); final missingPassword = - new Http2ChannelCredentials.secure(certificates: certificates); + new ChannelCredentials.secure(certificates: certificates); expect(() => missingPassword.securityContext, throwsA(isTlsException)); - final wrongPassword = new Http2ChannelCredentials.secure( + final wrongPassword = new ChannelCredentials.secure( certificates: certificates, password: 'wrong'); expect(() => wrongPassword.securityContext, throwsA(isTlsException)); - final correctPassword = new Http2ChannelCredentials.secure( + final correctPassword = new ChannelCredentials.secure( certificates: certificates, password: 'correct'); expect(correctPassword.securityContext, isNotNull); }); diff --git a/test/server_test.dart b/test/server_test.dart index 0993c77..687769c 100644 --- a/test/server_test.dart +++ b/test/server_test.dart @@ -12,7 +12,6 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -@TestOn('vm') import 'dart:async'; diff --git a/test/src/client_utils.dart b/test/src/client_utils.dart index e1b18b1..d79234e 100644 --- a/test/src/client_utils.dart +++ b/test/src/client_utils.dart @@ -15,7 +15,8 @@ import 'dart:async'; -import 'package:grpc/src/shared/message.dart'; +import 'package:grpc/src/shared/streams.dart'; +import 'package:http2/transport.dart'; import 'package:test/test.dart'; import 'package:mockito/mockito.dart'; @@ -23,41 +24,29 @@ import 'package:grpc/grpc.dart'; import 'utils.dart'; -typedef void ClientTestMessageHandler(List message); +class MockTransport extends Mock implements ClientTransportConnection {} -GrpcData validateClientDataMessage(List message) { - final decoded = new GrpcData(message); - - expect(decoded, new TypeMatcher()); - return decoded; -} - -class MockTransport extends Mock implements Transport {} - -class MockStream extends Mock implements GrpcTransportStream {} +class MockStream extends Mock implements ClientTransportStream {} class FakeConnection extends ClientConnection { + final ClientTransportConnection transport; + var connectionError; - FakeConnection._(String host, Transport transport, ChannelOptions options, - ConnectTransport connectTransport) - : super(host, 443, options, connectTransport); + FakeConnection(String host, this.transport, ChannelOptions options) + : super(host, 443, options); - factory FakeConnection( - String host, Transport transport, ChannelOptions options) { - FakeConnection f; - f = FakeConnection._(host, transport, options, (_, _1, _2) async { - if (f.connectionError != null) throw f.connectionError; - return transport; - }); - return f; + @override + Future connectTransport() async { + if (connectionError != null) throw connectionError; + return transport; } } Duration testBackoff(Duration lastBackoff) => const Duration(milliseconds: 1); class FakeChannelOptions implements ChannelOptions { - ChannelCredentials credentials = const Http2ChannelCredentials.secure(); + ChannelCredentials credentials = const ChannelCredentials.secure(); Duration idleTimeout = const Duration(seconds: 1); BackoffStrategy backoffStrategy = testBackoff; } @@ -73,6 +62,8 @@ class FakeChannel extends ClientChannel { Future getConnection() async => connection; } +typedef ServerMessageHandler = void Function(StreamMessage message); + class TestClient extends Client { static final _$unary = new ClientMethod('/Test/Unary', mockEncode, mockDecode); @@ -119,8 +110,8 @@ class ClientHarness { FakeChannelOptions channelOptions; MockStream stream; - StreamController> fromClient; - StreamController toClient; + StreamController fromClient; + StreamController toClient; TestClient client; @@ -132,7 +123,8 @@ class ClientHarness { stream = new MockStream(); fromClient = new StreamController(); toClient = new StreamController(); - when(transport.makeRequest(any, any, any)).thenReturn(stream); + when(transport.makeRequest(any, endStream: anyNamed('endStream'))) + .thenReturn(stream); when(transport.onActiveStateChanged = captureAny).thenReturn(null); when(stream.outgoingMessages).thenReturn(fromClient.sink); when(stream.incomingMessages).thenAnswer((_) => toClient.stream); @@ -144,17 +136,18 @@ class ClientHarness { toClient.close(); } - void sendResponseHeader({Map headers = const {}}) { - toClient.add(new GrpcMetadata(headers)); + void sendResponseHeader({List
headers = const []}) { + toClient.add(new HeadersStreamMessage(headers)); } void sendResponseValue(int value) { - toClient.add(new GrpcData(mockEncode(value))); + toClient + .add(new DataStreamMessage(GrpcHttpEncoder.frame(mockEncode(value)))); } void sendResponseTrailer( - {Map headers = const {}, bool closeStream = true}) { - toClient.add(new GrpcMetadata(headers)); + {List
headers = const [], bool closeStream = true}) { + toClient.add(new HeadersStreamMessage(headers, endStream: true)); if (closeStream) toClient.close(); } @@ -171,11 +164,11 @@ class ClientHarness { String expectedPath, Duration expectedTimeout, Map expectedCustomHeaders, - List serverHandlers = const [], + List serverHandlers = const [], Function doneHandler, bool expectDone = true}) async { int serverHandlerIndex = 0; - void handleServerMessage(List message) { + void handleServerMessage(StreamMessage message) { serverHandlers[serverHandlerIndex++](message); } @@ -189,17 +182,12 @@ class ClientHarness { expect(result, expectedResult); } - final capturedParameters = - verify(transport.makeRequest(captureAny, captureAny, captureAny)) - .captured; - if (expectedPath != null) { - expect(capturedParameters[0], expectedPath); - } - expect(capturedParameters[1], expectedTimeout); - final Map headers = capturedParameters[2]; - headers?.forEach((key, value) { - expect(expectedCustomHeaders[key], value); - }); + final List
capturedHeaders = + verify(transport.makeRequest(captureAny)).captured.single; + validateRequestHeaders(capturedHeaders, + path: expectedPath, + timeout: toTimeoutString(expectedTimeout), + customHeaders: expectedCustomHeaders); await clientSubscription.cancel(); } @@ -219,7 +207,7 @@ class ClientHarness { String expectedPath, Duration expectedTimeout, Map expectedCustomHeaders, - List serverHandlers = const [], + List serverHandlers = const [], bool expectDone = true}) async { return runTest( clientCall: expectThrows(clientCall, expectedException), diff --git a/test/src/server_utils.dart b/test/src/server_utils.dart index 673f0b7..f95b4f7 100644 --- a/test/src/server_utils.dart +++ b/test/src/server_utils.dart @@ -15,13 +15,11 @@ import 'dart:async'; -import 'package:grpc/src/shared/message.dart'; import 'package:grpc/src/shared/streams.dart'; import 'package:http2/transport.dart'; import 'package:test/test.dart'; import 'package:grpc/grpc.dart'; -import 'package:grpc/src/client/transport/http2_transport.dart'; import 'utils.dart'; @@ -172,14 +170,14 @@ class ServerHarness { {String authority = 'test', Map metadata, Duration timeout}) { - final headers = Http2Transport.createCallHeaders( + final headers = ClientConnection.createCallHeaders( true, authority, path, timeout, metadata); toServer.add(new HeadersStreamMessage(headers)); } void sendData(int value) { toServer - .add(new DataStreamMessage(frame(mockEncode(value)))); + .add(new DataStreamMessage(GrpcHttpEncoder.frame(mockEncode(value)))); } void runTest(String path, List requests, List expectedResponses) { diff --git a/test/src/utils.dart b/test/src/utils.dart index b0826fb..1c249f4 100644 --- a/test/src/utils.dart +++ b/test/src/utils.dart @@ -16,7 +16,6 @@ import 'dart:convert'; import 'package:grpc/src/shared/streams.dart'; -import 'package:grpc/src/shared/message.dart'; import 'package:http2/transport.dart'; import 'package:test/test.dart'; @@ -30,25 +29,26 @@ Map headersToMap(List
headers) => new Map.fromIterable(headers, key: (h) => ascii.decode(h.name), value: (h) => ascii.decode(h.value)); -void validateRequestHeaders(Map headers, +void validateRequestHeaders(List
headers, {String path, String authority = 'test', String timeout, Map customHeaders}) { - expect(headers[':method'], 'POST'); - expect(headers[':scheme'], 'https'); + final headerMap = headersToMap(headers); + expect(headerMap[':method'], 'POST'); + expect(headerMap[':scheme'], 'https'); if (path != null) { - expect(headers[':path'], path); + expect(headerMap[':path'], path); } - expect(headers[':authority'], authority); - expect(headers['grpc-timeout'], timeout); - expect(headers['content-type'], 'application/grpc'); - expect(headers['te'], 'trailers'); - expect(headers['grpc-accept-encoding'], 'identity'); - expect(headers['user-agent'], startsWith('dart-grpc/')); + expect(headerMap[':authority'], authority); + expect(headerMap['grpc-timeout'], timeout); + expect(headerMap['content-type'], 'application/grpc'); + expect(headerMap['te'], 'trailers'); + expect(headerMap['grpc-accept-encoding'], 'identity'); + expect(headerMap['user-agent'], startsWith('dart-grpc/')); customHeaders?.forEach((key, value) { - expect(headers[key], value); + expect(headerMap[key], value); }); } diff --git a/test/timeout_test.dart b/test/timeout_test.dart index 2d97ee8..73e175e 100644 --- a/test/timeout_test.dart +++ b/test/timeout_test.dart @@ -16,10 +16,12 @@ import 'dart:async'; import 'package:grpc/grpc.dart'; +import 'package:http2/transport.dart'; import 'package:test/test.dart'; import 'src/client_utils.dart'; import 'src/server_utils.dart'; +import 'src/utils.dart'; void main() { const dummyValue = 0; @@ -73,8 +75,8 @@ void main() { }); test('Calls time out if deadline is exceeded', () async { - void handleRequest(List message) { - validateClientDataMessage(message); + void handleRequest(StreamMessage message) { + validateDataMessage(message); final Future delay = new Future.delayed(new Duration(milliseconds: 2)); expect(delay, completes); delay.then((_) { @@ -140,5 +142,5 @@ void main() { timeout: new Duration(microseconds: 1)); await harness.fromServer.done; }); - }, testOn: 'vm'); + }); }