mirror of https://github.com/grpc/grpc-dart.git
Squashed commit of the following:
commit471a8b377b
Author: Tsavo Knott <tsavo@pieces.app> Date: Fri Jan 3 13:02:16 2025 -0500 Clean Up CI commit16328209c2
Author: Tsavo Knott <tsavo@pieces.app> Date: Fri Jan 3 13:00:20 2025 -0500 True Upstream Master commit1dddfe0c96
Merge:774bf81
c9d6286
Author: Tsavo Knott <102485237+tsavo-at-pieces@users.noreply.github.com> Date: Fri Jan 3 12:32:24 2025 -0500 Merge pull request #2 from open-runtime/update-from-upstream Update from Upstream Master commitc9d628640c
Merge:774bf81
9a9c017
Author: Tsavo Knott <tsavo@pieces.app> Date: Fri Jan 3 12:31:33 2025 -0500 Merge branch 'upstream-master' into update-from-upstream commit774bf81c73
Merge:4a043fa
00eabed
Author: Tsavo Knott <102485237+tsavo-at-pieces@users.noreply.github.com> Date: Fri Jan 3 12:13:44 2025 -0500 Merge pull request #1 from open-runtime/aot_monorepo_compat Merging AOT Monorepo Compat into our Main Branch commit9a9c01752c
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue Dec 17 09:58:22 2024 +0100 Bump vm_service from 14.3.1 to 15.0.0 (#751) Bumps [vm_service](https://github.com/dart-lang/sdk/tree/main/pkg) from 14.3.1 to 15.0.0. - [Changelog](https://github.com/dart-lang/sdk/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/sdk/commits/HEAD/pkg) --- updated-dependencies: - dependency-name: vm_service dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Moritz <mosum@google.com> commit3e94fecd14
Author: Moritz <mosum@google.com> Date: Tue Dec 17 09:53:02 2024 +0100 Update health.yaml (#753) * Update health.yaml * Upgrade example * Fixes * try different syntax * without endings * test new wf * new version * Works, use main now * Add changelog commit6676c20df2
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon Dec 16 13:37:35 2024 +0000 Bump dart-lang/setup-dart from 1.6.5 to 1.7.0 (#746) commitf61b9a3b37
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon Nov 4 10:45:05 2024 +0000 Bump actions/checkout from 4.2.0 to 4.2.2 (#744) commitc0630106a9
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue Oct 1 08:51:16 2024 +0000 Bump actions/checkout from 4.1.7 to 4.2.0 (#741) commit04ba68eb91
Author: Moritz <mosum@google.com> Date: Tue Oct 1 04:46:38 2024 -0400 Rev package:lints (#740) * Rev package:lints * Add changelog * Run CI on 3.5.0 * Test with 3.2.0 * Update .github/workflows/dart.yml Co-authored-by: Kevin Moore <kevmoo@users.noreply.github.com> * Update .github/workflows/dart.yml Co-authored-by: Kevin Moore <kevmoo@users.noreply.github.com> --------- Co-authored-by: Kevin Moore <kevmoo@users.noreply.github.com> commitf8bbdce629
Author: Kevin Moore <kevmoo@users.noreply.github.com> Date: Tue Sep 24 12:07:42 2024 -0700 ignore unreachable_switch_default in weird switch case (#737) commit071ebc5f31
Author: steffenhaak <haak@aucentiq.com> Date: Fri Sep 6 17:13:11 2024 +0200 fix: keep alive timeout finishes transport instead of connection shutdown (#722) * fix: keep alive timeout finishes transport instead of shutting down channel * Update keepalive_test.dart * Update CHANGELOG.md --------- Co-authored-by: Moritz <mosum@google.com> commit81776333d9
Author: Moritz <mosum@google.com> Date: Fri Sep 6 15:09:54 2024 +0200 Small fixes (#732) * Small fixes * Revert changes on file * Add changelog * Small fixes in keepalive test * Add delay * Fix symbol visibilty * Add try catch for debugging * Fail * fail * Use for loop commit38ca626e0a
Author: Lasse R.H. Nielsen <lrn@google.com> Date: Mon Sep 2 16:58:43 2024 +0200 Use `Map.of` instead of `Map.from` in grpc client. (#724) * Use `Map.of` instead of `Map.from` in grpc client. `Map.of` creates a new map with the same keys, values and *type* as the original map, when used without type arguments or context type, where `Map.from` creates a `Map<dynamic, dynamic>`. (This code failed on an attempt to make `Map.unmodifiable` be more strictly typed, like `Map.of` instead of `Map.from`, showing that an intermediate map had type `Map<dynamic, dynamic>` unnecessarily). Same for using `List.of` instead of `List.from`. The new code should be (microscopically) more efficient and type safe, and is forwards-compatible with a stronger type on `Map.unmodifiable`. (The code can be optimized more. For example `List.of(list1)..addAll(list2)` can be just `list1 + list2` or `[...list1, ...list2]`, both of which may know the total number of elements when doing the initial list allocation. This is a minimal change to allow the type changes for `.unmodifiable` to get past this very initial blocker in internal tests.) * Add changelog and minor version increment. And my save removes trailing spaces. commit4f6fe9b111
Author: c-lucera-pvotal <91328643+c-lucera-pvotal@users.noreply.github.com> Date: Wed Aug 28 08:18:15 2024 +0200 fix: fix headers not completing when call is terminated (#728) Fixes #727 commitc18e185bb0
Author: Kevin Moore <kevmoo@users.noreply.github.com> Date: Wed Jul 24 14:24:57 2024 -0700 Fix status badge (#726) commitb999b64502
Author: Galen Warren <galen@cvillewarrens.com> Date: Wed Jul 17 08:11:29 2024 -0400 feat: fix hang that occurs when hot restarting (#718) commitbf8bbde34c
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon Jul 1 11:56:47 2024 +0000 Bump dart-lang/setup-dart from 1.6.4 to 1.6.5 (#720) commit4aa4c8cb8d
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon Jul 1 11:52:08 2024 +0000 Bump actions/checkout from 4.1.6 to 4.1.7 (#719) commitdee1b2b43b
Author: Kevin Moore <kevmoo@users.noreply.github.com> Date: Wed May 29 17:23:53 2024 -0700 Update pubspec.yaml commit52023d404e
Author: Kevin Moore <kevmoo@google.com> Date: Tue May 28 14:47:30 2024 -0700 code fixes commitebb7368fa4
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed May 22 06:56:00 2024 +0000 Bump lints from 3.0.0 to 4.0.0 Bumps [lints](https://github.com/dart-lang/lints) from 3.0.0 to 4.0.0. - [Release notes](https://github.com/dart-lang/lints/releases) - [Changelog](https://github.com/dart-lang/lints/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/lints/compare/v3.0.0...v4.0.0) --- updated-dependencies: - dependency-name: lints dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> commit4e65d4b795
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue May 21 11:05:38 2024 +0000 --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> commit14954537f6
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue May 21 11:01:10 2024 +0000 Bump dart-lang/setup-dart from 1.6.2 to 1.6.4 Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.2 to 1.6.4. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](fedb1266e9...f0ead981b4
) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> commit6586b74969
Author: Sarah Zakarias <zarah@google.com> Date: Tue May 21 12:30:20 2024 +0200 Add `topics` to `pubspec.yaml` (#712) commit9f65399e28
Author: Moritz <mosum@google.com> Date: Fri May 17 14:53:33 2024 +0200 Move `codec.dart` to former place (#713) commit0d02e4386f
Author: Moritz <mosum@google.com> Date: Mon May 6 06:25:06 2024 -0700 Remove dependency on `package:archive` (#707) * Remove dependency on package:archive * Test compression on vm only * Add licenses * Fix analyze issues * Fix codec web * Fix licenses * Add changelog commit078fd23bca
Author: Moritz <mosum@google.com> Date: Thu Apr 25 04:45:40 2024 -0700 Remove generated `StatusCode` (#703) * Remove generated `StatusCode` * Rev version for breaking change * Upgrade min sdk version * Fix issues commitbdbe5f5003
Author: Ruben Garcia <RubenGarcia@users.noreply.github.com> Date: Mon Apr 22 16:09:18 2024 +0200 Fix issue 669 (#693) * Fix issue 669 * Update CHANGELOG.md * Update CHANGELOG.md * Fix dart format issue. Fix prefer single quote issue. * Update pubspec and changelog to avoid merge check publish / validate validate packages * Add test for GRPC Compression Flag * Fix dart analyze issues. * Fix latest dart analyze issue (uninizialized variable) commitbb8b6e5950
Author: Moritz <mosum@google.com> Date: Fri Apr 19 02:05:59 2024 -0700 Make protobuf generated imports absolute (#696) * Make protobuf generated imports absolute * Stop test for now commitb05fafe77c
Author: Moritz <mosum@google.com> Date: Mon Apr 15 04:43:26 2024 -0700 Add Health workflow (#699) * Add Health workflow * Remove license check commitaece2a4e3f
Author: Abdul Momin <98901875+Curious-x@users.noreply.github.com> Date: Mon Apr 15 12:53:00 2024 +0500 Typo Correction in README.md (#695) Corrected typo "RPs" to "RPCs". To avoid confusion.
This commit is contained in:
parent
00eabed7f6
commit
c5339134b3
|
@ -3,11 +3,10 @@ name: Dart
|
|||
on:
|
||||
# Run CI on pushes to the master branch, and on PRs against master.
|
||||
push:
|
||||
branches: [master]
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
schedule:
|
||||
- cron: "0 0 * * 0"
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
# Check code formatting and static analysis on a single OS (linux)
|
||||
|
@ -16,10 +15,10 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
sdk: [3.0.0, dev]
|
||||
sdk: [3.5, dev]
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
|
||||
- uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
- uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94
|
||||
with:
|
||||
sdk: ${{ matrix.sdk }}
|
||||
- name: Report version
|
||||
|
@ -60,7 +59,7 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
sdk: [3.0.0, dev]
|
||||
sdk: [3.5, dev]
|
||||
platform: [vm, chrome]
|
||||
exclude:
|
||||
# We only run Chrome tests on Linux. No need to run them
|
||||
|
@ -70,8 +69,8 @@ jobs:
|
|||
- os: macos-latest
|
||||
platform: chrome
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
|
||||
- uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
- uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94
|
||||
with:
|
||||
sdk: ${{ matrix.sdk }}
|
||||
- name: Report version
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
name: Health
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
types: [opened, synchronize, reopened, labeled, unlabeled]
|
||||
jobs:
|
||||
health:
|
||||
uses: dart-lang/ecosystem/.github/workflows/health.yaml@main
|
||||
with:
|
||||
checks: "changelog,do-not-submit,breaking,coverage,leaking"
|
||||
ignore_coverage: "example/**,interop/**"
|
||||
permissions:
|
||||
pull-requests: write
|
|
@ -0,0 +1,17 @@
|
|||
name: Comment on the pull request
|
||||
|
||||
on:
|
||||
# Trigger this workflow after the Health workflow completes. This workflow will have permissions to
|
||||
# do things like create comments on the PR, even if the original workflow couldn't.
|
||||
workflow_run:
|
||||
workflows:
|
||||
- Health
|
||||
- Publish
|
||||
types:
|
||||
- completed
|
||||
|
||||
jobs:
|
||||
upload:
|
||||
uses: dart-lang/ecosystem/.github/workflows/post_summaries.yaml@main
|
||||
permissions:
|
||||
pull-requests: write
|
|
@ -1,12 +0,0 @@
|
|||
name: Publish
|
||||
permissions:
|
||||
id-token: write
|
||||
pull-requests: write
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
push:
|
||||
tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ]
|
||||
jobs:
|
||||
publish:
|
||||
uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main
|
28
CHANGELOG.md
28
CHANGELOG.md
|
@ -1,3 +1,25 @@
|
|||
## 4.0.2-wip
|
||||
|
||||
* Internal optimization to client code.
|
||||
* Small fixes, such as ports in testing and enabling `timeline_test.dart`.
|
||||
* When the keep alive manager runs into a timeout, it will finish the transport instead of closing
|
||||
the connection, as defined in the gRPC spec.
|
||||
* Upgrade to `package:lints` version 5.0.0 and Dart SDK version 3.5.0.
|
||||
* Upgrade `example/grpc-web` code.
|
||||
* Update xhr transport to migrate off legacy JS/HTML apis.
|
||||
|
||||
## 4.0.1
|
||||
|
||||
* Fix header and trailing not completing if the call is terminated. Fixes [#727](https://github.com/grpc/grpc-dart/issues/727)
|
||||
|
||||
## 4.0.0
|
||||
|
||||
* Set compressed flag correctly for grpc-encoding = identity. Fixes [#669](https://github.com/grpc/grpc-dart/issues/669) (https://github.com/grpc/grpc-dart/pull/693)
|
||||
* Remove generated status codes.
|
||||
* Remove dependency on `package:archive`.
|
||||
* Move `codec.dart`.
|
||||
* Work around hang during Flutter hot restart by adding default case handler in _GrpcWebConversionSink.add.
|
||||
|
||||
## 3.2.4
|
||||
|
||||
* Forward internal `GrpcError` on when throwing while sending a request.
|
||||
|
@ -19,19 +41,19 @@
|
|||
|
||||
## 3.2.1
|
||||
|
||||
* `package:http` now supports more versions: `>=0.13.0 <2.0.0`.
|
||||
* `package:http` now supports more versions: `>=0.13.0 <2.0.0`.
|
||||
* `package:protobuf` new supports more versions: `>=2.0.0 <4.0.0`.
|
||||
|
||||
## 3.2.0
|
||||
|
||||
* `ChannelOptions` now exposes `connectTimeout`, which is used on the
|
||||
* `ChannelOptions` now exposes `connectTimeout`, which is used on the
|
||||
socket connect. This is used to specify the maximum allowed time to wait
|
||||
for a connection to be established. If `connectTime` is longer than the system
|
||||
level timeout duration, a timeout may occur sooner than specified in
|
||||
`connectTimeout`. On timeout, a `SocketException` is thrown.
|
||||
* Require Dart 2.17 or greater.
|
||||
* Fix issue [#51](https://github.com/grpc/grpc-dart/issues/51), add support for custom error handling.
|
||||
* Expose client IP address to server
|
||||
* Expose client IP address to server
|
||||
* Add a `channelShutdownHandler` argument to `ClientChannel` and the subclasses.
|
||||
This callback can be used to react to channel shutdown or termination.
|
||||
* Export the `Code` protobuf enum from the `grpc.dart` library.
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
The [Dart](https://www.dart.dev/) implementation of
|
||||
[gRPC](https://grpc.io/): A high performance, open source, general RPC framework that puts mobile and HTTP/2 first.
|
||||
|
||||
[](https://github.com/grpc/grpc-dart/actions?query=workflow%3A%22Dart%22+branch%3Amaster)
|
||||
[](https://github.com/grpc/grpc-dart/actions/workflows/dart.yml)
|
||||
[](https://pub.dev/packages/grpc)
|
||||
|
||||
|
||||
## Learn more
|
||||
|
||||
- [Quick Start](https://grpc.io/docs/languages/dart/quickstart) - get an app running in minutes
|
||||
- [Examples](example)
|
||||
- [Examples](https://github.com/grpc/grpc-dart/tree/master/example)
|
||||
- [API reference](https://grpc.io/docs/languages/dart/api)
|
||||
|
||||
For complete documentation, see [Dart gRPC](https://grpc.io/docs/languages/dart).
|
||||
|
|
|
@ -9,13 +9,15 @@ analyzer:
|
|||
|
||||
linter:
|
||||
rules:
|
||||
- always_declare_return_types
|
||||
- cancel_subscriptions
|
||||
- close_sinks
|
||||
- directives_ordering
|
||||
- omit_local_variable_types
|
||||
- prefer_final_locals
|
||||
- prefer_single_quotes
|
||||
- test_types_in_equals
|
||||
- use_super_parameters
|
||||
- prefer_relative_imports
|
||||
#true
|
||||
always_declare_return_types: true
|
||||
cancel_subscriptions: true
|
||||
close_sinks: true
|
||||
directives_ordering: true
|
||||
omit_local_variable_types: true
|
||||
prefer_final_locals: true
|
||||
prefer_single_quotes: true
|
||||
test_types_in_equals: true
|
||||
prefer_relative_imports: true
|
||||
#false
|
||||
unintended_html_in_doc_comment: false
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
Four code examples are available:
|
||||
|
||||
1. [helloworld](https://github.com/grpc/grpc-dart/tree/master/example/helloworld):
|
||||
A demonstration of using the Dart gRPC library to perform unary RPs.
|
||||
A demonstration of using the Dart gRPC library to perform unary RPCs.
|
||||
|
||||
1. [googleapis](https://github.com/grpc/grpc-dart/tree/master/example/googleapis):
|
||||
A demonstration of using the Dart gRPC library to communicate with Google APIs.
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||
</content>
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Dart SDK" level="project" />
|
||||
<orderEntry type="library" name="Dart Packages" level="project" />
|
||||
</component>
|
||||
</module>
|
|
@ -1,4 +0,0 @@
|
|||
# melos_managed_dependency_overrides: grpc
|
||||
dependency_overrides:
|
||||
grpc:
|
||||
path: ../..
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||
</content>
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Dart SDK" level="project" />
|
||||
<orderEntry type="library" name="Dart Packages" level="project" />
|
||||
</component>
|
||||
</module>
|
|
@ -1,3 +1,18 @@
|
|||
// Copyright (c) 2024, 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';
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ description: Dart gRPC-Web sample client
|
|||
publish_to: none
|
||||
|
||||
environment:
|
||||
sdk: '>=2.12.0 <3.0.0'
|
||||
sdk: ^3.5.0
|
||||
|
||||
dependencies:
|
||||
grpc:
|
||||
|
@ -11,6 +11,6 @@ dependencies:
|
|||
protobuf: ^3.0.0
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: ^2.0.0
|
||||
build_web_compilers: '>3.0.0 <5.0.0'
|
||||
lints: ^2.0.0
|
||||
build_runner: ^2.4.13
|
||||
build_web_compilers: ^4.0.11
|
||||
lints: ^5.0.0
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
# melos_managed_dependency_overrides: grpc
|
||||
dependency_overrides:
|
||||
grpc:
|
||||
path: ../..
|
|
@ -13,10 +13,10 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Dart implementation of the gRPC helloworld.Greeter client.
|
||||
import 'package:grpc/grpc.dart';
|
||||
import 'package:helloworld/src/generated/helloworld.pbgrpc.dart';
|
||||
|
||||
/// Dart implementation of the gRPC helloworld.Greeter client.
|
||||
Future<void> main(List<String> args) async {
|
||||
final channel = ClientChannel(
|
||||
'localhost',
|
||||
|
|
|
@ -13,10 +13,10 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Dart implementation of the gRPC helloworld.Greeter server.
|
||||
import 'package:grpc/grpc.dart';
|
||||
import 'package:helloworld/src/generated/helloworld.pbgrpc.dart';
|
||||
|
||||
/// Dart implementation of the gRPC helloworld.Greeter server.
|
||||
class GreeterService extends GreeterServiceBase {
|
||||
@override
|
||||
Future<HelloReply> sayHello(ServiceCall call, HelloRequest request) async {
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Dart implementation of the gRPC helloworld.Greeter client.
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:grpc/grpc.dart';
|
||||
import 'package:helloworld/src/generated/helloworld.pbgrpc.dart';
|
||||
|
||||
/// Dart implementation of the gRPC helloworld.Greeter client.
|
||||
Future<void> main(List<String> args) async {
|
||||
final udsAddress =
|
||||
InternetAddress('localhost', type: InternetAddressType.unix);
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Dart implementation of the gRPC helloworld.Greeter server.
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:grpc/grpc.dart';
|
||||
import 'package:helloworld/src/generated/helloworld.pbgrpc.dart';
|
||||
|
||||
/// Dart implementation of the gRPC helloworld.Greeter server.
|
||||
class GreeterService extends GreeterServiceBase {
|
||||
@override
|
||||
Future<HelloReply> sayHello(ServiceCall call, HelloRequest request) async {
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||
</content>
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Dart SDK" level="project" />
|
||||
<orderEntry type="library" name="Dart Packages" level="project" />
|
||||
</component>
|
||||
</module>
|
|
@ -1,4 +0,0 @@
|
|||
# melos_managed_dependency_overrides: grpc
|
||||
dependency_overrides:
|
||||
grpc:
|
||||
path: ../..
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||
</content>
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Dart SDK" level="project" />
|
||||
<orderEntry type="library" name="Dart Packages" level="project" />
|
||||
</component>
|
||||
</module>
|
|
@ -1,4 +0,0 @@
|
|||
# melos_managed_dependency_overrides: grpc
|
||||
dependency_overrides:
|
||||
grpc:
|
||||
path: ../..
|
|
@ -1,4 +0,0 @@
|
|||
# melos_managed_dependency_overrides: grpc
|
||||
dependency_overrides:
|
||||
grpc:
|
||||
path: ../..
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||
</content>
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Dart SDK" level="project" />
|
||||
<orderEntry type="library" name="Dart Packages" level="project" />
|
||||
</component>
|
||||
</module>
|
18
grpc.iml
18
grpc.iml
|
@ -1,18 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/example" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/interop" />
|
||||
</content>
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Dart SDK" level="project" />
|
||||
<orderEntry type="library" name="Dart Packages" level="project" />
|
||||
</component>
|
||||
</module>
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||
</content>
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Dart SDK" level="project" />
|
||||
<orderEntry type="library" name="Dart Packages" level="project" />
|
||||
</component>
|
||||
</module>
|
|
@ -208,7 +208,7 @@ class Tester {
|
|||
final receivedBytes = response.payload.body.length;
|
||||
if (receivedBytes != 314159) {
|
||||
throw 'Response payload mismatch. Expected 314159 bytes, '
|
||||
'got ${receivedBytes}.';
|
||||
'got $receivedBytes.';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -869,7 +869,7 @@ class Tester {
|
|||
final receivedBytes = response.payload.body.length;
|
||||
if (receivedBytes != 314159) {
|
||||
throw 'Response payload mismatch. Expected 314159 bytes, '
|
||||
'got ${receivedBytes}.';
|
||||
'got $receivedBytes.';
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
|
|
@ -3,15 +3,15 @@ description: Dart gRPC interoperability test suite.
|
|||
publish_to: none
|
||||
|
||||
environment:
|
||||
sdk: '>=3.0.0 <4.0.0'
|
||||
sdk: ^3.0.0
|
||||
|
||||
dependencies:
|
||||
args: ^2.5.0
|
||||
async: ^2.11.0
|
||||
collection: ^1.18.0
|
||||
args: ^2.0.0
|
||||
async: ^2.2.0
|
||||
collection: ^1.14.11
|
||||
grpc:
|
||||
path: ../
|
||||
protobuf: ^3.1.0
|
||||
protobuf: ^3.0.0
|
||||
|
||||
dev_dependencies:
|
||||
test: ^1.25.3
|
||||
test: ^1.16.0
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
# melos_managed_dependency_overrides: grpc
|
||||
dependency_overrides:
|
||||
grpc:
|
||||
path: ..
|
|
@ -13,6 +13,10 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// ignore: dangling_library_doc_comments
|
||||
/// Status detail types and error codes
|
||||
export 'package:grpc/src/generated/google/rpc/error_details.pb.dart';
|
||||
|
||||
export 'src/auth/auth.dart' show BaseAuthenticator;
|
||||
export 'src/auth/auth_io.dart'
|
||||
show
|
||||
|
@ -39,10 +43,6 @@ export 'src/client/options.dart'
|
|||
export 'src/client/proxy.dart' show Proxy;
|
||||
export 'src/client/transport/http2_credentials.dart'
|
||||
show BadCertificateHandler, allowBadCertificates, ChannelCredentials;
|
||||
|
||||
/// Status detail types and error codes
|
||||
export 'src/generated/google/rpc/code.pbenum.dart';
|
||||
export 'src/generated/google/rpc/error_details.pb.dart';
|
||||
export 'src/server/call.dart' show ServiceCall;
|
||||
export 'src/server/interceptor.dart' show Interceptor;
|
||||
export 'src/server/server.dart'
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
import 'src/client/grpc_or_grpcweb_channel_grpc.dart'
|
||||
if (dart.library.html) 'src/client/grpc_or_grpcweb_channel_web.dart';
|
||||
if (dart.library.js_interop) 'src/client/grpc_or_grpcweb_channel_web.dart';
|
||||
import 'src/client/http2_channel.dart';
|
||||
import 'src/client/options.dart';
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
/// Exports the minimum api to define server and client stubs.
|
||||
///
|
||||
/// Mainly intended to be imported by generated code.
|
||||
library service_api;
|
||||
library;
|
||||
|
||||
export 'src/client/call.dart' show CallOptions, MetadataProvider;
|
||||
export 'src/client/channel.dart' show ClientChannel;
|
||||
|
|
|
@ -69,7 +69,7 @@ class _CredentialsRefreshingAuthenticator extends HttpBasedAuthenticator {
|
|||
await super.authenticate(metadata, uri);
|
||||
if (_quotaProject != null) {
|
||||
// https://cloud.google.com/apis/docs/system-parameters#definitions
|
||||
metadata['X-Goog-User-Project'] = _quotaProject!;
|
||||
metadata['X-Goog-User-Project'] = _quotaProject;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -86,9 +86,9 @@ class CallOptions {
|
|||
|
||||
CallOptions mergedWith(CallOptions? other) {
|
||||
if (other == null) return this;
|
||||
final mergedMetadata = Map.from(metadata)..addAll(other.metadata);
|
||||
final mergedMetadata = Map.of(metadata)..addAll(other.metadata);
|
||||
final mergedTimeout = other.timeout ?? timeout;
|
||||
final mergedProviders = List.from(metadataProviders)
|
||||
final mergedProviders = List.of(metadataProviders)
|
||||
..addAll(other.metadataProviders);
|
||||
final mergedCompression = other.compression ?? compression;
|
||||
return CallOptions._(
|
||||
|
@ -146,9 +146,9 @@ class WebCallOptions extends CallOptions {
|
|||
CallOptions mergedWith(CallOptions? other) {
|
||||
if (other == null) return this;
|
||||
|
||||
final mergedMetadata = Map.from(metadata)..addAll(other.metadata);
|
||||
final mergedMetadata = Map.of(metadata)..addAll(other.metadata);
|
||||
final mergedTimeout = other.timeout ?? timeout;
|
||||
final mergedProviders = List.from(metadataProviders)
|
||||
final mergedProviders = List.of(metadataProviders)
|
||||
..addAll(other.metadataProviders);
|
||||
|
||||
if (other is! WebCallOptions) {
|
||||
|
@ -241,7 +241,7 @@ class ClientCall<Q, R> implements Response {
|
|||
if (options.metadataProviders.isEmpty) {
|
||||
_sendRequest(connection, _sanitizeMetadata(options.metadata));
|
||||
} else {
|
||||
final metadata = Map<String, String>.from(options.metadata);
|
||||
final metadata = Map<String, String>.of(options.metadata);
|
||||
Future.forEach(
|
||||
options.metadataProviders,
|
||||
(MetadataProvider provider) => provider(metadata,
|
||||
|
@ -483,6 +483,12 @@ class ClientCall<Q, R> implements Response {
|
|||
if (_responseSubscription != null) {
|
||||
futures.add(_responseSubscription!.cancel());
|
||||
}
|
||||
if (!_headers.isCompleted) {
|
||||
_headers.complete({});
|
||||
}
|
||||
if (!_trailers.isCompleted) {
|
||||
_trailers.complete({});
|
||||
}
|
||||
await Future.wait(futures);
|
||||
}
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ class Http2ClientConnection implements connection.ClientConnection {
|
|||
transport.ping();
|
||||
}
|
||||
},
|
||||
onPingTimeout: () => shutdown(),
|
||||
onPingTimeout: () => transport.finish(),
|
||||
);
|
||||
transport.onFrameReceived
|
||||
.listen((_) => keepAliveManager?.onFrameReceived());
|
||||
|
|
|
@ -58,7 +58,7 @@ class ChannelCredentials {
|
|||
if (!isSecure) return null;
|
||||
if (_certificateBytes != null) {
|
||||
return createSecurityContext(false)
|
||||
..setTrustedCertificatesBytes(_certificateBytes!,
|
||||
..setTrustedCertificatesBytes(_certificateBytes,
|
||||
password: _certificatePassword);
|
||||
}
|
||||
final context = SecurityContext(withTrustedRoots: true);
|
||||
|
|
|
@ -132,6 +132,16 @@ class _GrpcWebConversionSink implements ChunkedConversionSink<ByteBuffer> {
|
|||
void add(ByteBuffer chunk) {
|
||||
_chunkOffset = 0;
|
||||
final chunkData = chunk.asUint8List();
|
||||
// in flutter web, when a hot-restart is requested, the code can get stuck
|
||||
// in the following loop if there is an active streaming call. the
|
||||
// switch statement is invoked but doesn't match any of the cases. this
|
||||
// presumably has something to do how enums work across isolates.
|
||||
// possibly related to https://github.com/dart-lang/sdk/issues/35626.
|
||||
//
|
||||
// in any case, adding a default handler to the switch statement
|
||||
// causes this loop to end in that case, allowing the old isolate
|
||||
// to shut down and the hot-restart to work properly.
|
||||
processingLoop:
|
||||
while (_chunkOffset < chunk.lengthInBytes) {
|
||||
switch (_state) {
|
||||
case _GrpcWebParseState.init:
|
||||
|
@ -143,6 +153,10 @@ class _GrpcWebConversionSink implements ChunkedConversionSink<ByteBuffer> {
|
|||
case _GrpcWebParseState.message:
|
||||
_parseMessage(chunkData);
|
||||
break;
|
||||
// ignore: unreachable_switch_default
|
||||
default:
|
||||
// only expected to be hit when hot-restarting, see above
|
||||
break processingLoop;
|
||||
}
|
||||
}
|
||||
_chunkOffset = 0;
|
||||
|
|
|
@ -14,10 +14,11 @@
|
|||
// limitations under the License.
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:html';
|
||||
import 'dart:js_interop';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:web/web.dart';
|
||||
|
||||
import '../../client/call.dart';
|
||||
import '../../shared/message.dart';
|
||||
|
@ -30,7 +31,7 @@ import 'web_streams.dart';
|
|||
const _contentTypeKey = 'Content-Type';
|
||||
|
||||
class XhrTransportStream implements GrpcTransportStream {
|
||||
final HttpRequest _request;
|
||||
final IXMLHttpRequest _request;
|
||||
final ErrorHandler _onError;
|
||||
final Function(XhrTransportStream stream) _onDone;
|
||||
bool _headersReceived = false;
|
||||
|
@ -49,19 +50,20 @@ class XhrTransportStream implements GrpcTransportStream {
|
|||
{required ErrorHandler onError, required onDone})
|
||||
: _onError = onError,
|
||||
_onDone = onDone {
|
||||
_outgoingMessages.stream
|
||||
.map(frame)
|
||||
.listen((data) => _request.send(data), cancelOnError: true);
|
||||
_outgoingMessages.stream.map(frame).listen(
|
||||
(data) => _request.send(Uint8List.fromList(data).toJS),
|
||||
cancelOnError: true,
|
||||
onError: _onError);
|
||||
|
||||
_request.onReadyStateChange.listen((data) {
|
||||
_request.onReadyStateChange.listen((_) {
|
||||
if (_incomingProcessor.isClosed) {
|
||||
return;
|
||||
}
|
||||
switch (_request.readyState) {
|
||||
case HttpRequest.HEADERS_RECEIVED:
|
||||
case XMLHttpRequest.HEADERS_RECEIVED:
|
||||
_onHeadersReceived();
|
||||
break;
|
||||
case HttpRequest.DONE:
|
||||
case XMLHttpRequest.DONE:
|
||||
_onRequestDone();
|
||||
_close();
|
||||
break;
|
||||
|
@ -81,13 +83,11 @@ class XhrTransportStream implements GrpcTransportStream {
|
|||
if (_incomingProcessor.isClosed) {
|
||||
return;
|
||||
}
|
||||
// Use response over responseText as most browsers don't support
|
||||
// using responseText during an onProgress event.
|
||||
final responseString = _request.response as String;
|
||||
final responseText = _request.responseText;
|
||||
final bytes = Uint8List.fromList(
|
||||
responseString.substring(_requestBytesRead).codeUnits)
|
||||
responseText.substring(_requestBytesRead).codeUnits)
|
||||
.buffer;
|
||||
_requestBytesRead = responseString.length;
|
||||
_requestBytesRead = responseText.length;
|
||||
_incomingProcessor.add(bytes);
|
||||
});
|
||||
|
||||
|
@ -122,9 +122,11 @@ class XhrTransportStream implements GrpcTransportStream {
|
|||
if (!_headersReceived && !_validateResponseState()) {
|
||||
return;
|
||||
}
|
||||
if (_request.response == null) {
|
||||
if (_request.status != 200) {
|
||||
_onError(
|
||||
GrpcError.unavailable('XhrConnection request null response', null,
|
||||
GrpcError.unavailable(
|
||||
'Request failed with status: ${_request.status}',
|
||||
null,
|
||||
_request.responseText),
|
||||
StackTrace.current);
|
||||
return;
|
||||
|
@ -144,6 +146,110 @@ class XhrTransportStream implements GrpcTransportStream {
|
|||
}
|
||||
}
|
||||
|
||||
// XMLHttpRequest is an extension type and can't be extended or implemented.
|
||||
// This interface is used to allow for mocking XMLHttpRequest in tests of
|
||||
// XhrClientConnection.
|
||||
@visibleForTesting
|
||||
abstract interface class IXMLHttpRequest {
|
||||
Stream<Event> get onReadyStateChange;
|
||||
Stream<ProgressEvent> get onProgress;
|
||||
Stream<ProgressEvent> get onError;
|
||||
int get readyState;
|
||||
JSAny? get response;
|
||||
String get responseText;
|
||||
Map<String, String> get responseHeaders;
|
||||
int get status;
|
||||
|
||||
set responseType(String responseType);
|
||||
set withCredentials(bool withCredentials);
|
||||
|
||||
void abort();
|
||||
void open(
|
||||
String method,
|
||||
String url, [
|
||||
// external default is true
|
||||
bool async = true,
|
||||
String? username,
|
||||
String? password,
|
||||
]);
|
||||
void overrideMimeType(String mimeType);
|
||||
void send([JSAny? body]);
|
||||
void setRequestHeader(String header, String value);
|
||||
|
||||
// This method should only be used in production code.
|
||||
XMLHttpRequest toXMLHttpRequest();
|
||||
}
|
||||
|
||||
// IXMLHttpRequest that delegates to a real XMLHttpRequest.
|
||||
class XMLHttpRequestImpl implements IXMLHttpRequest {
|
||||
final XMLHttpRequest _xhr = XMLHttpRequest();
|
||||
|
||||
XMLHttpRequestImpl();
|
||||
|
||||
@override
|
||||
Stream<Event> get onReadyStateChange => _xhr.onReadyStateChange;
|
||||
@override
|
||||
Stream<ProgressEvent> get onProgress => _xhr.onProgress;
|
||||
@override
|
||||
Stream<ProgressEvent> get onError => _xhr.onError;
|
||||
@override
|
||||
int get readyState => _xhr.readyState;
|
||||
@override
|
||||
Map<String, String> get responseHeaders => _xhr.responseHeaders;
|
||||
@override
|
||||
JSAny? get response => _xhr.response;
|
||||
@override
|
||||
String get responseText => _xhr.responseText;
|
||||
@override
|
||||
int get status => _xhr.status;
|
||||
|
||||
@override
|
||||
set responseType(String responseType) {
|
||||
_xhr.responseType = responseType;
|
||||
}
|
||||
|
||||
@override
|
||||
set withCredentials(bool withCredentials) {
|
||||
_xhr.withCredentials = withCredentials;
|
||||
}
|
||||
|
||||
@override
|
||||
void abort() {
|
||||
_xhr.abort();
|
||||
}
|
||||
|
||||
@override
|
||||
void open(
|
||||
String method,
|
||||
String url, [
|
||||
bool async = true,
|
||||
String? username,
|
||||
String? password,
|
||||
]) {
|
||||
_xhr.open(method, url, async, username, password);
|
||||
}
|
||||
|
||||
@override
|
||||
void overrideMimeType(String mimeType) {
|
||||
_xhr.overrideMimeType(mimeType);
|
||||
}
|
||||
|
||||
@override
|
||||
void setRequestHeader(String header, String value) {
|
||||
_xhr.setRequestHeader(header, value);
|
||||
}
|
||||
|
||||
@override
|
||||
void send([JSAny? body]) {
|
||||
_xhr.send(body);
|
||||
}
|
||||
|
||||
@override
|
||||
XMLHttpRequest toXMLHttpRequest() {
|
||||
return _xhr;
|
||||
}
|
||||
}
|
||||
|
||||
class XhrClientConnection implements ClientConnection {
|
||||
final Uri uri;
|
||||
|
||||
|
@ -153,20 +259,20 @@ class XhrClientConnection implements ClientConnection {
|
|||
|
||||
@override
|
||||
String get authority => uri.authority;
|
||||
|
||||
@override
|
||||
String get scheme => uri.scheme;
|
||||
|
||||
void _initializeRequest(HttpRequest request, Map<String, String> metadata) {
|
||||
for (final header in metadata.keys) {
|
||||
request.setRequestHeader(header, metadata[header]!);
|
||||
}
|
||||
void _initializeRequest(
|
||||
IXMLHttpRequest request, Map<String, String> metadata) {
|
||||
metadata.forEach(request.setRequestHeader);
|
||||
// Overriding the mimetype allows us to stream and parse the data
|
||||
request.overrideMimeType('text/plain; charset=x-user-defined');
|
||||
request.responseType = 'text';
|
||||
}
|
||||
|
||||
@visibleForTesting
|
||||
HttpRequest createHttpRequest() => HttpRequest();
|
||||
IXMLHttpRequest createHttpRequest() => XMLHttpRequestImpl();
|
||||
|
||||
@override
|
||||
GrpcTransportStream makeRequest(String path, Duration? timeout,
|
||||
|
@ -194,11 +300,16 @@ class XhrClientConnection implements ClientConnection {
|
|||
_initializeRequest(request, metadata);
|
||||
|
||||
final transportStream =
|
||||
XhrTransportStream(request, onError: onError, onDone: _removeStream);
|
||||
_createXhrTransportStream(request, onError, _removeStream);
|
||||
_requests.add(transportStream);
|
||||
return transportStream;
|
||||
}
|
||||
|
||||
XhrTransportStream _createXhrTransportStream(IXMLHttpRequest request,
|
||||
ErrorHandler onError, void Function(XhrTransportStream stream) onDone) {
|
||||
return XhrTransportStream(request, onError: onError, onDone: onDone);
|
||||
}
|
||||
|
||||
void _removeStream(XhrTransportStream stream) {
|
||||
_requests.remove(stream);
|
||||
}
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
//
|
||||
// Generated code. Do not modify.
|
||||
// source: google/rpc/code.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
|
||||
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
||||
import 'dart:core' as $core;
|
||||
|
||||
export 'code.pbenum.dart';
|
|
@ -1,79 +0,0 @@
|
|||
//
|
||||
// Generated code. Do not modify.
|
||||
// source: google/rpc/code.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
|
||||
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
||||
import 'dart:core' as $core;
|
||||
|
||||
import 'package:protobuf/protobuf.dart' as $pb;
|
||||
|
||||
/// The canonical error codes for gRPC APIs.
|
||||
///
|
||||
///
|
||||
/// Sometimes multiple error codes may apply. Services should return
|
||||
/// the most specific error code that applies. For example, prefer
|
||||
/// `OUT_OF_RANGE` over `FAILED_PRECONDITION` if both codes apply.
|
||||
/// Similarly prefer `NOT_FOUND` or `ALREADY_EXISTS` over `FAILED_PRECONDITION`.
|
||||
class Code extends $pb.ProtobufEnum {
|
||||
static const Code OK = Code._(0, _omitEnumNames ? '' : 'OK');
|
||||
static const Code CANCELLED = Code._(1, _omitEnumNames ? '' : 'CANCELLED');
|
||||
static const Code UNKNOWN = Code._(2, _omitEnumNames ? '' : 'UNKNOWN');
|
||||
static const Code INVALID_ARGUMENT =
|
||||
Code._(3, _omitEnumNames ? '' : 'INVALID_ARGUMENT');
|
||||
static const Code DEADLINE_EXCEEDED =
|
||||
Code._(4, _omitEnumNames ? '' : 'DEADLINE_EXCEEDED');
|
||||
static const Code NOT_FOUND = Code._(5, _omitEnumNames ? '' : 'NOT_FOUND');
|
||||
static const Code ALREADY_EXISTS =
|
||||
Code._(6, _omitEnumNames ? '' : 'ALREADY_EXISTS');
|
||||
static const Code PERMISSION_DENIED =
|
||||
Code._(7, _omitEnumNames ? '' : 'PERMISSION_DENIED');
|
||||
static const Code UNAUTHENTICATED =
|
||||
Code._(16, _omitEnumNames ? '' : 'UNAUTHENTICATED');
|
||||
static const Code RESOURCE_EXHAUSTED =
|
||||
Code._(8, _omitEnumNames ? '' : 'RESOURCE_EXHAUSTED');
|
||||
static const Code FAILED_PRECONDITION =
|
||||
Code._(9, _omitEnumNames ? '' : 'FAILED_PRECONDITION');
|
||||
static const Code ABORTED = Code._(10, _omitEnumNames ? '' : 'ABORTED');
|
||||
static const Code OUT_OF_RANGE =
|
||||
Code._(11, _omitEnumNames ? '' : 'OUT_OF_RANGE');
|
||||
static const Code UNIMPLEMENTED =
|
||||
Code._(12, _omitEnumNames ? '' : 'UNIMPLEMENTED');
|
||||
static const Code INTERNAL = Code._(13, _omitEnumNames ? '' : 'INTERNAL');
|
||||
static const Code UNAVAILABLE =
|
||||
Code._(14, _omitEnumNames ? '' : 'UNAVAILABLE');
|
||||
static const Code DATA_LOSS = Code._(15, _omitEnumNames ? '' : 'DATA_LOSS');
|
||||
|
||||
static const $core.List<Code> values = <Code>[
|
||||
OK,
|
||||
CANCELLED,
|
||||
UNKNOWN,
|
||||
INVALID_ARGUMENT,
|
||||
DEADLINE_EXCEEDED,
|
||||
NOT_FOUND,
|
||||
ALREADY_EXISTS,
|
||||
PERMISSION_DENIED,
|
||||
UNAUTHENTICATED,
|
||||
RESOURCE_EXHAUSTED,
|
||||
FAILED_PRECONDITION,
|
||||
ABORTED,
|
||||
OUT_OF_RANGE,
|
||||
UNIMPLEMENTED,
|
||||
INTERNAL,
|
||||
UNAVAILABLE,
|
||||
DATA_LOSS,
|
||||
];
|
||||
|
||||
static final $core.Map<$core.int, Code> _byValue =
|
||||
$pb.ProtobufEnum.initByValue(values);
|
||||
static Code? valueOf($core.int value) => _byValue[value];
|
||||
|
||||
const Code._($core.int v, $core.String n) : super(v, n);
|
||||
}
|
||||
|
||||
const _omitEnumNames = $core.bool.fromEnvironment('protobuf.omit_enum_names');
|
|
@ -1,47 +0,0 @@
|
|||
//
|
||||
// Generated code. Do not modify.
|
||||
// source: google/rpc/code.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
|
||||
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
||||
import 'dart:convert' as $convert;
|
||||
import 'dart:core' as $core;
|
||||
import 'dart:typed_data' as $typed_data;
|
||||
|
||||
@$core.Deprecated('Use codeDescriptor instead')
|
||||
const Code$json = {
|
||||
'1': 'Code',
|
||||
'2': [
|
||||
{'1': 'OK', '2': 0},
|
||||
{'1': 'CANCELLED', '2': 1},
|
||||
{'1': 'UNKNOWN', '2': 2},
|
||||
{'1': 'INVALID_ARGUMENT', '2': 3},
|
||||
{'1': 'DEADLINE_EXCEEDED', '2': 4},
|
||||
{'1': 'NOT_FOUND', '2': 5},
|
||||
{'1': 'ALREADY_EXISTS', '2': 6},
|
||||
{'1': 'PERMISSION_DENIED', '2': 7},
|
||||
{'1': 'UNAUTHENTICATED', '2': 16},
|
||||
{'1': 'RESOURCE_EXHAUSTED', '2': 8},
|
||||
{'1': 'FAILED_PRECONDITION', '2': 9},
|
||||
{'1': 'ABORTED', '2': 10},
|
||||
{'1': 'OUT_OF_RANGE', '2': 11},
|
||||
{'1': 'UNIMPLEMENTED', '2': 12},
|
||||
{'1': 'INTERNAL', '2': 13},
|
||||
{'1': 'UNAVAILABLE', '2': 14},
|
||||
{'1': 'DATA_LOSS', '2': 15},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `Code`. Decode as a `google.protobuf.EnumDescriptorProto`.
|
||||
final $typed_data.Uint8List codeDescriptor = $convert.base64Decode(
|
||||
'CgRDb2RlEgYKAk9LEAASDQoJQ0FOQ0VMTEVEEAESCwoHVU5LTk9XThACEhQKEElOVkFMSURfQV'
|
||||
'JHVU1FTlQQAxIVChFERUFETElORV9FWENFRURFRBAEEg0KCU5PVF9GT1VORBAFEhIKDkFMUkVB'
|
||||
'RFlfRVhJU1RTEAYSFQoRUEVSTUlTU0lPTl9ERU5JRUQQBxITCg9VTkFVVEhFTlRJQ0FURUQQEB'
|
||||
'IWChJSRVNPVVJDRV9FWEhBVVNURUQQCBIXChNGQUlMRURfUFJFQ09ORElUSU9OEAkSCwoHQUJP'
|
||||
'UlRFRBAKEhAKDE9VVF9PRl9SQU5HRRALEhEKDVVOSU1QTEVNRU5URUQQDBIMCghJTlRFUk5BTB'
|
||||
'ANEg8KC1VOQVZBSUxBQkxFEA4SDQoJREFUQV9MT1NTEA8=');
|
|
@ -1,186 +0,0 @@
|
|||
// Copyright 2020 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
|
||||
//
|
||||
// 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.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.rpc;
|
||||
|
||||
option go_package = "google.golang.org/genproto/googleapis/rpc/code;code";
|
||||
option java_multiple_files = true;
|
||||
option java_outer_classname = "CodeProto";
|
||||
option java_package = "com.google.rpc";
|
||||
option objc_class_prefix = "RPC";
|
||||
|
||||
// The canonical error codes for gRPC APIs.
|
||||
//
|
||||
//
|
||||
// Sometimes multiple error codes may apply. Services should return
|
||||
// the most specific error code that applies. For example, prefer
|
||||
// `OUT_OF_RANGE` over `FAILED_PRECONDITION` if both codes apply.
|
||||
// Similarly prefer `NOT_FOUND` or `ALREADY_EXISTS` over `FAILED_PRECONDITION`.
|
||||
enum Code {
|
||||
// Not an error; returned on success
|
||||
//
|
||||
// HTTP Mapping: 200 OK
|
||||
OK = 0;
|
||||
|
||||
// The operation was cancelled, typically by the caller.
|
||||
//
|
||||
// HTTP Mapping: 499 Client Closed Request
|
||||
CANCELLED = 1;
|
||||
|
||||
// Unknown error. For example, this error may be returned when
|
||||
// a `Status` value received from another address space belongs to
|
||||
// an error space that is not known in this address space. Also
|
||||
// errors raised by APIs that do not return enough error information
|
||||
// may be converted to this error.
|
||||
//
|
||||
// HTTP Mapping: 500 Internal Server Error
|
||||
UNKNOWN = 2;
|
||||
|
||||
// The client specified an invalid argument. Note that this differs
|
||||
// from `FAILED_PRECONDITION`. `INVALID_ARGUMENT` indicates arguments
|
||||
// that are problematic regardless of the state of the system
|
||||
// (e.g., a malformed file name).
|
||||
//
|
||||
// HTTP Mapping: 400 Bad Request
|
||||
INVALID_ARGUMENT = 3;
|
||||
|
||||
// The deadline expired before the operation could complete. For operations
|
||||
// that change the state of the system, this error may be returned
|
||||
// even if the operation has completed successfully. For example, a
|
||||
// successful response from a server could have been delayed long
|
||||
// enough for the deadline to expire.
|
||||
//
|
||||
// HTTP Mapping: 504 Gateway Timeout
|
||||
DEADLINE_EXCEEDED = 4;
|
||||
|
||||
// Some requested entity (e.g., file or directory) was not found.
|
||||
//
|
||||
// Note to server developers: if a request is denied for an entire class
|
||||
// of users, such as gradual feature rollout or undocumented whitelist,
|
||||
// `NOT_FOUND` may be used. If a request is denied for some users within
|
||||
// a class of users, such as user-based access control, `PERMISSION_DENIED`
|
||||
// must be used.
|
||||
//
|
||||
// HTTP Mapping: 404 Not Found
|
||||
NOT_FOUND = 5;
|
||||
|
||||
// The entity that a client attempted to create (e.g., file or directory)
|
||||
// already exists.
|
||||
//
|
||||
// HTTP Mapping: 409 Conflict
|
||||
ALREADY_EXISTS = 6;
|
||||
|
||||
// The caller does not have permission to execute the specified
|
||||
// operation. `PERMISSION_DENIED` must not be used for rejections
|
||||
// caused by exhausting some resource (use `RESOURCE_EXHAUSTED`
|
||||
// instead for those errors). `PERMISSION_DENIED` must not be
|
||||
// used if the caller can not be identified (use `UNAUTHENTICATED`
|
||||
// instead for those errors). This error code does not imply the
|
||||
// request is valid or the requested entity exists or satisfies
|
||||
// other pre-conditions.
|
||||
//
|
||||
// HTTP Mapping: 403 Forbidden
|
||||
PERMISSION_DENIED = 7;
|
||||
|
||||
// The request does not have valid authentication credentials for the
|
||||
// operation.
|
||||
//
|
||||
// HTTP Mapping: 401 Unauthorized
|
||||
UNAUTHENTICATED = 16;
|
||||
|
||||
// Some resource has been exhausted, perhaps a per-user quota, or
|
||||
// perhaps the entire file system is out of space.
|
||||
//
|
||||
// HTTP Mapping: 429 Too Many Requests
|
||||
RESOURCE_EXHAUSTED = 8;
|
||||
|
||||
// The operation was rejected because the system is not in a state
|
||||
// required for the operation's execution. For example, the directory
|
||||
// to be deleted is non-empty, an rmdir operation is applied to
|
||||
// a non-directory, etc.
|
||||
//
|
||||
// Service implementors can use the following guidelines to decide
|
||||
// between `FAILED_PRECONDITION`, `ABORTED`, and `UNAVAILABLE`:
|
||||
// (a) Use `UNAVAILABLE` if the client can retry just the failing call.
|
||||
// (b) Use `ABORTED` if the client should retry at a higher level
|
||||
// (e.g., when a client-specified test-and-set fails, indicating the
|
||||
// client should restart a read-modify-write sequence).
|
||||
// (c) Use `FAILED_PRECONDITION` if the client should not retry until
|
||||
// the system state has been explicitly fixed. E.g., if an "rmdir"
|
||||
// fails because the directory is non-empty, `FAILED_PRECONDITION`
|
||||
// should be returned since the client should not retry unless
|
||||
// the files are deleted from the directory.
|
||||
//
|
||||
// HTTP Mapping: 400 Bad Request
|
||||
FAILED_PRECONDITION = 9;
|
||||
|
||||
// The operation was aborted, typically due to a concurrency issue such as
|
||||
// a sequencer check failure or transaction abort.
|
||||
//
|
||||
// See the guidelines above for deciding between `FAILED_PRECONDITION`,
|
||||
// `ABORTED`, and `UNAVAILABLE`.
|
||||
//
|
||||
// HTTP Mapping: 409 Conflict
|
||||
ABORTED = 10;
|
||||
|
||||
// The operation was attempted past the valid range. E.g., seeking or
|
||||
// reading past end-of-file.
|
||||
//
|
||||
// Unlike `INVALID_ARGUMENT`, this error indicates a problem that may
|
||||
// be fixed if the system state changes. For example, a 32-bit file
|
||||
// system will generate `INVALID_ARGUMENT` if asked to read at an
|
||||
// offset that is not in the range [0,2^32-1], but it will generate
|
||||
// `OUT_OF_RANGE` if asked to read from an offset past the current
|
||||
// file size.
|
||||
//
|
||||
// There is a fair bit of overlap between `FAILED_PRECONDITION` and
|
||||
// `OUT_OF_RANGE`. We recommend using `OUT_OF_RANGE` (the more specific
|
||||
// error) when it applies so that callers who are iterating through
|
||||
// a space can easily look for an `OUT_OF_RANGE` error to detect when
|
||||
// they are done.
|
||||
//
|
||||
// HTTP Mapping: 400 Bad Request
|
||||
OUT_OF_RANGE = 11;
|
||||
|
||||
// The operation is not implemented or is not supported/enabled in this
|
||||
// service.
|
||||
//
|
||||
// HTTP Mapping: 501 Not Implemented
|
||||
UNIMPLEMENTED = 12;
|
||||
|
||||
// Internal errors. This means that some invariants expected by the
|
||||
// underlying system have been broken. This error code is reserved
|
||||
// for serious errors.
|
||||
//
|
||||
// HTTP Mapping: 500 Internal Server Error
|
||||
INTERNAL = 13;
|
||||
|
||||
// The service is currently unavailable. This is most likely a
|
||||
// transient condition, which can be corrected by retrying with
|
||||
// a backoff. Note that it is not always safe to retry
|
||||
// non-idempotent operations.
|
||||
//
|
||||
// See the guidelines above for deciding between `FAILED_PRECONDITION`,
|
||||
// `ABORTED`, and `UNAVAILABLE`.
|
||||
//
|
||||
// HTTP Mapping: 503 Service Unavailable
|
||||
UNAVAILABLE = 14;
|
||||
|
||||
// Unrecoverable data loss or corruption.
|
||||
//
|
||||
// HTTP Mapping: 500 Internal Server Error
|
||||
DATA_LOSS = 15;
|
||||
}
|
|
@ -170,7 +170,7 @@ class ServerHandler extends ServiceCall {
|
|||
final acceptedEncodings =
|
||||
clientMetadata!['grpc-accept-encoding']?.split(',') ?? [];
|
||||
_callEncodingCodec = acceptedEncodings
|
||||
.map(_codecRegistry!.lookup)
|
||||
.map(_codecRegistry.lookup)
|
||||
.firstWhere((c) => c != null, orElse: () => null);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,56 +13,6 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import 'package:archive/archive.dart';
|
||||
|
||||
abstract class Codec {
|
||||
/// Returns the message encoding that this compressor uses.
|
||||
///
|
||||
/// This can be values such as "gzip", "deflate", "snappy", etc.
|
||||
String get encodingName;
|
||||
|
||||
/// Wraps an existing output stream with a compressed output.
|
||||
List<int> compress(List<int> data);
|
||||
|
||||
/// Wraps an existing output stream with a uncompressed input data.
|
||||
List<int> decompress(List<int> data);
|
||||
}
|
||||
|
||||
/// The "identity", or "none" codec.
|
||||
///
|
||||
/// This codec is special in that it can be used to explicitly disable Call
|
||||
/// compression on a Channel that by default compresses.
|
||||
class IdentityCodec implements Codec {
|
||||
const IdentityCodec();
|
||||
|
||||
@override
|
||||
final encodingName = 'identity';
|
||||
|
||||
@override
|
||||
List<int> compress(List<int> data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
@override
|
||||
List<int> decompress(List<int> data) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
/// A gzip compressor and decompressor.
|
||||
class GzipCodec implements Codec {
|
||||
const GzipCodec();
|
||||
|
||||
@override
|
||||
final encodingName = 'gzip';
|
||||
|
||||
@override
|
||||
List<int> compress(List<int> data) {
|
||||
return GZipEncoder().encode(data)!;
|
||||
}
|
||||
|
||||
@override
|
||||
List<int> decompress(List<int> data) {
|
||||
return GZipDecoder().decodeBytes(data);
|
||||
}
|
||||
}
|
||||
export 'codec/codec_all.dart';
|
||||
export 'codec/codec_io.dart'
|
||||
if (dart.library.js_interop) 'codec/codec_web.dart'; // package:web implementation
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright (c) 2024, 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.
|
||||
|
||||
abstract class Codec {
|
||||
/// Returns the message encoding that this compressor uses.
|
||||
///
|
||||
/// This can be values such as "gzip", "deflate", "snappy", etc.
|
||||
String get encodingName;
|
||||
|
||||
/// Wraps an existing output stream with a compressed output.
|
||||
List<int> compress(List<int> data);
|
||||
|
||||
/// Wraps an existing output stream with a uncompressed input data.
|
||||
List<int> decompress(List<int> data);
|
||||
}
|
||||
|
||||
/// The "identity", or "none" codec.
|
||||
///
|
||||
/// This codec is special in that it can be used to explicitly disable Call
|
||||
/// compression on a Channel that by default compresses.
|
||||
class IdentityCodec implements Codec {
|
||||
const IdentityCodec();
|
||||
|
||||
@override
|
||||
final encodingName = 'identity';
|
||||
|
||||
@override
|
||||
List<int> compress(List<int> data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
@override
|
||||
List<int> decompress(List<int> data) {
|
||||
return data;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright (c) 2024, 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 'codec_all.dart';
|
||||
|
||||
/// A gzip compressor and decompressor.
|
||||
class GzipCodec implements Codec {
|
||||
const GzipCodec();
|
||||
|
||||
@override
|
||||
final encodingName = 'gzip';
|
||||
|
||||
@override
|
||||
List<int> compress(List<int> data) {
|
||||
return gzip.encode(data);
|
||||
}
|
||||
|
||||
@override
|
||||
List<int> decompress(List<int> data) {
|
||||
return gzip.decode(data);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright (c) 2024, 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 'codec_all.dart';
|
||||
|
||||
/// A gzip compressor and decompressor.
|
||||
class GzipCodec implements Codec {
|
||||
const GzipCodec();
|
||||
|
||||
@override
|
||||
final encodingName = 'gzip';
|
||||
|
||||
@override
|
||||
List<int> compress(List<int> data) {
|
||||
throw UnsupportedError('Gzip is not supported for grpc web');
|
||||
}
|
||||
|
||||
@override
|
||||
List<int> decompress(List<int> data) {
|
||||
throw UnsupportedError('Gzip is not supported for grpc web');
|
||||
}
|
||||
}
|
|
@ -68,7 +68,8 @@ List<int> frame(List<int> rawPayload, [Codec? codec]) {
|
|||
final payloadLength = compressedPayload.length;
|
||||
final bytes = Uint8List(payloadLength + 5);
|
||||
final header = bytes.buffer.asByteData(0, 5);
|
||||
header.setUint8(0, codec == null ? 0 : 1);
|
||||
header.setUint8(
|
||||
0, (codec == null || codec.encodingName == 'identity') ? 0 : 1);
|
||||
header.setUint32(1, payloadLength);
|
||||
bytes.setRange(5, bytes.length, compressedPayload);
|
||||
return bytes;
|
||||
|
|
|
@ -13,15 +13,16 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// ignore_for_file: prefer_relative_imports
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:grpc/src/generated/google/protobuf/any.pb.dart';
|
||||
import 'package:grpc/src/generated/google/rpc/error_details.pb.dart';
|
||||
import 'package:grpc/src/generated/google/rpc/status.pb.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:protobuf/protobuf.dart';
|
||||
|
||||
import '../generated/google/protobuf/any.pb.dart';
|
||||
import '../generated/google/rpc/code.pbenum.dart';
|
||||
import '../generated/google/rpc/error_details.pb.dart';
|
||||
import '../generated/google/rpc/status.pb.dart';
|
||||
import 'io_bits/io_bits.dart' show HttpStatus;
|
||||
|
||||
class StatusCode {
|
||||
|
@ -149,6 +150,28 @@ class StatusCode {
|
|||
static int fromHttpStatus(int status) {
|
||||
return _httpStatusToGrpcStatus[status] ?? StatusCode.unknown;
|
||||
}
|
||||
|
||||
/// Creates a string from a gRPC status code.
|
||||
static String? name(int status) => switch (status) {
|
||||
ok => 'OK',
|
||||
cancelled => 'CANCELLED',
|
||||
unknown => 'UNKNOWN',
|
||||
invalidArgument => 'INVALID_ARGUMENT',
|
||||
deadlineExceeded => 'DEADLINE_EXCEEDED',
|
||||
notFound => 'NOT_FOUND',
|
||||
alreadyExists => 'ALREADY_EXISTS',
|
||||
permissionDenied => 'PERMISSION_DENIED',
|
||||
resourceExhausted => 'RESOURCE_EXHAUSTED',
|
||||
failedPrecondition => 'FAILED_PRECONDITION',
|
||||
aborted => 'ABORTED',
|
||||
outOfRange => 'OUT_OF_RANGE',
|
||||
unimplemented => 'UNIMPLEMENTED',
|
||||
internal => 'INTERNAL',
|
||||
unavailable => 'UNAVAILABLE',
|
||||
dataLoss => 'DATA_LOSS',
|
||||
unauthenticated => 'UNAUTHENTICATED',
|
||||
int() => null,
|
||||
};
|
||||
}
|
||||
|
||||
class GrpcError implements Exception {
|
||||
|
@ -306,7 +329,8 @@ class GrpcError implements Exception {
|
|||
code = StatusCode.unauthenticated;
|
||||
|
||||
/// Given a status code, return the name
|
||||
String get codeName => (Code.valueOf(code) ?? Code.UNKNOWN).name;
|
||||
String get codeName =>
|
||||
StatusCode.name(code) ?? StatusCode.name(StatusCode.unknown)!;
|
||||
|
||||
@override
|
||||
bool operator ==(other) {
|
||||
|
@ -328,6 +352,7 @@ class GrpcError implements Exception {
|
|||
/// This list comes from `error_details.proto`. If any new error detail types are
|
||||
/// added to the protbuf definition, this function should be updated accordingly to
|
||||
/// support them.
|
||||
@visibleForTesting
|
||||
GeneratedMessage parseErrorDetailsFromAny(Any any) {
|
||||
switch (any.typeUrl) {
|
||||
case 'type.googleapis.com/google.rpc.RetryInfo':
|
||||
|
@ -449,7 +474,7 @@ GrpcError? grpcErrorDetailsFromTrailers(Map<String, String> trailers) {
|
|||
}
|
||||
|
||||
Map<String, String> toCustomTrailers(Map<String, String> trailers) {
|
||||
return Map.from(trailers)
|
||||
return Map.of(trailers)
|
||||
..remove(':status')
|
||||
..remove('content-type')
|
||||
..remove('grpc-status')
|
||||
|
|
42
pubspec.yaml
42
pubspec.yaml
|
@ -1,35 +1,41 @@
|
|||
name: grpc
|
||||
description: Dart implementation of gRPC, a high performance, open-source universal RPC framework.
|
||||
version: 3.2.4
|
||||
version: 4.0.2-wip
|
||||
|
||||
repository: https://github.com/grpc/grpc-dart
|
||||
|
||||
environment:
|
||||
sdk: '>=3.3.0 <4.5.0'
|
||||
sdk: ^3.5.0
|
||||
|
||||
dependencies:
|
||||
archive: ^3.4.10
|
||||
async: ^2.11.0
|
||||
crypto: ^3.0.3
|
||||
fixnum: ^1.1.0
|
||||
googleapis_auth: ^1.6.0
|
||||
meta: ">=1.11.0 <2.0.0"
|
||||
async: ^2.5.0
|
||||
crypto: ^3.0.0
|
||||
fixnum: ^1.0.0
|
||||
googleapis_auth: ^1.1.0
|
||||
meta: ^1.3.0
|
||||
http: '>=0.13.0 <2.0.0'
|
||||
http2: ^2.3.0
|
||||
http2: ^2.2.0
|
||||
protobuf: '>=2.0.0 <4.0.0'
|
||||
clock: ^1.1.1
|
||||
web: ^1.1.0
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: ^2.4.9
|
||||
build_test: ^2.2.2
|
||||
lints: ">=2.0.0 <4.0.0"
|
||||
mockito: ^5.4.4
|
||||
path: ^1.9.0
|
||||
test: ^1.25.3
|
||||
stream_channel: ^2.1.2
|
||||
stream_transform: ^2.1.0
|
||||
vm_service: ">=11.6.0 <15.0.0"
|
||||
build_runner: ^2.0.0
|
||||
build_test: ^2.0.0
|
||||
lints: ^5.0.0
|
||||
mockito: ^5.0.0
|
||||
path: ^1.8.0
|
||||
test: ^1.16.0
|
||||
stream_channel: ^2.1.0
|
||||
stream_transform: ^2.0.0
|
||||
vm_service: ">=11.6.0 <16.0.0"
|
||||
fake_async: ^1.3.1
|
||||
|
||||
false_secrets:
|
||||
- interop/server1.key
|
||||
- test/data/localhost.key
|
||||
|
||||
topics:
|
||||
- grpc
|
||||
- rpc
|
||||
- protocols
|
||||
|
|
|
@ -1,6 +1,23 @@
|
|||
// Copyright (c) 2024, 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.
|
||||
|
||||
// TODO(dartbug.com/26057) currently Mac OS X seems to have some issues with
|
||||
// client certificates so we disable the test.
|
||||
@TestOn('vm && !mac-os')
|
||||
library;
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
|
|
|
@ -1,4 +1,21 @@
|
|||
// Copyright (c) 2024, 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')
|
||||
library;
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:grpc/grpc.dart' as grpc;
|
||||
|
|
|
@ -1,7 +1,38 @@
|
|||
// Copyright (c) 2024, 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/grpc.dart';
|
||||
import 'package:grpc/src/client/call.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../src/client_utils.dart';
|
||||
|
||||
void main() {
|
||||
const dummyValue = 0;
|
||||
const cancelDurationMillis = 300;
|
||||
|
||||
late ClientHarness harness;
|
||||
|
||||
setUp(() {
|
||||
harness = ClientHarness()..setUp();
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
harness.tearDown();
|
||||
});
|
||||
|
||||
test('WebCallOptions mergeWith CallOptions returns WebCallOptions', () {
|
||||
final options =
|
||||
WebCallOptions(bypassCorsPreflight: true, withCredentials: true);
|
||||
|
@ -13,4 +44,57 @@ void main() {
|
|||
expect(mergedOptions.bypassCorsPreflight, true);
|
||||
expect(mergedOptions.withCredentials, true);
|
||||
});
|
||||
|
||||
test(
|
||||
'Cancelling a call correctly complete headers future',
|
||||
() async {
|
||||
final clientCall = harness.client.unary(dummyValue);
|
||||
|
||||
Future.delayed(
|
||||
Duration(milliseconds: cancelDurationMillis),
|
||||
).then((_) => clientCall.cancel());
|
||||
|
||||
expect(await clientCall.headers, isEmpty);
|
||||
|
||||
await expectLater(
|
||||
clientCall,
|
||||
throwsA(
|
||||
isA<GrpcError>().having(
|
||||
(e) => e.codeName,
|
||||
'Test codename',
|
||||
contains('CANCELLED'),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'Cancelling a call correctly complete trailers futures',
|
||||
() async {
|
||||
final clientCall = harness.client.unary(dummyValue);
|
||||
|
||||
Future.delayed(
|
||||
Duration(milliseconds: cancelDurationMillis),
|
||||
).then((_) {
|
||||
clientCall.cancel();
|
||||
});
|
||||
|
||||
expect(
|
||||
await clientCall.trailers,
|
||||
isEmpty,
|
||||
);
|
||||
|
||||
await expectLater(
|
||||
clientCall,
|
||||
throwsA(
|
||||
isA<GrpcError>().having(
|
||||
(e) => e.codeName,
|
||||
'Test codename',
|
||||
contains('CANCELLED'),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
// Copyright (c) 2024, 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 'package:grpc/grpc.dart';
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
// Copyright (c) 2024, 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:fake_async/fake_async.dart';
|
||||
import 'package:grpc/src/client/client_keepalive.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
|
|
|
@ -1,7 +1,24 @@
|
|||
// Mocks generated by Mockito 5.4.4 from annotations
|
||||
// Copyright (c) 2024, 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.
|
||||
|
||||
// Mocks generated by Mockito 5.4.1 from annotations
|
||||
// in grpc/test/client_tests/client_keepalive_manager_test.dart.
|
||||
// Do not manually edit this file.
|
||||
|
||||
// @dart=2.19
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:mockito/mockito.dart' as _i1;
|
||||
|
||||
|
@ -11,8 +28,6 @@ import 'client_keepalive_manager_test.dart' as _i2;
|
|||
// ignore_for_file: avoid_redundant_argument_values
|
||||
// ignore_for_file: avoid_setters_without_getters
|
||||
// ignore_for_file: comment_references
|
||||
// ignore_for_file: deprecated_member_use
|
||||
// ignore_for_file: deprecated_member_use_from_same_package
|
||||
// ignore_for_file: implementation_imports
|
||||
// ignore_for_file: invalid_use_of_visible_for_testing_member
|
||||
// ignore_for_file: prefer_const_constructors
|
||||
|
@ -32,7 +47,6 @@ class MockPinger extends _i1.Mock implements _i2.Pinger {
|
|||
),
|
||||
returnValueForMissingStub: null,
|
||||
);
|
||||
|
||||
@override
|
||||
void onPingTimeout() => super.noSuchMethod(
|
||||
Invocation.method(
|
||||
|
|
|
@ -13,10 +13,11 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
@TestOn('browser')
|
||||
library;
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:html';
|
||||
|
||||
import 'dart:js_interop';
|
||||
import 'dart:typed_data';
|
||||
import 'package:async/async.dart';
|
||||
import 'package:grpc/src/client/call.dart';
|
||||
import 'package:grpc/src/client/transport/xhr_transport.dart';
|
||||
|
@ -25,12 +26,13 @@ import 'package:grpc/src/shared/status.dart';
|
|||
import 'package:mockito/mockito.dart';
|
||||
import 'package:stream_transform/stream_transform.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:web/web.dart';
|
||||
|
||||
final readyStateChangeEvent =
|
||||
Event('readystatechange', canBubble: false, cancelable: false);
|
||||
Event('readystatechange', EventInit(bubbles: false, cancelable: false));
|
||||
final progressEvent = ProgressEvent('onloadstart');
|
||||
|
||||
class MockHttpRequest extends Mock implements HttpRequest {
|
||||
class MockHttpRequest extends Mock implements IXMLHttpRequest {
|
||||
MockHttpRequest({int? code}) : status = code ?? 200;
|
||||
// ignore: close_sinks
|
||||
StreamController<Event> readyStateChangeController =
|
||||
|
@ -51,6 +53,10 @@ class MockHttpRequest extends Mock implements HttpRequest {
|
|||
@override
|
||||
final int status;
|
||||
|
||||
@override
|
||||
String get responseText =>
|
||||
super.noSuchMethod(Invocation.getter(#responseText), returnValue: '');
|
||||
|
||||
@override
|
||||
int get readyState =>
|
||||
super.noSuchMethod(Invocation.getter(#readyState), returnValue: -1);
|
||||
|
@ -64,13 +70,13 @@ class MockHttpRequest extends Mock implements HttpRequest {
|
|||
class MockXhrClientConnection extends XhrClientConnection {
|
||||
MockXhrClientConnection({int? code})
|
||||
: _statusCode = code ?? 200,
|
||||
super(Uri.parse('test:8080'));
|
||||
super(Uri.parse('test:0'));
|
||||
|
||||
late MockHttpRequest latestRequest;
|
||||
final int _statusCode;
|
||||
|
||||
@override
|
||||
HttpRequest createHttpRequest() {
|
||||
IXMLHttpRequest createHttpRequest() {
|
||||
final request = MockHttpRequest(code: _statusCode);
|
||||
latestRequest = request;
|
||||
return request;
|
||||
|
@ -207,8 +213,8 @@ void main() {
|
|||
await stream.terminate();
|
||||
|
||||
final expectedData = frame(data);
|
||||
expect(verify(connection.latestRequest.send(captureAny)).captured.single,
|
||||
expectedData);
|
||||
verify(
|
||||
connection.latestRequest.send(Uint8List.fromList(expectedData).toJS));
|
||||
});
|
||||
|
||||
test('Stream handles headers properly', () async {
|
||||
|
@ -224,14 +230,13 @@ void main() {
|
|||
(error, _) => fail(error.toString()));
|
||||
|
||||
when(transport.latestRequest.responseHeaders).thenReturn(responseHeaders);
|
||||
when(transport.latestRequest.response)
|
||||
when(transport.latestRequest.responseText)
|
||||
.thenReturn(String.fromCharCodes(frame(<int>[])));
|
||||
|
||||
// Set expectation for request readyState and generate two readyStateChange
|
||||
// events, so that incomingMessages stream completes.
|
||||
final readyStates = [HttpRequest.HEADERS_RECEIVED, HttpRequest.DONE];
|
||||
when(transport.latestRequest.readyState)
|
||||
.thenAnswer((_) => readyStates.removeAt(0));
|
||||
final readyStates = [XMLHttpRequest.HEADERS_RECEIVED, XMLHttpRequest.DONE];
|
||||
when(transport.latestRequest.readyState).thenReturnInOrder(readyStates);
|
||||
transport.latestRequest.readyStateChangeController
|
||||
.add(readyStateChangeEvent);
|
||||
transport.latestRequest.readyStateChangeController
|
||||
|
@ -266,13 +271,12 @@ void main() {
|
|||
final encodedString = String.fromCharCodes(encodedTrailers);
|
||||
|
||||
when(connection.latestRequest.responseHeaders).thenReturn(requestHeaders);
|
||||
when(connection.latestRequest.response).thenReturn(encodedString);
|
||||
when(connection.latestRequest.responseText).thenReturn(encodedString);
|
||||
|
||||
// Set expectation for request readyState and generate events so that
|
||||
// incomingMessages stream completes.
|
||||
final readyStates = [HttpRequest.HEADERS_RECEIVED, HttpRequest.DONE];
|
||||
when(connection.latestRequest.readyState)
|
||||
.thenAnswer((_) => readyStates.removeAt(0));
|
||||
when(connection.latestRequest.readyState).thenReturnInOrder(
|
||||
[XMLHttpRequest.HEADERS_RECEIVED, XMLHttpRequest.DONE]);
|
||||
connection.latestRequest.readyStateChangeController
|
||||
.add(readyStateChangeEvent);
|
||||
connection.latestRequest.progressController.add(progressEvent);
|
||||
|
@ -302,13 +306,11 @@ void main() {
|
|||
final encodedString = String.fromCharCodes(encoded);
|
||||
|
||||
when(connection.latestRequest.responseHeaders).thenReturn(requestHeaders);
|
||||
when(connection.latestRequest.response).thenReturn(encodedString);
|
||||
|
||||
when(connection.latestRequest.responseText).thenReturn(encodedString);
|
||||
// Set expectation for request readyState and generate events so that
|
||||
// incomingMessages stream completes.
|
||||
final readyStates = [HttpRequest.HEADERS_RECEIVED, HttpRequest.DONE];
|
||||
when(connection.latestRequest.readyState)
|
||||
.thenAnswer((_) => readyStates.removeAt(0));
|
||||
when(connection.latestRequest.readyState).thenReturnInOrder(
|
||||
[XMLHttpRequest.HEADERS_RECEIVED, XMLHttpRequest.DONE]);
|
||||
connection.latestRequest.readyStateChangeController
|
||||
.add(readyStateChangeEvent);
|
||||
connection.latestRequest.progressController.add(progressEvent);
|
||||
|
@ -336,14 +338,13 @@ void main() {
|
|||
requestHeaders, (error, _) => fail(error.toString()));
|
||||
final data = List<int>.filled(10, 224);
|
||||
when(connection.latestRequest.responseHeaders).thenReturn(requestHeaders);
|
||||
when(connection.latestRequest.response)
|
||||
when(connection.latestRequest.responseText)
|
||||
.thenReturn(String.fromCharCodes(frame(data)));
|
||||
|
||||
// Set expectation for request readyState and generate events, so that
|
||||
// incomingMessages stream completes.
|
||||
final readyStates = [HttpRequest.HEADERS_RECEIVED, HttpRequest.DONE];
|
||||
when(connection.latestRequest.readyState)
|
||||
.thenAnswer((_) => readyStates.removeAt(0));
|
||||
when(connection.latestRequest.readyState).thenReturnInOrder(
|
||||
[XMLHttpRequest.HEADERS_RECEIVED, XMLHttpRequest.DONE]);
|
||||
connection.latestRequest.readyStateChangeController
|
||||
.add(readyStateChangeEvent);
|
||||
connection.latestRequest.progressController.add(progressEvent);
|
||||
|
@ -368,7 +369,7 @@ void main() {
|
|||
const errorDetails = 'error details';
|
||||
when(connection.latestRequest.responseHeaders)
|
||||
.thenReturn({'content-type': 'application/grpc+proto'});
|
||||
when(connection.latestRequest.readyState).thenReturn(HttpRequest.DONE);
|
||||
when(connection.latestRequest.readyState).thenReturn(XMLHttpRequest.DONE);
|
||||
when(connection.latestRequest.responseText).thenReturn(errorDetails);
|
||||
connection.latestRequest.readyStateChangeController
|
||||
.add(readyStateChangeEvent);
|
||||
|
@ -397,12 +398,12 @@ void main() {
|
|||
|
||||
when(connection.latestRequest.responseHeaders).thenReturn(metadata);
|
||||
when(connection.latestRequest.readyState)
|
||||
.thenReturn(HttpRequest.HEADERS_RECEIVED);
|
||||
.thenReturn(XMLHttpRequest.HEADERS_RECEIVED);
|
||||
|
||||
// At first invocation the response should be the the first message, after
|
||||
// that first + last messages.
|
||||
var first = true;
|
||||
when(connection.latestRequest.response).thenAnswer((_) {
|
||||
when(connection.latestRequest.responseText).thenAnswer((_) {
|
||||
if (first) {
|
||||
first = false;
|
||||
return encodedStrings[0];
|
||||
|
@ -410,7 +411,7 @@ void main() {
|
|||
return encodedStrings[0] + encodedStrings[1];
|
||||
});
|
||||
|
||||
final readyStates = [HttpRequest.HEADERS_RECEIVED, HttpRequest.DONE];
|
||||
final readyStates = [XMLHttpRequest.HEADERS_RECEIVED, XMLHttpRequest.DONE];
|
||||
when(connection.latestRequest.readyState)
|
||||
.thenAnswer((_) => readyStates.removeAt(0));
|
||||
|
||||
|
|
|
@ -13,12 +13,14 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
@TestOn('!browser')
|
||||
library;
|
||||
|
||||
import 'package:grpc/grpc.dart';
|
||||
import 'package:grpc/grpc_or_grpcweb.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
const host = 'example.com';
|
||||
const port = 8080;
|
||||
const port = 0;
|
||||
|
||||
void main() {
|
||||
test('Channel on non-web uses gRPC ClientChannel with correct params', () {
|
||||
|
|
|
@ -13,13 +13,14 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
@TestOn('browser')
|
||||
library;
|
||||
|
||||
import 'package:grpc/grpc_or_grpcweb.dart';
|
||||
import 'package:grpc/grpc_web.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
const host = 'example.com';
|
||||
const port = 8080;
|
||||
const port = 0;
|
||||
|
||||
void main() {
|
||||
test('Channel on web uses GrpcWebClientChannel with correct URI', () {
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
@TestOn('vm')
|
||||
library;
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
|
@ -289,7 +290,7 @@ void main() {
|
|||
}
|
||||
|
||||
GrpcError? interceptor(call, method) {
|
||||
if (method.identifier == 'Unary') {
|
||||
if (method.name == 'Unary') {
|
||||
return null;
|
||||
}
|
||||
return GrpcError.unauthenticated('Request is unauthenticated');
|
||||
|
@ -311,7 +312,7 @@ void main() {
|
|||
|
||||
group('returns error if interceptor blocks request', () {
|
||||
GrpcError? interceptor(call, method) {
|
||||
if (method.identifier == 'Unary') {
|
||||
if (method.name == 'Unary') {
|
||||
return GrpcError.unauthenticated('Request is unauthenticated');
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright (c) 2024, 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')
|
||||
library;
|
||||
|
||||
import 'package:grpc/src/shared/codec.dart';
|
||||
import 'package:grpc/src/shared/message.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group('GRPC Compression Flag', () {
|
||||
test('compression flag 0 with null codec', () {
|
||||
final rawPayload = <int>[1, 2, 3, 4];
|
||||
final Codec? codec = null;
|
||||
final data = frame(rawPayload, codec);
|
||||
expect(data[0], 0);
|
||||
});
|
||||
test('compression flag 0 with grpc-encoding identity', () {
|
||||
final rawPayload = <int>[1, 2, 3, 4];
|
||||
final Codec codec = IdentityCodec();
|
||||
final data = frame(rawPayload, codec);
|
||||
expect(data[0], 0);
|
||||
});
|
||||
test('compression flag 1 with grpc-encoding gzip', () {
|
||||
final rawPayload = <int>[1, 2, 3, 4];
|
||||
final Codec codec = GzipCodec();
|
||||
final data = frame(rawPayload, codec);
|
||||
expect(data[0], 1);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -1,3 +1,18 @@
|
|||
// Copyright (c) 2024, 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:typed_data';
|
||||
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
// Copyright (c) 2024, 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';
|
||||
|
|
|
@ -1,4 +1,21 @@
|
|||
// Copyright (c) 2024, 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')
|
||||
library;
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:math' as math;
|
||||
|
||||
|
|
|
@ -1,4 +1,21 @@
|
|||
// Copyright (c) 2024, 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')
|
||||
library;
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:grpc/grpc.dart';
|
||||
|
@ -15,16 +32,20 @@ void main() {
|
|||
late EchoServiceClient fakeClient;
|
||||
late FakeClientChannel fakeChannel;
|
||||
late EchoServiceClient unresponsiveClient;
|
||||
late ClientChannel unresponsiveChannel;
|
||||
late FakeClientChannel unresponsiveChannel;
|
||||
|
||||
final pingInterval = Duration(milliseconds: 10);
|
||||
final timeout = Duration(milliseconds: 30);
|
||||
final maxBadPings = 5;
|
||||
|
||||
setUp(() async {
|
||||
final serverOptions = ServerKeepAliveOptions(
|
||||
maxBadPings: 5,
|
||||
maxBadPings: maxBadPings,
|
||||
minIntervalBetweenPingsWithoutData: Duration(milliseconds: 10),
|
||||
);
|
||||
final clientOptions = ClientKeepAliveOptions(
|
||||
pingInterval: Duration(milliseconds: 10),
|
||||
timeout: Duration(milliseconds: 30),
|
||||
pingInterval: pingInterval,
|
||||
timeout: timeout,
|
||||
permitWithoutCalls: true,
|
||||
);
|
||||
|
||||
|
@ -32,7 +53,7 @@ void main() {
|
|||
services: [FakeEchoService()],
|
||||
keepAliveOptions: serverOptions,
|
||||
);
|
||||
await server.serve(address: 'localhost', port: 8081);
|
||||
await server.serve(address: 'localhost', port: 0);
|
||||
fakeChannel = FakeClientChannel(
|
||||
'localhost',
|
||||
port: server.port!,
|
||||
|
@ -62,7 +83,7 @@ void main() {
|
|||
test('Server terminates connection after too many pings without data',
|
||||
() async {
|
||||
await fakeClient.echo(EchoRequest());
|
||||
await Future.delayed(Duration(milliseconds: 300));
|
||||
await Future.delayed(timeout * maxBadPings * 2);
|
||||
await fakeClient.echo(EchoRequest());
|
||||
// Check that the server closed the connection, the next request then has
|
||||
// to build a new one.
|
||||
|
@ -71,23 +92,27 @@ void main() {
|
|||
|
||||
test('Server doesnt terminate connection after pings, as data is sent',
|
||||
() async {
|
||||
final timer = Timer.periodic(
|
||||
Duration(milliseconds: 10), (timer) => fakeClient.echo(EchoRequest()));
|
||||
await Future.delayed(Duration(milliseconds: 200), () => timer.cancel());
|
||||
|
||||
// Wait for last request to be sent
|
||||
await Future.delayed(Duration(milliseconds: 20));
|
||||
for (var i = 0; i < 10; i++) {
|
||||
await fakeClient.echo(EchoRequest());
|
||||
await Future.delayed(timeout * 0.2);
|
||||
}
|
||||
|
||||
// Check that the server never closed the connection
|
||||
expect(fakeChannel.newConnectionCounter, 1);
|
||||
});
|
||||
|
||||
test('Server doesnt ack the ping, making the client shutdown the connection',
|
||||
test('Server doesnt ack the ping, making the client shutdown the transport',
|
||||
() async {
|
||||
//Send a first request, get a connection
|
||||
await unresponsiveClient.echo(EchoRequest());
|
||||
await Future.delayed(Duration(milliseconds: 200));
|
||||
await expectLater(
|
||||
unresponsiveClient.echo(EchoRequest()), throwsA(isA<GrpcError>()));
|
||||
expect(unresponsiveChannel.newConnectionCounter, 1);
|
||||
|
||||
//Ping is not being acked on time
|
||||
await Future.delayed(timeout * 2);
|
||||
|
||||
//A second request gets a new connection
|
||||
await unresponsiveClient.echo(EchoRequest());
|
||||
expect(unresponsiveChannel.newConnectionCounter, 2);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -96,7 +121,7 @@ class FakeClientChannel extends ClientChannel {
|
|||
FakeHttp2ClientConnection? fakeHttp2ClientConnection;
|
||||
FakeClientChannel(
|
||||
super.host, {
|
||||
super.port = 443,
|
||||
super.port,
|
||||
super.options = const ChannelOptions(),
|
||||
super.channelShutdownHandler,
|
||||
});
|
||||
|
@ -125,20 +150,23 @@ class FakeHttp2ClientConnection extends Http2ClientConnection {
|
|||
}
|
||||
|
||||
/// A wrapper around a [FakeHttp2ClientConnection]
|
||||
class UnresponsiveClientChannel extends ClientChannel {
|
||||
class UnresponsiveClientChannel extends FakeClientChannel {
|
||||
UnresponsiveClientChannel(
|
||||
super.host, {
|
||||
super.port = 443,
|
||||
super.port,
|
||||
super.options = const ChannelOptions(),
|
||||
super.channelShutdownHandler,
|
||||
});
|
||||
|
||||
@override
|
||||
ClientConnection createConnection() =>
|
||||
UnresponsiveHttp2ClientConnection(host, port, options);
|
||||
ClientConnection createConnection() {
|
||||
fakeHttp2ClientConnection =
|
||||
UnresponsiveHttp2ClientConnection(host, port, options);
|
||||
return fakeHttp2ClientConnection!;
|
||||
}
|
||||
}
|
||||
|
||||
class UnresponsiveHttp2ClientConnection extends Http2ClientConnection {
|
||||
class UnresponsiveHttp2ClientConnection extends FakeHttp2ClientConnection {
|
||||
UnresponsiveHttp2ClientConnection(super.host, super.port, super.options);
|
||||
|
||||
@override
|
||||
|
@ -172,8 +200,6 @@ class FakeEchoService extends EchoServiceBase {
|
|||
|
||||
@override
|
||||
Stream<ServerStreamingEchoResponse> serverStreamingEcho(
|
||||
ServiceCall call, ServerStreamingEchoRequest request) {
|
||||
// TODO: implement serverStreamingEcho
|
||||
throw UnimplementedError();
|
||||
}
|
||||
ServiceCall call, ServerStreamingEchoRequest request) =>
|
||||
throw UnsupportedError('Not used in this test');
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
@TestOn('vm')
|
||||
library;
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
|
|
|
@ -1,4 +1,21 @@
|
|||
// Copyright (c) 2024, 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')
|
||||
library;
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
|
@ -16,13 +33,13 @@ void main() {
|
|||
server = Server.create(services: [FakeEchoService()]);
|
||||
await server.serve(
|
||||
address: 'localhost',
|
||||
port: 8888,
|
||||
port: 0,
|
||||
security: ServerTlsCredentials(
|
||||
certificate: File('test/data/localhost.crt').readAsBytesSync(),
|
||||
privateKey: File('test/data/localhost.key').readAsBytesSync(),
|
||||
),
|
||||
);
|
||||
final proxy = Proxy(host: 'localhost', port: 8080);
|
||||
final proxy = Proxy(host: 'localhost', port: 0);
|
||||
final proxyCAName = '/CN=mitmproxy/O=mitmproxy';
|
||||
|
||||
fakeChannel = ClientChannel(
|
||||
|
|
|
@ -1,4 +1,21 @@
|
|||
// Copyright (c) 2024, 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')
|
||||
library;
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:grpc/grpc.dart';
|
||||
|
@ -13,9 +30,9 @@ void main() {
|
|||
|
||||
setUp(() async {
|
||||
server = Server.create(services: [FakeEchoService()]);
|
||||
await server.serve(address: 'localhost', port: 8888);
|
||||
await server.serve(address: 'localhost', port: 0);
|
||||
|
||||
final proxy = Proxy(host: 'localhost', port: 8080);
|
||||
final proxy = Proxy(host: 'localhost', port: 0);
|
||||
|
||||
fakeChannel = ClientChannel(
|
||||
'localhost',
|
||||
|
|
|
@ -1,4 +1,21 @@
|
|||
// Copyright (c) 2024, 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')
|
||||
library;
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
// limitations under the License.
|
||||
|
||||
@TestOn('vm')
|
||||
library;
|
||||
|
||||
import 'package:grpc/grpc.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
|
@ -45,7 +47,7 @@ void main() {
|
|||
server = Server.create(
|
||||
services: [EchoService()],
|
||||
);
|
||||
await server.serve(address: 'localhost', port: 8081);
|
||||
await server.serve(address: 'localhost', port: 0);
|
||||
channel = ClientChannel(
|
||||
'localhost',
|
||||
port: server.port!,
|
||||
|
|
|
@ -1,4 +1,21 @@
|
|||
// Copyright (c) 2024, 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')
|
||||
library;
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'dart:isolate';
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
// Copyright (c) 2024, 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 'package:fake_async/fake_async.dart';
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
@TestOn('vm')
|
||||
library;
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
|
@ -303,7 +304,7 @@ void main() {
|
|||
}
|
||||
|
||||
GrpcError? interceptor(call, method) {
|
||||
if (method.identifier == 'Unary') {
|
||||
if (method.name == 'Unary') {
|
||||
return null;
|
||||
}
|
||||
return GrpcError.unauthenticated('Request is unauthenticated');
|
||||
|
@ -325,7 +326,7 @@ void main() {
|
|||
|
||||
group('returns error if interceptor blocks request', () {
|
||||
GrpcError? interceptor(call, method) {
|
||||
if (method.identifier == 'Unary') {
|
||||
if (method.name == 'Unary') {
|
||||
return GrpcError.unauthenticated('Request is unauthenticated');
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
// Copyright (c) 2024, 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/shared/codec.dart';
|
||||
import 'package:grpc/src/shared/codec_registry.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
// Mocks generated by Mockito 5.4.4 from annotations
|
||||
// Mocks generated by Mockito 5.4.1 from annotations
|
||||
// in grpc/test/src/client_utils.dart.
|
||||
// Do not manually edit this file.
|
||||
|
||||
// @dart=2.19
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'dart:async' as _i3;
|
||||
|
||||
|
@ -13,8 +15,6 @@ import 'package:mockito/mockito.dart' as _i1;
|
|||
// ignore_for_file: avoid_redundant_argument_values
|
||||
// ignore_for_file: avoid_setters_without_getters
|
||||
// ignore_for_file: comment_references
|
||||
// ignore_for_file: deprecated_member_use
|
||||
// ignore_for_file: deprecated_member_use_from_same_package
|
||||
// ignore_for_file: implementation_imports
|
||||
// ignore_for_file: invalid_use_of_visible_for_testing_member
|
||||
// ignore_for_file: prefer_const_constructors
|
||||
|
@ -57,7 +57,6 @@ class MockClientTransportConnection extends _i1.Mock
|
|||
Invocation.getter(#isOpen),
|
||||
returnValue: false,
|
||||
) as bool);
|
||||
|
||||
@override
|
||||
set onActiveStateChanged(_i2.ActiveStateHandler? callback) =>
|
||||
super.noSuchMethod(
|
||||
|
@ -67,25 +66,21 @@ class MockClientTransportConnection extends _i1.Mock
|
|||
),
|
||||
returnValueForMissingStub: null,
|
||||
);
|
||||
|
||||
@override
|
||||
_i3.Future<void> get onInitialPeerSettingsReceived => (super.noSuchMethod(
|
||||
Invocation.getter(#onInitialPeerSettingsReceived),
|
||||
returnValue: _i3.Future<void>.value(),
|
||||
) as _i3.Future<void>);
|
||||
|
||||
@override
|
||||
_i3.Stream<int> get onPingReceived => (super.noSuchMethod(
|
||||
Invocation.getter(#onPingReceived),
|
||||
returnValue: _i3.Stream<int>.empty(),
|
||||
) as _i3.Stream<int>);
|
||||
|
||||
@override
|
||||
_i3.Stream<void> get onFrameReceived => (super.noSuchMethod(
|
||||
Invocation.getter(#onFrameReceived),
|
||||
returnValue: _i3.Stream<void>.empty(),
|
||||
) as _i3.Stream<void>);
|
||||
|
||||
@override
|
||||
_i2.ClientTransportStream makeRequest(
|
||||
List<_i4.Header>? headers, {
|
||||
|
@ -106,7 +101,6 @@ class MockClientTransportConnection extends _i1.Mock
|
|||
),
|
||||
),
|
||||
) as _i2.ClientTransportStream);
|
||||
|
||||
@override
|
||||
_i3.Future<dynamic> ping() => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
|
@ -115,7 +109,6 @@ class MockClientTransportConnection extends _i1.Mock
|
|||
),
|
||||
returnValue: _i3.Future<dynamic>.value(),
|
||||
) as _i3.Future<dynamic>);
|
||||
|
||||
@override
|
||||
_i3.Future<dynamic> finish() => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
|
@ -124,7 +117,6 @@ class MockClientTransportConnection extends _i1.Mock
|
|||
),
|
||||
returnValue: _i3.Future<dynamic>.value(),
|
||||
) as _i3.Future<dynamic>);
|
||||
|
||||
@override
|
||||
_i3.Future<dynamic> terminate([int? errorCode]) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
|
@ -149,19 +141,16 @@ class MockClientTransportStream extends _i1.Mock
|
|||
Invocation.getter(#peerPushes),
|
||||
returnValue: _i3.Stream<_i2.TransportStreamPush>.empty(),
|
||||
) as _i3.Stream<_i2.TransportStreamPush>);
|
||||
|
||||
@override
|
||||
int get id => (super.noSuchMethod(
|
||||
Invocation.getter(#id),
|
||||
returnValue: 0,
|
||||
) as int);
|
||||
|
||||
@override
|
||||
_i3.Stream<_i2.StreamMessage> get incomingMessages => (super.noSuchMethod(
|
||||
Invocation.getter(#incomingMessages),
|
||||
returnValue: _i3.Stream<_i2.StreamMessage>.empty(),
|
||||
) as _i3.Stream<_i2.StreamMessage>);
|
||||
|
||||
@override
|
||||
_i3.StreamSink<_i2.StreamMessage> get outgoingMessages => (super.noSuchMethod(
|
||||
Invocation.getter(#outgoingMessages),
|
||||
|
@ -170,7 +159,6 @@ class MockClientTransportStream extends _i1.Mock
|
|||
Invocation.getter(#outgoingMessages),
|
||||
),
|
||||
) as _i3.StreamSink<_i2.StreamMessage>);
|
||||
|
||||
@override
|
||||
set onTerminated(void Function(int?)? value) => super.noSuchMethod(
|
||||
Invocation.setter(
|
||||
|
@ -179,7 +167,6 @@ class MockClientTransportStream extends _i1.Mock
|
|||
),
|
||||
returnValueForMissingStub: null,
|
||||
);
|
||||
|
||||
@override
|
||||
void terminate() => super.noSuchMethod(
|
||||
Invocation.method(
|
||||
|
@ -188,7 +175,6 @@ class MockClientTransportStream extends _i1.Mock
|
|||
),
|
||||
returnValueForMissingStub: null,
|
||||
);
|
||||
|
||||
@override
|
||||
void sendHeaders(
|
||||
List<_i4.Header>? headers, {
|
||||
|
@ -202,7 +188,6 @@ class MockClientTransportStream extends _i1.Mock
|
|||
),
|
||||
returnValueForMissingStub: null,
|
||||
);
|
||||
|
||||
@override
|
||||
void sendData(
|
||||
List<int>? bytes, {
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
@TestOn('vm')
|
||||
@Skip(
|
||||
'Run only as `dart run --enable-vm-service --timeline-streams=Dart test/timeline_test.dart`')
|
||||
library;
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:developer' as dev;
|
||||
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
// Copyright (c) 2024, 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 'package:grpc/grpc.dart';
|
||||
|
@ -5,7 +20,7 @@ import 'package:grpc/src/client/http2_connection.dart';
|
|||
import 'package:http2/http2.dart';
|
||||
|
||||
Future<void> main(List<String> args) async {
|
||||
final serverPort = 5678;
|
||||
final serverPort = 0;
|
||||
final proxyPort = int.tryParse(args.first);
|
||||
|
||||
final proxy =
|
||||
|
@ -22,7 +37,7 @@ Future<void> main(List<String> args) async {
|
|||
final incoming =
|
||||
proxy == null ? connector.socket : await connector.connectToProxy(proxy);
|
||||
|
||||
final uri = Uri.parse('http://localhost:8080');
|
||||
final uri = Uri.parse('http://localhost:0');
|
||||
|
||||
final transport =
|
||||
ClientTransportConnection.viaStreams(incoming, connector.socket);
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
// Copyright (c) 2024, 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:io';
|
||||
|
||||
|
|
Loading…
Reference in New Issue