97 Commits

Author SHA1 Message Date
Scott Blum
42f63028d4 Update go.mod, goreleaser for v1.8.8 (#413)
* Update go.mod, goreleaser for v1.8.8

* move ci check to go 1.20

* debug

* ci diff
2023-09-22 16:21:54 -04:00
Valters Jansons
743e60a4c9 Run tests on Go 1.21 (#408)
* Run tests on Go 1.21

For the most part, there are no breaking changes.

However, the expired certificate is now showing "expired certificate"
although previously it showed a simpler "bad certificate" which was
hard-coded into the TLS settings test scenario.

* Simplify condition for certificate error

Instead of two `expired certificate` and `bad certificate` comparisons, we can just check for `certificate` in error output. This satisfies us when checking there is something wrong with the certificate.

Co-authored-by: Scott Blum <dragonsinth@gmail.com>

---------

Co-authored-by: Scott Blum <dragonsinth@gmail.com>
2023-08-31 12:14:34 -04:00
Valters Jansons
b7a5d3bba8 Update protoreflect v1.15.2 and grpc v1.57.0 (#406)
The proposal already exists by Dependabot, but the version bump pulls
in `grpc.reflection.v1.ServerReflection` resulting in minor test change
being required.

Transient dependency `github.com/bufbuild/protocompile` is now added,
and requires at least Go 1.18. This PR includes the version removal.
2023-08-31 12:14:03 -04:00
Valters Jansons
2a29c1e64b Use grpc.reflection.v1.ServerReflection (#407)
The proper `v1` gRPC reflection has been around for a bit.
The "client auto" mechanism still supports falling back to `v1alpha`.
Not many support the `v1`, but we should default to it when possible.
2023-08-31 12:13:33 -04:00
dependabot[bot]
9a59bed1d2 Bump google.golang.org/protobuf from 1.30.0 to 1.31.0 (#401)
Bumps google.golang.org/protobuf from 1.30.0 to 1.31.0.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-26 12:05:13 -04:00
dependabot[bot]
ae7dadff19 Bump google.golang.org/grpc from 1.55.0 to 1.56.1 (#400)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.55.0 to 1.56.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.55.0...v1.56.1)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-26 11:38:28 -04:00
Sophy Cao
3961a33e7f Fix issues with error details (#379)
Co-authored-by: Erik Engberg <ejohansson@spotify.com>
2023-06-22 12:58:51 -04:00
Joshua Humphries
d5b8e4d4ce fix nil-dereference panic (#395) 2023-05-12 12:50:32 -04:00
dependabot[bot]
0efcfa65f2 Bump google.golang.org/grpc from 1.54.0 to 1.55.0 (#390)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.54.0 to 1.55.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.54.0...v1.55.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-09 20:08:41 -04:00
Joshua Humphries
fae58803d9 Add "checkgenerate" make target to CI (#385) 2023-04-18 12:09:16 -04:00
dependabot[bot]
1fda47eb90 Bump google.golang.org/grpc from 1.53.0 to 1.54.0 (#383)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.53.0 to 1.54.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.53.0...v1.54.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-27 10:01:15 -04:00
dependabot[bot]
031cd3d1e7 Bump google.golang.org/protobuf from 1.29.1 to 1.30.0 (#378)
Bumps [google.golang.org/protobuf](https://github.com/protocolbuffers/protobuf-go) from 1.29.1 to 1.30.0.
- [Release notes](https://github.com/protocolbuffers/protobuf-go/releases)
- [Changelog](https://github.com/protocolbuffers/protobuf-go/blob/master/release.bash)
- [Commits](https://github.com/protocolbuffers/protobuf-go/compare/v1.29.1...v1.30.0)

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-20 09:58:32 -04:00
dependabot[bot]
a5037bdf4a Bump google.golang.org/protobuf from 1.29.0 to 1.29.1 (#376)
Bumps [google.golang.org/protobuf](https://github.com/protocolbuffers/protobuf-go) from 1.29.0 to 1.29.1.
- [Release notes](https://github.com/protocolbuffers/protobuf-go/releases)
- [Changelog](https://github.com/protocolbuffers/protobuf-go/blob/master/release.bash)
- [Commits](https://github.com/protocolbuffers/protobuf-go/compare/v1.29.0...v1.29.1)

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-14 23:11:32 +00:00
dependabot[bot]
4775fb574b Bump google.golang.org/protobuf from 1.28.1 to 1.29.0 (#375)
Bumps [google.golang.org/protobuf](https://github.com/protocolbuffers/protobuf-go) from 1.28.1 to 1.29.0.
- [Release notes](https://github.com/protocolbuffers/protobuf-go/releases)
- [Changelog](https://github.com/protocolbuffers/protobuf-go/blob/master/release.bash)
- [Commits](https://github.com/protocolbuffers/protobuf-go/compare/v1.28.1...v1.29.0)

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-13 09:12:47 -04:00
dependabot[bot]
b96cb4ddd0 Bump github.com/golang/protobuf from 1.5.2 to 1.5.3 (#374)
Bumps [github.com/golang/protobuf](https://github.com/golang/protobuf) from 1.5.2 to 1.5.3.
- [Release notes](https://github.com/golang/protobuf/releases)
- [Commits](https://github.com/golang/protobuf/compare/v1.5.2...v1.5.3)

---
updated-dependencies:
- dependency-name: github.com/golang/protobuf
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-13 09:11:31 -04:00
dependabot[bot]
006918123d Bump google.golang.org/grpc from 1.52.3 to 1.53.0 (#370)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.52.3 to 1.53.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.52.3...v1.53.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-13 17:08:49 -05:00
codesee-maps[bot]
66a2405833 Install the CodeSee workflow. Learn more at https://docs.codesee.io (#368)
Co-authored-by: codesee-maps[bot] <86324825+codesee-maps[bot]@users.noreply.github.com>
2023-02-07 15:24:26 -05:00
dependabot[bot]
dfd889a44b Bump google.golang.org/grpc from 1.51.0 to 1.52.3 (#365)
* Bump google.golang.org/grpc from 1.51.0 to 1.52.3

Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.51.0 to 1.52.3.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.51.0...v1.52.3)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* update test assertion for latest version of grpc-go (#366)

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Joshua Humphries <2035234+jhump@users.noreply.github.com>
2023-01-30 20:35:03 -05:00
dependabot[bot]
a3a5bcd8ab Bump github.com/jhump/protoreflect from 1.14.0 to 1.14.1 (#361)
Bumps [github.com/jhump/protoreflect](https://github.com/jhump/protoreflect) from 1.14.0 to 1.14.1.
- [Release notes](https://github.com/jhump/protoreflect/releases)
- [Commits](https://github.com/jhump/protoreflect/compare/v1.14.0...v1.14.1)

---
updated-dependencies:
- dependency-name: github.com/jhump/protoreflect
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-16 09:15:25 -05:00
dependabot[bot]
61a9c00d87 Bump google.golang.org/grpc from 1.50.1 to 1.51.0 (#348)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.50.1 to 1.51.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.50.1...v1.51.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-22 11:01:49 -05:00
cui fliter
85f1cbf7ad fix funcname in comment (#346)
Signed-off-by: cui fliter <imcusg@gmail.com>

Signed-off-by: cui fliter <imcusg@gmail.com>
2022-11-09 07:59:56 -05:00
dependabot[bot]
dd2f60135c Bump github.com/jhump/protoreflect from 1.13.0 to 1.14.0 (#343)
* Bump github.com/jhump/protoreflect from 1.13.0 to 1.14.0

Bumps [github.com/jhump/protoreflect](https://github.com/jhump/protoreflect) from 1.13.0 to 1.14.0.
- [Release notes](https://github.com/jhump/protoreflect/releases)
- [Commits](https://github.com/jhump/protoreflect/compare/v1.13.0...v1.14.0)

---
updated-dependencies:
- dependency-name: github.com/jhump/protoreflect
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix ci

* what can we even build on?

* stop testing old things

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Scott Blum <dragonsinth@gmail.com>
2022-11-01 10:26:55 -04:00
dependabot[bot]
81c624c41f Bump google.golang.org/grpc from 1.50.0 to 1.50.1 (#338)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.50.0 to 1.50.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.50.0...v1.50.1)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-17 12:49:30 -04:00
dependabot[bot]
3826617999 Bump google.golang.org/grpc from 1.49.0 to 1.50.0 (#336)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.49.0 to 1.50.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.49.0...v1.50.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-10 12:31:11 -04:00
dependabot[bot]
8d60b618ac Bump github.com/jhump/protoreflect from 1.12.0 to 1.13.0 (#335)
Bumps [github.com/jhump/protoreflect](https://github.com/jhump/protoreflect) from 1.12.0 to 1.13.0.
- [Release notes](https://github.com/jhump/protoreflect/releases)
- [Commits](https://github.com/jhump/protoreflect/compare/v1.12.0...v1.13.0)

---
updated-dependencies:
- dependency-name: github.com/jhump/protoreflect
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-19 11:26:42 -04:00
dependabot[bot]
47b842a805 Bump google.golang.org/grpc from 1.48.0 to 1.49.0 (#330)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.48.0 to 1.49.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.48.0...v1.49.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-29 09:36:26 -04:00
Scott Blum
898bdad041 fixup release process (#328) 2022-08-10 14:25:13 -04:00
dependabot[bot]
25c896aa59 Bump google.golang.org/protobuf from 1.28.0 to 1.28.1 (#327)
Bumps [google.golang.org/protobuf](https://github.com/protocolbuffers/protobuf-go) from 1.28.0 to 1.28.1.
- [Release notes](https://github.com/protocolbuffers/protobuf-go/releases)
- [Changelog](https://github.com/protocolbuffers/protobuf-go/blob/master/release.bash)
- [Commits](https://github.com/protocolbuffers/protobuf-go/compare/v1.28.0...v1.28.1)

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-08 12:26:59 -04:00
Scott Blum
0d0992e6a2 Add go 1.18 support; set Dockerfile to go 1.18 (#325) 2022-07-25 11:54:27 -04:00
Ben Redmond-Benham
8093376ece build alpine base image (#311) 2022-07-20 14:58:00 -04:00
cui fliter
fec466efa6 fix some typos (#314)
Signed-off-by: cuishuang <imcusg@gmail.com>
2022-07-20 14:57:53 -04:00
dependabot[bot]
7f919e6459 Bump google.golang.org/grpc from 1.47.0 to 1.48.0 (#324)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.47.0 to 1.48.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.47.0...v1.48.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-18 13:22:36 -04:00
ghatwala
0df5c93e8d Adding power(ppc64le) arch support (#296)
Needing power(ppc64le) arch based "grpcurl" binaries here https://docs.openshift.com/container-platform/4.9/operators/admin/olm-restricted-networks.html
1. Adding power support for releases and docker images(multi-arch).

signed-off-by : Amit Ghatwal <ghatwala@us.ibm.com>
2022-06-27 11:10:08 -04:00
Lyubomir Gardev
353e0953cb Enable support for Unix sockets for Windows by enabling -unix flag for Windows builds. (#317) 2022-06-20 09:37:33 -04:00
dependabot[bot]
c9ac3da95f Bump google.golang.org/grpc from 1.46.2 to 1.47.0 (#315)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.46.2 to 1.47.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.46.2...v1.47.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-06 08:08:43 -04:00
dependabot[bot]
ea24a77215 Bump github.com/jhump/protoreflect from 1.10.3 to 1.12.0 (#294)
Bumps [github.com/jhump/protoreflect](https://github.com/jhump/protoreflect) from 1.10.3 to 1.12.0.
- [Release notes](https://github.com/jhump/protoreflect/releases)
- [Commits](https://github.com/jhump/protoreflect/compare/v1.10.3...v1.12.0)

---
updated-dependencies:
- dependency-name: github.com/jhump/protoreflect
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-02 16:18:22 -04:00
dependabot[bot]
c3fbeaff64 Bump google.golang.org/grpc from 1.44.0 to 1.46.2 (#310)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.44.0 to 1.46.2.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.44.0...v1.46.2)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Scott Blum <dragonsinth@gmail.com>
2022-06-02 16:10:40 -04:00
dependabot[bot]
7860209a53 Bump google.golang.org/protobuf from 1.27.1 to 1.28.0 (#298)
Bumps [google.golang.org/protobuf](https://github.com/protocolbuffers/protobuf-go) from 1.27.1 to 1.28.0.
- [Release notes](https://github.com/protocolbuffers/protobuf-go/releases)
- [Changelog](https://github.com/protocolbuffers/protobuf-go/blob/master/release.bash)
- [Commits](https://github.com/protocolbuffers/protobuf-go/compare/v1.27.1...v1.28.0)

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-02 15:56:21 -04:00
Joshua Humphries
b953ea196a use newer goreleaser (#293) 2022-02-15 20:31:31 -05:00
Joshua Humphries
683a7fb09c Restore support for linux/s390x for the next release. (#292)
This reverts commit 8ee6c9423b.
2022-02-15 19:03:59 -05:00
dependabot[bot]
8bb6eeb0d0 Bump google.golang.org/protobuf from 1.26.0 to 1.27.1 (#288)
Bumps [google.golang.org/protobuf](https://github.com/protocolbuffers/protobuf-go) from 1.26.0 to 1.27.1.
- [Release notes](https://github.com/protocolbuffers/protobuf-go/releases)
- [Changelog](https://github.com/protocolbuffers/protobuf-go/blob/master/release.bash)
- [Commits](https://github.com/protocolbuffers/protobuf-go/compare/v1.26.0...v1.27.1)

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-09 14:27:46 -05:00
Joshua Humphries
805e231182 bump protoreflect again, to 1.10.3 (#290) 2022-02-08 16:49:23 -05:00
Joshua Humphries
aa5998a119 no longer supporting go 1.14 (#289) 2022-02-07 12:03:53 -05:00
Jeff Widman
b34b13bab3 Bump grpc lib and fix deprecations (#286)
* Bump google.golang.org/grpc from 1.37.0 to 1.44.0

Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.37.0 to 1.44.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.37.0...v1.44.0)

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-05 10:28:05 -05:00
Jeff Widman
b890db745f Bump protobuf lib and fix deprecation warnings (#285)
* Bump github.com/golang/protobuf from 1.4.2 to 1.5.2

Bumps [github.com/golang/protobuf](https://github.com/golang/protobuf) from 1.4.2 to 1.5.2.
- [Release notes](https://github.com/golang/protobuf/releases)
- [Commits](https://github.com/golang/protobuf/compare/v1.4.2...v1.5.2)

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---

* Also pulls along update of golang.google.org/protobuf to v1.26
* Fix deprecation warnings about `ptypes` package
2022-02-04 17:19:52 -05:00
Vladyslav Shalamai
57a2cd1a09 bump github.com/jhump/protoreflect from v1.10.1 to v1.10.2 (#284) 2022-02-04 10:15:18 -05:00
wwuck
ae7473c7a7 add dependabot configuration (#267) 2022-01-12 09:57:41 -05:00
Joshua Humphries
b3f576068c update golang.org/x/text to v0.3.7 (#275) 2022-01-10 15:18:54 -05:00
Joshua Humphries
8ee6c9423b can't build s390x docker images; skip for now (#265) 2021-10-07 16:37:41 -04:00
Joshua Humphries
4b65b3ee55 fix release script: 'docker buildx create' step needs to be re-runnable without error (#264) 2021-10-07 16:10:47 -04:00
Jeffrey Duce
9ac7e3a34d set value of creds instead of creating new variable (#263) 2021-10-07 15:49:59 -04:00
Joshua Humphries
76bbedeed0 invoking client-streaming RPC can panic (#262) 2021-10-07 14:55:12 -04:00
Joshua Humphries
b9d2d8cfa8 cleanup deps; pin versions of tools using 'go install' instead of in go.mod; tidy up go.sum (#260)
Addresses two depend-a-bot security warnings for libraries previously references in go.sum.
2021-10-06 20:58:00 -04:00
Bjarne Sievers
30b8cd1531 Add info about docker pitfalls to README (#258) 2021-10-06 15:25:18 -04:00
Joshua Humphries
a8f79c8751 use latest protoreflect (#259) 2021-10-06 09:39:01 -04:00
Joshua Humphries
bf9b13d6c5 update install from source directions to work with Go 1.16 2021-09-23 10:37:13 -04:00
Joshua Humphries
c3bde04cc1 use circleci instead of travis (#256) 2021-09-23 09:20:48 -04:00
Namrata Bhave
2e9ba5024e Build multiarch docker images for release: amd, s390x, arm (#251) 2021-09-23 07:55:01 -04:00
Igor
127194b205 Support SSLKEYLOGFILE environment variable for key logging (#245) 2021-09-20 11:53:44 -04:00
Namrata Bhave
cd242fe1ed build release binaries for linux/s390x (#248) 2021-08-18 08:53:40 -04:00
Sunil Thorat
59a32e5eb0 Upgrade to using golang 1.15 to build (#240) 2021-07-14 10:24:01 -04:00
Joshua Humphries
7e1cd16164 use newer protoreflect, v1.9.0 (#242) 2021-07-13 11:53:16 -04:00
Joshua Humphries
de25c89822 allow callers of BlockingDial to override grpc.FailOnNonTempDialError dial option (#241) 2021-07-12 15:27:33 -04:00
Joshua Humphries
f1d396c31e freshen README, point to 3rd party packages for install (#229) 2021-05-04 12:03:54 -04:00
Josh Humphries
1986364acd make go.sum authoritative 2021-04-30 17:15:18 -04:00
Erik Johansson
bdf97bc934 Bump grpc-go to 1.37.0 (#230)
Pulls in support for XDS v3
2021-04-29 10:48:41 -04:00
Z. Liu
2f55ac63a4 release binaries for arm64 (#220) 2021-04-02 08:06:16 -04:00
Joshua Humphries
8d7770a962 use latest version of protoreflect (#212) 2021-02-22 17:32:40 -05:00
Leonhard Markert
1f34448998 Help text for "-H" option: remove duplicated word (#207) 2021-02-01 10:31:49 -05:00
Josh Humphries
06a970022e darwin/386... 🤦 2021-01-05 12:42:15 -05:00
Josh Humphries
db90ec1160 go 1.15 no longer supports darwin/386; ignore any IDE config folder 2021-01-05 12:39:34 -05:00
Mikhail Katychev
9da71fbe53 when -format-error option is used, format service reflection errors, too (#188) 2020-09-30 13:24:46 -04:00
Guilherme Salazar
9846afccbc feat: add support for user-agent header (#182) 2020-09-04 11:31:28 -04:00
Joshua Humphries
ba5f667e13 fix latest CI breakages by forking code from grpc-go's interop/testing
Also moves testing package to internal/testing
2020-08-31 14:44:59 -04:00
Joshua Humphries
54ffdcacda fix typo 2020-08-24 13:58:09 -04:00
Joshua Humphries
ceef817807 make use of -plaintext flag more clear in examples 2020-08-24 13:56:57 -04:00
Sergei Vorobev
e544b9e66f Print size of the message in very verbose mode (#181)
Adds -vv flag for "very verbose".
Includes estimated message size when enabled. The size is an estimate because it is the canonical size for the proto message, but not necessarily its actual on-the-wire size.
2020-08-14 11:02:42 -04:00
Joshua Humphries
41a6ac0479 no more support for go 1.11 without modules (#180) 2020-07-31 12:26:31 -04:00
Joshua Humphries
f37ec641c5 make release work... (#179) 2020-07-30 22:10:03 -04:00
Adam Babik
8e51c5e2d3 cmd/grpcurl: add -allow-unknown-fields option (#147) 2020-07-23 10:54:06 -04:00
Joshua Humphries
8376c2f7bb update go get line in README
Go tool needs to also gets dependencies for sub-packages
2020-07-20 12:46:55 -04:00
Joshua Humphries
0162fa9726 go.mod and Makefile tweaks; move import of xds package to cmd/grpcurl (#170) 2020-07-14 12:20:32 -04:00
Erik Johansson
b8c67b7a4e Bump grpc-go to 1.30.0 (#168)
* Bump grpc-go to 1.30.0
* Import new xds package instead of experimental

Co-authored-by: Erik Johansson <ejohansson@spotify.com>
2020-07-13 13:16:48 -04:00
Joshua Humphries
ff114930fd update travis badge and link 2020-07-09 20:53:23 -04:00
Joshua Humphries
5ad5edb29c pin goreleaser in go.mod; fix config file so latest version accepts it; allow using go modules in 'make release' (#161) 2020-06-01 18:56:18 -04:00
Joshua Humphries
44547153b3 unpin Go point release and alpine version in Dockerfile (#162) 2020-05-15 11:40:32 -04:00
Joshua Humphries
2108c8f0b3 use go 1.13 to build docker image (#160) 2020-05-15 08:21:08 -04:00
Mikhail Katychev
36008aa111 Add -format-error option (#155) 2020-05-14 20:40:13 -04:00
Joshua Humphries
50833f1b21 upgrade deps; remove go 1.14 from go.mod (#158) 2020-05-14 20:00:04 -04:00
Joshua Humphries
939766fb42 Go tip does not like using string(i) where i untyped int (#159) 2020-05-14 19:38:08 -04:00
Joshua Humphries
b58182a88d get travis CI green again (#157)
* fix test to work w/ newer grpc repo; run 'make ci' to have it update go.mod and go.sum, trying to repro ci failure locally
* vet w/ go 1.13; use normal go proxy instead of direct in CI
2020-05-12 13:06:14 -04:00
Serge Bazanski
8e2cf9b3c2 fix crash when emitting empty messages in text format (#153) 2020-04-23 16:20:45 -04:00
Alexander Chiu
36f9e53dfd Allow extra descriptor sources in reflection mode (#146)
Allows descriptors or proto files to be supplied that are used as an additional descriptor source when server reflection is used. This is needed to resolve message types embedded in an Any message, that the server has no knowledge of, as well as extensions that the server has no knowledge of.
2020-04-20 15:42:11 -04:00
Joshua Humphries
bfbbed1d42 vet with modules (#150)
fixes CI failures caused by newer version of dependency introducing new deprecations that cause staticcheck violations
2020-04-16 15:27:01 -04:00
Johan Brandhorst
153d36db8c Remove golang/protobuf/jsonpbtest dep (#145)
With 1.4.0 the golang/protobuf json testing protofiles
are being moved to [an internal package][1]. While this is
technically a breaking change, I doubt the maintainers
are going to reintroduce it, so I've copied the necessary
parts to our own testing protofile.

This allows users of this package and, more importantly,
grpcui to try 1.4.0 without this package having to migrate yet.
When it comes to migrating to 1.4.0, this should also make the
transition easier.

[1]: https://github.com/golang/protobuf/tree/v1.4.0-rc.4/internal/testprotos
2020-04-03 12:45:05 -04:00
Joshua Humphries
2af40876fc drop Go 1.9 and 1.10 from CI; add 1.13 and 1.14 (#144) 2020-04-01 09:02:40 -04:00
Joshua Humphries
0218a7db67 add script and readme for creating new releases (#140) 2020-03-18 08:51:18 -04:00
77 changed files with 6045 additions and 2985 deletions

47
.circleci/config.yml Normal file
View File

@@ -0,0 +1,47 @@
shared_configs:
simple_job_steps: &simple_job_steps
- checkout
- run:
name: Run tests
command: |
make test
# Use the latest 2.1 version of CircleCI pipeline process engine. See: https://circleci.com/docs/2.0/configuration-reference
version: 2.1
jobs:
build-1-18:
working_directory: ~/repo
docker:
- image: cimg/go:1.18
steps: *simple_job_steps
build-1-19:
working_directory: ~/repo
docker:
- image: cimg/go:1.19
steps: *simple_job_steps
build-1-20:
working_directory: ~/repo
docker:
- image: cimg/go:1.20
steps:
- checkout
- run:
name: Run tests and linters
command: |
make ci
build-1-21:
working_directory: ~/repo
docker:
- image: cimg/go:1.21
steps: *simple_job_steps
workflows:
pr-build-test:
jobs:
- build-1-18
- build-1-19
- build-1-20
- build-1-21

7
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,7 @@
version: 2
updates:
- package-ecosystem: "gomod"
directory: "/"
# Check for updates once a week
schedule:
interval: "weekly"

View File

@@ -0,0 +1,22 @@
# This workflow was added by CodeSee. Learn more at https://codesee.io/
# This is v2.0 of this workflow file
on:
push:
branches:
- master
pull_request_target:
types: [opened, synchronize, reopened]
name: CodeSee
permissions: read-all
jobs:
codesee:
runs-on: ubuntu-latest
continue-on-error: true
name: Analyze the repo with CodeSee
steps:
- uses: Codesee-io/codesee-action@v2
with:
codesee-token: ${{ secrets.CODESEE_ARCH_DIAG_API_TOKEN }}

2
.gitignore vendored
View File

@@ -1,2 +1,4 @@
dist/
.idea/
VERSION
.tmp/

View File

@@ -8,17 +8,33 @@ builds:
goarch:
- amd64
- 386
- arm64
- s390x
- ppc64le
ignore:
- goos: darwin
goarch: 386
- goos: windows
goarch: arm64
- goos: darwin
goarch: s390x
- goos: windows
goarch: s390x
- goos: darwin
goarch: ppc64le
- goos: windows
goarch: ppc64le
ldflags:
- -s -w -X main.version=v{{.Version}}
archive:
format: tar.gz
format_overrides:
- goos: windows
format: zip
replacements:
amd64: x86_64
386: x86_32
darwin: osx
files:
- LICENSE
archives:
- format: tar.gz
format_overrides:
- goos: windows
format: zip
replacements:
amd64: x86_64
386: x86_32
darwin: osx
files:
- LICENSE

View File

@@ -1,21 +0,0 @@
language: go
sudo: false
matrix:
include:
- go: 1.9.x
- go: 1.10.x
- go: 1.11.x
env:
- GO111MODULE=off
- VET=1
- go: 1.11.x
env: GO111MODULE=on
- go: 1.12.x
env: GO111MODULE=off
- go: 1.12.x
env: GO111MODULE=on
- go: tip
script:
- if [[ "$VET" = 1 ]]; then make ci; else make deps test; fi

View File

@@ -1,10 +1,6 @@
FROM golang:1.11.10-alpine as builder
FROM golang:1.18-alpine as builder
MAINTAINER FullStory Engineering
# currently, a module build requires gcc (so Go tool can build
# module-aware versions of std library; it ships only w/ the
# non-module versions)
RUN apk update && apk add --no-cache ca-certificates git gcc g++ libc-dev
# create non-privileged group and user
RUN addgroup -S grpcurl && adduser -S grpcurl -G grpcurl
@@ -15,13 +11,20 @@ COPY cmd /tmp/fullstorydev/grpcurl/cmd
# and build a completely static binary (so we can use
# scratch as basis for the final image)
ENV CGO_ENABLED=0
ENV GOOS=linux
ENV GOARCH=amd64
ENV GO111MODULE=on
RUN go build -o /grpcurl \
-ldflags "-w -extldflags \"-static\" -X \"main.version=$(cat VERSION)\"" \
./cmd/grpcurl
FROM alpine:3 as alpine
WORKDIR /
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=builder /etc/passwd /etc/passwd
COPY --from=builder /grpcurl /bin/grpcurl
USER grpcurl
ENTRYPOINT ["/bin/grpcurl"]
# New FROM so we have a nice'n'tiny image
FROM scratch
WORKDIR /

View File

@@ -1,12 +1,16 @@
dev_build_version=$(shell git describe --tags --always --dirty)
export PATH := $(shell pwd)/.tmp/protoc/bin:$(PATH)
export PROTOC_VERSION := 22.0
# TODO: run golint and errcheck, but only to catch *new* violations and
# decide whether to change code or not (e.g. we need to be able to whitelist
# violations already in the code). They can be useful to catch errors, but
# they are just too noisy to be a requirement for a CI -- we don't even *want*
# to fix some of the things they consider to be violations.
.PHONY: ci
ci: deps checkgofmt vet staticcheck ineffassign predeclared test
ci: deps checkgofmt checkgenerate vet staticcheck ineffassign predeclared test
.PHONY: deps
deps:
@@ -22,8 +26,8 @@ install:
.PHONY: release
release:
@GO111MODULE=off go get github.com/goreleaser/goreleaser
goreleaser --rm-dist
@go install github.com/goreleaser/goreleaser@v1.10.0
goreleaser release --rm-dist
.PHONY: docker
docker:
@@ -31,6 +35,20 @@ docker:
docker build -t fullstorydev/grpcurl:$(dev_build_version) .
@rm VERSION
.PHONY: generate
generate: .tmp/protoc/bin/protoc
@go install google.golang.org/protobuf/cmd/protoc-gen-go@a709e31e5d12
@go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1.0
go generate ./...
.PHONY: checkgenerate
checkgenerate: generate
git status --porcelain
@if [ -n "$$(git status --porcelain)" ]; then \
git diff; \
exit 1; \
fi
.PHONY: checkgofmt
checkgofmt:
gofmt -s -l .
@@ -42,41 +60,37 @@ checkgofmt:
vet:
go vet ./...
# TODO: remove the ignored check; need it for now because it
# is complaining about a deprecated comment added to grpc,
# but it's not yet released. Once the new (non-deprecated)
# API is included in a release, we can move to that new
# version and fix the call site to no longer use deprecated
# method.
# This all works fine with Go modules, but without modules,
# CI is just getting latest master for dependencies like grpc.
.PHONY: staticcheck
staticcheck:
@go get honnef.co/go/tools/cmd/staticcheck
@go install honnef.co/go/tools/cmd/staticcheck@v0.4.3
staticcheck ./...
.PHONY: ineffassign
ineffassign:
@go get github.com/gordonklaus/ineffassign
@go install github.com/gordonklaus/ineffassign@7953dde2c7bf
ineffassign .
.PHONY: predeclared
predeclared:
@go get github.com/nishanths/predeclared
predeclared .
@go install github.com/nishanths/predeclared@5f2f810c9ae6
predeclared ./...
# Intentionally omitted from CI, but target here for ad-hoc reports.
.PHONY: golint
golint:
@go get golang.org/x/lint/golint
@go install golang.org/x/lint/golint@v0.0.0-20210508222113-6edffad5e616
golint -min_confidence 0.9 -set_exit_status ./...
# Intentionally omitted from CI, but target here for ad-hoc reports.
.PHONY: errcheck
errcheck:
@go get github.com/kisielk/errcheck
@go install github.com/kisielk/errcheck@v1.2.0
errcheck ./...
.PHONY: test
test:
go test -race ./...
.tmp/protoc/bin/protoc: ./Makefile ./download_protoc.sh
./download_protoc.sh

View File

@@ -1,5 +1,5 @@
# gRPCurl
[![Build Status](https://travis-ci.org/fullstorydev/grpcurl.svg?branch=master)](https://travis-ci.org/fullstorydev/grpcurl/branches)
[![Build Status](https://circleci.com/gh/fullstorydev/grpcurl/tree/master.svg?style=svg)](https://circleci.com/gh/fullstorydev/grpcurl/tree/master)
[![Go Report Card](https://goreportcard.com/badge/github.com/fullstorydev/grpcurl)](https://goreportcard.com/report/github.com/fullstorydev/grpcurl)
`grpcurl` is a command-line tool that lets you interact with gRPC servers. It's
@@ -14,7 +14,7 @@ This program accepts messages using JSON encoding, which is much more friendly f
humans and scripts.
With this tool you can also browse the schema for gRPC services, either by querying
a server that supports [server reflection](https://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1alpha/reflection.proto),
a server that supports [server reflection](https://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1/reflection.proto),
by reading proto source files, or by loading in compiled "protoset" files (files that contain
encoded file [descriptor protos](https://github.com/google/protobuf/blob/master/src/google/protobuf/descriptor.proto)).
In fact, the way the tool transforms JSON request data into a binary encoded protobuf
@@ -35,9 +35,9 @@ See also the [`grpcurl` talk at GopherCon 2018](https://www.youtube.com/watch?v=
operate bi-directional streaming methods interactively by running `grpcurl` from an
interactive terminal and using stdin as the request body!
`grpcurl` supports both plain-text and TLS servers and has numerous options for TLS
configuration. It also supports mutual TLS, where the client is required to present a
client certificate.
`grpcurl` supports both secure/TLS servers _and_ plain-text servers (i.e. no TLS) and has
numerous options for TLS configuration. It also supports mutual TLS, where the client is
required to present a client certificate.
As mentioned above, `grpcurl` works seamlessly if the server supports the reflection
service. If not, you can supply the `.proto` source files or you can supply protoset
@@ -49,32 +49,57 @@ files (containing compiled descriptors, produced by `protoc`) to `grpcurl`.
Download the binary from the [releases](https://github.com/fullstorydev/grpcurl/releases) page.
### Homebrew (macOS)
On macOS, `grpcurl` is available via Homebrew:
```shell
brew install grpcurl
```
### From Source
You can use the `go` tool to install `grpcurl`:
### Docker
For platforms that support Docker, you can download an image that lets you run `grpcurl`:
```shell
go get github.com/fullstorydev/grpcurl
go install github.com/fullstorydev/grpcurl/cmd/grpcurl
# Download image
docker pull fullstorydev/grpcurl:latest
# Run the tool
docker run fullstorydev/grpcurl api.grpc.me:443 list
```
Note that there are some pitfalls when using docker:
- If you need to interact with a server listening on the host's loopback network, you must specify the host as `host.docker.internal` instead of `localhost` (for Mac or Windows) _OR_ have the container use the host network with `-network="host"` (Linux only).
- If you need to provide proto source files or descriptor sets, you must mount the folder containing the files as a volume (`-v $(pwd):/protos`) and adjust the import paths to container paths accordingly.
- If you want to provide the request message via stdin, using the `-d @` option, you need to use the `-i` flag on the docker command.
### Other Packages
There are numerous other ways to install `grpcurl`, thanks to support from third parties that
have created recipes/packages for it. These include other ways to install `grpcurl` on a variety
of environments, including Windows and myriad Linux distributions.
You can see more details and the full list of other packages for `grpcurl` at _repology.org_:
https://repology.org/project/grpcurl/information
### From Source
If you already have the [Go SDK](https://golang.org/doc/install) installed, you can use the `go`
tool to install `grpcurl`:
```shell
go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest
```
This installs the command into the `bin` sub-folder of wherever your `$GOPATH`
environment variable points. If this directory is already in your `$PATH`, then
you should be good to go.
environment variable points. (If you have no `GOPATH` environment variable set,
the default install location is `$HOME/go/bin`). If this directory is already in
your `$PATH`, then you should be good to go.
If you have already pulled down this repo to a location that is not in your
`$GOPATH` and want to build from the sources, you can `cd` into the repo and then
run `make install`.
If you encounter compile errors, you could have out-dated versions of `grpcurl`'s
dependencies. You can update the dependencies by running `make updatedeps`. You can
also use [`vgo`](https://github.com/golang/vgo) to install, which will use the right
versions of dependencies. Or, if you are using Go 1.11, you can add `GO111MODULE=on`
as a prefix to the commands above, which will also build using the right versions of
dependencies (vs. whatever you may already in your `GOPATH`).
If you encounter compile errors and are using a version of the Go SDK older than 1.13,
you could have out-dated versions of `grpcurl`'s dependencies. You can update the
dependencies by running `make updatedeps`. Or, if you are using Go 1.11 or 1.12, you
can add `GO111MODULE=on` as a prefix to the commands above, which will also build using
the right versions of dependencies (vs. whatever you may already have in your `GOPATH`).
## Usage
The usage doc for the tool explains the numerous options:
@@ -91,6 +116,9 @@ that requires no client certs and supports server reflection is the simplest thi
do with `grpcurl`. This minimal invocation sends an empty request body:
```shell
grpcurl grpc.server.com:443 my.custom.server.Service/Method
# no TLS
grpcurl -plaintext grpc.server.com:80 my.custom.server.Service/Method
```
To send a non-empty request, use the `-d` argument. Note that all arguments must come
@@ -164,7 +192,7 @@ are needed to use them.
### Server Reflection
Without any additional command-line flags, `grpcurl` will try to use [server reflection](https://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1alpha/reflection.proto).
Without any additional command-line flags, `grpcurl` will try to use [server reflection](https://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1/reflection.proto).
Examples for how to set up server reflection can be found [here](https://github.com/grpc/grpc/blob/master/doc/server-reflection.md#known-implementations).

View File

@@ -1,3 +1,4 @@
//go:build go1.10
// +build go1.10
package main

View File

@@ -1,3 +1,4 @@
//go:build !go1.10
// +build !go1.10
package main

View File

@@ -4,31 +4,42 @@
package main
import (
"context"
"flag"
"fmt"
"io"
"os"
"path/filepath"
"strconv"
"strings"
"time"
"github.com/fullstorydev/grpcurl"
descpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
"github.com/jhump/protoreflect/desc"
"github.com/jhump/protoreflect/grpcreflect"
"golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/keepalive"
"google.golang.org/grpc/metadata"
reflectpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/descriptorpb"
// Register gzip compressor so compressed responses will work:
// Register gzip compressor so compressed responses will work
_ "google.golang.org/grpc/encoding/gzip"
// Register xds so xds and xds-experimental resolver schemes work
_ "google.golang.org/grpc/xds"
"github.com/fullstorydev/grpcurl"
)
var version = "dev build <no version set>"
// To avoid confusion between program error codes and the gRPC resonse
// status codes 'Cancelled' and 'Unknown', 1 and 2 respectively,
// the response status codes emitted use an offest of 64
const statusCodeOffset = 64
const noVersion = "dev build <no version set>"
var version = noVersion
var (
exit = os.Exit
@@ -76,6 +87,10 @@ var (
is used, this will also be used as the server name when verifying the
server's certificate. It defaults to the address that is provided in the
positional arguments.`))
userAgent = flags.String("user-agent", "", prettify(`
If set, the specified value will be added to the User-Agent header set
by the grpc-go library.
`))
data = flags.String("d", "", prettify(`
Data for request contents. If the value is '@' then the request contents
are read from stdin. For calls that accept a stream of requests, the
@@ -91,9 +106,16 @@ var (
ASCII character: 0x1E. The stream should not end in a record separator.
If it does, it will be interpreted as a final, blank message after the
separator.`))
allowUnknownFields = flags.Bool("allow-unknown-fields", false, prettify(`
When true, the request contents, if 'json' format is used, allows
unknown fields to be present. They will be ignored when parsing
the request.`))
connectTimeout = flags.Float64("connect-timeout", 0, prettify(`
The maximum time, in seconds, to wait for connection to be established.
Defaults to 10 seconds.`))
formatError = flags.Bool("format-error", false, prettify(`
When a non-zero status is returned, format the response using the
value set by the -format flag .`))
keepaliveTime = flags.Float64("keepalive-time", 0, prettify(`
If present, the maximum idle time in seconds, after which a keepalive
probe is sent. If the connection remains idle and no keepalive response
@@ -119,6 +141,8 @@ var (
When describing messages, show a template of input data.`))
verbose = flags.Bool("v", false, prettify(`
Enable verbose output.`))
veryVerbose = flags.Bool("vv", false, prettify(`
Enable very verbose output.`))
serverName = flags.String("servername", "", prettify(`
Override server name when validating TLS certificate. This flag is
ignored if -plaintext or -insecure is used.
@@ -126,13 +150,14 @@ var (
an error to use both -authority and -servername (though this will be
permitted if they are both set to the same value, to increase backwards
compatibility with earlier releases that allowed both to be set).`))
reflection = optionalBoolFlag{val: true}
)
func init() {
flags.Var(&addlHeaders, "H", prettify(`
Additional headers in 'name: value' format. May specify more than one
via multiple flags. These headers will also be included in reflection
requests requests to a server.`))
requests to a server.`))
flags.Var(&rpcHeaders, "rpc-header", prettify(`
Additional RPC headers in 'name: value' format. May specify more than
one via multiple flags. These headers will *only* be used when invoking
@@ -168,6 +193,12 @@ func init() {
order given. If no import paths are given, all files (including all
imports) must be provided as -proto flags, and grpcurl will attempt to
resolve all import statements from the set of file names given.`))
flags.Var(&reflection, "use-reflection", prettify(`
When true, server reflection will be used to determine the RPC schema.
Defaults to true unless a -proto or -protoset option is provided. If
-use-reflection is used in combination with a -proto or -protoset flag,
the provided descriptor sources will be used in addition to server
reflection to resolve messages and extensions.`))
}
type multiString []string
@@ -181,6 +212,49 @@ func (s *multiString) Set(value string) error {
return nil
}
// Uses a file source as a fallback for resolving symbols and extensions, but
// only uses the reflection source for listing services
type compositeSource struct {
reflection grpcurl.DescriptorSource
file grpcurl.DescriptorSource
}
func (cs compositeSource) ListServices() ([]string, error) {
return cs.reflection.ListServices()
}
func (cs compositeSource) FindSymbol(fullyQualifiedName string) (desc.Descriptor, error) {
d, err := cs.reflection.FindSymbol(fullyQualifiedName)
if err == nil {
return d, nil
}
return cs.file.FindSymbol(fullyQualifiedName)
}
func (cs compositeSource) AllExtensionsForType(typeName string) ([]*desc.FieldDescriptor, error) {
exts, err := cs.reflection.AllExtensionsForType(typeName)
if err != nil {
// On error fall back to file source
return cs.file.AllExtensionsForType(typeName)
}
// Track the tag numbers from the reflection source
tags := make(map[int32]bool)
for _, ext := range exts {
tags[ext.GetNumber()] = true
}
fileExts, err := cs.file.AllExtensionsForType(typeName)
if err != nil {
return exts, nil
}
for _, ext := range fileExts {
// Prioritize extensions found via reflection
if !tags[ext.GetNumber()] {
exts = append(exts, ext)
}
}
return exts, nil
}
func main() {
flags.Usage = usage
flags.Parse(os.Args[1:])
@@ -219,7 +293,7 @@ func main() {
fail(nil, "The -cert and -key arguments must be used together and both be present.")
}
if *format != "json" && *format != "text" {
fail(nil, "The -format option must be 'json' or 'text.")
fail(nil, "The -format option must be 'json' or 'text'.")
}
if *emitDefaults && *format != "json" {
warn("The -emit-defaults is only used when using json format.")
@@ -250,6 +324,14 @@ func main() {
invoke = true
}
verbosityLevel := 0
if *verbose {
verbosityLevel = 1
}
if *veryVerbose {
verbosityLevel = 2
}
var symbol string
if invoke {
if len(args) == 0 {
@@ -288,11 +370,21 @@ func main() {
if len(importPaths) > 0 && len(protoFiles) == 0 {
warn("The -import-path argument is not used unless -proto files are used.")
}
if !reflection.val && len(protoset) == 0 && len(protoFiles) == 0 {
fail(nil, "No protoset files or proto files specified and -use-reflection set to false.")
}
// Protoset or protofiles provided and -use-reflection unset
if !reflection.set && (len(protoset) > 0 || len(protoFiles) > 0) {
reflection.val = false
}
ctx := context.Background()
if *maxTime > 0 {
timeout := time.Duration(*maxTime * float64(time.Second))
ctx, _ = context.WithTimeout(ctx, timeout)
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, timeout)
defer cancel()
}
dial := func() *grpc.ClientConn {
@@ -315,12 +407,22 @@ func main() {
}
var creds credentials.TransportCredentials
if !*plaintext {
var err error
creds, err = grpcurl.ClientTransportCredentials(*insecure, *cacert, *cert, *key)
tlsConf, err := grpcurl.ClientTLSConfig(*insecure, *cacert, *cert, *key)
if err != nil {
fail(err, "Failed to configure transport credentials")
fail(err, "Failed to create TLS config")
}
sslKeylogFile := os.Getenv("SSLKEYLOGFILE")
if sslKeylogFile != "" {
w, err := os.OpenFile(sslKeylogFile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0600)
if err != nil {
fail(err, "Could not open SSLKEYLOGFILE %s", sslKeylogFile)
}
tlsConf.KeyLogWriter = w
}
creds = credentials.NewTLS(tlsConf)
// can use either -servername or -authority; but not both
if *serverName != "" && *authority != "" {
if *serverName == *authority {
@@ -335,13 +437,21 @@ func main() {
}
if overrideName != "" {
if err := creds.OverrideServerName(overrideName); err != nil {
fail(err, "Failed to override server name as %q", overrideName)
}
opts = append(opts, grpc.WithAuthority(overrideName))
}
} else if *authority != "" {
opts = append(opts, grpc.WithAuthority(*authority))
}
grpcurlUA := "grpcurl/" + version
if version == noVersion {
grpcurlUA = "grpcurl/dev-build (no version set)"
}
if *userAgent != "" {
grpcurlUA = *userAgent + " " + grpcurlUA
}
opts = append(opts, grpc.WithUserAgent(grpcurlUA))
network := "tcp"
if isUnixSocket != nil && isUnixSocket() {
network = "unix"
@@ -352,6 +462,13 @@ func main() {
}
return cc
}
printFormattedStatus := func(w io.Writer, stat *status.Status, formatter grpcurl.Formatter) {
formattedStatus, err := formatter(stat.Proto())
if err != nil {
fmt.Fprintf(w, "ERROR: %v", err.Error())
}
fmt.Fprint(w, formattedStatus)
}
if *expandHeaders {
var err error
@@ -372,24 +489,33 @@ func main() {
var cc *grpc.ClientConn
var descSource grpcurl.DescriptorSource
var refClient *grpcreflect.Client
var fileSource grpcurl.DescriptorSource
if len(protoset) > 0 {
var err error
descSource, err = grpcurl.DescriptorSourceFromProtoSets(protoset...)
fileSource, err = grpcurl.DescriptorSourceFromProtoSets(protoset...)
if err != nil {
fail(err, "Failed to process proto descriptor sets.")
}
} else if len(protoFiles) > 0 {
var err error
descSource, err = grpcurl.DescriptorSourceFromProtoFiles(importPaths, protoFiles...)
fileSource, err = grpcurl.DescriptorSourceFromProtoFiles(importPaths, protoFiles...)
if err != nil {
fail(err, "Failed to process proto source files.")
}
} else {
}
if reflection.val {
md := grpcurl.MetadataFromHeaders(append(addlHeaders, reflHeaders...))
refCtx := metadata.NewOutgoingContext(ctx, md)
cc = dial()
refClient = grpcreflect.NewClient(refCtx, reflectpb.NewServerReflectionClient(cc))
descSource = grpcurl.DescriptorSourceFromServer(ctx, refClient)
refClient = grpcreflect.NewClientAuto(refCtx, cc)
reflSource := grpcurl.DescriptorSourceFromServer(ctx, refClient)
if fileSource != nil {
descSource = compositeSource{reflSource, fileSource}
} else {
descSource = reflSource
}
} else {
descSource = fileSource
}
// arrange for the RPCs to be cleanly shutdown
@@ -487,7 +613,7 @@ func main() {
} else {
// see if it's a group
for _, f := range parent.GetFields() {
if f.GetType() == descpb.FieldDescriptorProto_TYPE_GROUP && f.GetMessageType() == d {
if f.GetType() == descriptorpb.FieldDescriptorProto_TYPE_GROUP && f.GetMessageType() == d {
// found it: describe the map field instead
elementType = "the type of a group field"
dsc = f
@@ -498,7 +624,7 @@ func main() {
}
case *desc.FieldDescriptor:
elementType = "a field"
if d.GetType() == descpb.FieldDescriptorProto_TYPE_GROUP {
if d.GetType() == descriptorpb.FieldDescriptorProto_TYPE_GROUP {
elementType = "a group field"
} else if d.IsExtension() {
elementType = "an extension"
@@ -529,7 +655,8 @@ func main() {
// for messages, also show a template in JSON, to make it easier to
// create a request to invoke an RPC
tmpl := grpcurl.MakeTemplate(dsc)
_, formatter, err := grpcurl.RequestParserAndFormatterFor(grpcurl.Format(*format), descSource, true, false, nil)
options := grpcurl.FormatOptions{EmitJSONDefaultFields: true}
_, formatter, err := grpcurl.RequestParserAndFormatter(grpcurl.Format(*format), descSource, nil, options)
if err != nil {
fail(err, "Failed to construct formatter for %q", *format)
}
@@ -560,16 +687,29 @@ func main() {
// if not verbose output, then also include record delimiters
// between each message, so output could potentially be piped
// to another grpcurl process
includeSeparators := !*verbose
rf, formatter, err := grpcurl.RequestParserAndFormatterFor(grpcurl.Format(*format), descSource, *emitDefaults, includeSeparators, in)
includeSeparators := verbosityLevel == 0
options := grpcurl.FormatOptions{
EmitJSONDefaultFields: *emitDefaults,
IncludeTextSeparator: includeSeparators,
AllowUnknownFields: *allowUnknownFields,
}
rf, formatter, err := grpcurl.RequestParserAndFormatter(grpcurl.Format(*format), descSource, in, options)
if err != nil {
fail(err, "Failed to construct request parser and formatter for %q", *format)
}
h := grpcurl.NewDefaultEventHandler(os.Stdout, descSource, formatter, *verbose)
h := &grpcurl.DefaultEventHandler{
Out: os.Stdout,
Formatter: formatter,
VerbosityLevel: verbosityLevel,
}
err = grpcurl.InvokeRPC(ctx, descSource, cc, symbol, append(addlHeaders, rpcHeaders...), h, rf.Next)
if err != nil {
fail(err, "Error invoking method %q", symbol)
if errStatus, ok := status.FromError(err); ok && *formatError {
h.Status = errStatus
} else {
fail(err, "Error invoking method %q", symbol)
}
}
reqSuffix := ""
respSuffix := ""
@@ -580,12 +720,16 @@ func main() {
if h.NumResponses != 1 {
respSuffix = "s"
}
if *verbose {
if verbosityLevel > 0 {
fmt.Printf("Sent %d request%s and received %d response%s\n", reqCount, reqSuffix, h.NumResponses, respSuffix)
}
if h.Status.Code() != codes.OK {
grpcurl.PrintStatus(os.Stderr, h.Status, formatter)
exit(1)
if *formatError {
printFormattedStatus(os.Stderr, h.Status, formatter)
} else {
grpcurl.PrintStatus(os.Stderr, h.Status, formatter)
}
exit(statusCodeOffset + int(h.Status.Code()))
}
}
}
@@ -672,3 +816,28 @@ func writeProtoset(descSource grpcurl.DescriptorSource, symbols ...string) error
defer f.Close()
return grpcurl.WriteProtoset(f, descSource, symbols...)
}
type optionalBoolFlag struct {
set, val bool
}
func (f *optionalBoolFlag) String() string {
if !f.set {
return "unset"
}
return strconv.FormatBool(f.val)
}
func (f *optionalBoolFlag) Set(s string) error {
v, err := strconv.ParseBool(s)
if err != nil {
return err
}
f.set = true
f.val = v
return nil
}
func (f *optionalBoolFlag) IsBoolFlag() bool {
return true
}

View File

@@ -1,4 +1,5 @@
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || windows
// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
package main

View File

@@ -1,21 +1,21 @@
package grpcurl
import (
"context"
"errors"
"fmt"
"io"
"io/ioutil"
"sync"
"github.com/golang/protobuf/proto"
descpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
"github.com/golang/protobuf/proto" //lint:ignore SA1019 we have to import this because it appears in exported API
"github.com/jhump/protoreflect/desc"
"github.com/jhump/protoreflect/desc/protoparse"
"github.com/jhump/protoreflect/dynamic"
"github.com/jhump/protoreflect/grpcreflect"
"golang.org/x/net/context"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/descriptorpb"
)
// ErrReflectionNotSupported is returned by DescriptorSource operations that
@@ -39,13 +39,13 @@ type DescriptorSource interface {
// DescriptorSourceFromProtoSets creates a DescriptorSource that is backed by the named files, whose contents
// are encoded FileDescriptorSet protos.
func DescriptorSourceFromProtoSets(fileNames ...string) (DescriptorSource, error) {
files := &descpb.FileDescriptorSet{}
files := &descriptorpb.FileDescriptorSet{}
for _, fileName := range fileNames {
b, err := ioutil.ReadFile(fileName)
if err != nil {
return nil, fmt.Errorf("could not load protoset file %q: %v", fileName, err)
}
var fs descpb.FileDescriptorSet
var fs descriptorpb.FileDescriptorSet
err = proto.Unmarshal(b, &fs)
if err != nil {
return nil, fmt.Errorf("could not parse contents of protoset file %q: %v", fileName, err)
@@ -76,8 +76,8 @@ func DescriptorSourceFromProtoFiles(importPaths []string, fileNames ...string) (
}
// DescriptorSourceFromFileDescriptorSet creates a DescriptorSource that is backed by the FileDescriptorSet.
func DescriptorSourceFromFileDescriptorSet(files *descpb.FileDescriptorSet) (DescriptorSource, error) {
unresolved := map[string]*descpb.FileDescriptorProto{}
func DescriptorSourceFromFileDescriptorSet(files *descriptorpb.FileDescriptorSet) (DescriptorSource, error) {
unresolved := map[string]*descriptorpb.FileDescriptorProto{}
for _, fd := range files.File {
unresolved[fd.GetName()] = fd
}
@@ -91,7 +91,7 @@ func DescriptorSourceFromFileDescriptorSet(files *descpb.FileDescriptorSet) (Des
return &fileSource{files: resolved}, nil
}
func resolveFileDescriptor(unresolved map[string]*descpb.FileDescriptorProto, resolved map[string]*desc.FileDescriptor, filename string) (*desc.FileDescriptor, error) {
func resolveFileDescriptor(unresolved map[string]*descriptorpb.FileDescriptorProto, resolved map[string]*desc.FileDescriptor, filename string) (*desc.FileDescriptor, error) {
if r, ok := resolved[filename]; ok {
return r, nil
}
@@ -275,12 +275,12 @@ func WriteProtoset(out io.Writer, descSource DescriptorSource, symbols ...string
// now expand that to include transitive dependencies in topologically sorted
// order (such that file always appears after its dependencies)
expandedFiles := make(map[string]struct{}, len(fds))
allFilesSlice := make([]*descpb.FileDescriptorProto, 0, len(fds))
allFilesSlice := make([]*descriptorpb.FileDescriptorProto, 0, len(fds))
for _, filename := range filenames {
allFilesSlice = addFilesToSet(allFilesSlice, expandedFiles, fds[filename])
}
// now we can serialize to file
b, err := proto.Marshal(&descpb.FileDescriptorSet{File: allFilesSlice})
b, err := proto.Marshal(&descriptorpb.FileDescriptorSet{File: allFilesSlice})
if err != nil {
return fmt.Errorf("failed to serialize file descriptor set: %v", err)
}
@@ -290,7 +290,7 @@ func WriteProtoset(out io.Writer, descSource DescriptorSource, symbols ...string
return nil
}
func addFilesToSet(allFiles []*descpb.FileDescriptorProto, expanded map[string]struct{}, fd *desc.FileDescriptor) []*descpb.FileDescriptorProto {
func addFilesToSet(allFiles []*descriptorpb.FileDescriptorProto, expanded map[string]struct{}, fd *desc.FileDescriptor) []*descriptorpb.FileDescriptorProto {
if _, ok := expanded[fd.GetName()]; ok {
// already seen this one
return allFiles

View File

@@ -5,21 +5,21 @@ import (
"io/ioutil"
"testing"
"github.com/golang/protobuf/proto"
"github.com/golang/protobuf/protoc-gen-go/descriptor"
"github.com/golang/protobuf/proto" //lint:ignore SA1019 we have to import this because it appears in exported API
"google.golang.org/protobuf/types/descriptorpb"
)
func TestWriteProtoset(t *testing.T) {
exampleProtoset, err := loadProtoset("./testing/example.protoset")
exampleProtoset, err := loadProtoset("./internal/testing/example.protoset")
if err != nil {
t.Fatalf("failed to load example.protoset: %v", err)
}
testProtoset, err := loadProtoset("./testing/test.protoset")
testProtoset, err := loadProtoset("./internal/testing/test.protoset")
if err != nil {
t.Fatalf("failed to load test.protoset: %v", err)
}
mergedProtoset := &descriptor.FileDescriptorSet{
mergedProtoset := &descriptorpb.FileDescriptorSet{
File: append(exampleProtoset.File, testProtoset.File...),
}
@@ -29,29 +29,29 @@ func TestWriteProtoset(t *testing.T) {
}
checkWriteProtoset(t, descSrc, exampleProtoset, "TestService")
checkWriteProtoset(t, descSrc, testProtoset, "grpc.testing.TestService")
checkWriteProtoset(t, descSrc, mergedProtoset, "TestService", "grpc.testing.TestService")
checkWriteProtoset(t, descSrc, testProtoset, "testing.TestService")
checkWriteProtoset(t, descSrc, mergedProtoset, "TestService", "testing.TestService")
}
func loadProtoset(path string) (*descriptor.FileDescriptorSet, error) {
func loadProtoset(path string) (*descriptorpb.FileDescriptorSet, error) {
b, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
var protoset descriptor.FileDescriptorSet
var protoset descriptorpb.FileDescriptorSet
if err := proto.Unmarshal(b, &protoset); err != nil {
return nil, err
}
return &protoset, nil
}
func checkWriteProtoset(t *testing.T, descSrc DescriptorSource, protoset *descriptor.FileDescriptorSet, symbols ...string) {
func checkWriteProtoset(t *testing.T, descSrc DescriptorSource, protoset *descriptorpb.FileDescriptorSet, symbols ...string) {
var buf bytes.Buffer
if err := WriteProtoset(&buf, descSrc, symbols...); err != nil {
t.Fatalf("failed to write protoset: %v", err)
}
var result descriptor.FileDescriptorSet
var result descriptorpb.FileDescriptorSet
if err := proto.Unmarshal(buf.Bytes(), &result); err != nil {
t.Fatalf("failed to unmarshal written protoset: %v", err)
}

35
download_protoc.sh Executable file
View File

@@ -0,0 +1,35 @@
#!/usr/bin/env bash
set -e
cd $(dirname $0)
if [[ -z "$PROTOC_VERSION" ]]; then
echo "Set PROTOC_VERSION env var to indicate the version to download" >&2
exit 1
fi
PROTOC_OS="$(uname -s)"
PROTOC_ARCH="$(uname -m)"
case "${PROTOC_OS}" in
Darwin) PROTOC_OS="osx" ;;
Linux) PROTOC_OS="linux" ;;
*)
echo "Invalid value for uname -s: ${PROTOC_OS}" >&2
exit 1
esac
# This is for macs with M1 chips. Precompiled binaries for osx/amd64 are not available for download, so for that case
# we download the x86_64 version instead. This will work as long as rosetta2 is installed.
if [ "$PROTOC_OS" = "osx" ] && [ "$PROTOC_ARCH" = "arm64" ]; then
PROTOC_ARCH="x86_64"
fi
PROTOC="${PWD}/.tmp/protoc/bin/protoc"
if [[ "$(${PROTOC} --version 2>/dev/null)" != "libprotoc 3.${PROTOC_VERSION}" ]]; then
rm -rf ./.tmp/protoc
mkdir -p .tmp/protoc
curl -L "https://github.com/google/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-${PROTOC_OS}-${PROTOC_ARCH}.zip" > .tmp/protoc/protoc.zip
pushd ./.tmp/protoc && unzip protoc.zip && popd
fi

169
format.go
View File

@@ -11,8 +11,8 @@ import (
"strings"
"sync"
"github.com/golang/protobuf/jsonpb"
"github.com/golang/protobuf/proto"
"github.com/golang/protobuf/jsonpb" //lint:ignore SA1019 we have to import this because it appears in exported API
"github.com/golang/protobuf/proto" //lint:ignore SA1019 we have to import this because it appears in exported API
"github.com/jhump/protoreflect/desc"
"github.com/jhump/protoreflect/dynamic"
"google.golang.org/grpc/codes"
@@ -55,6 +55,15 @@ func NewJSONRequestParser(in io.Reader, resolver jsonpb.AnyResolver) RequestPars
}
}
// NewJSONRequestParserWithUnmarshaler is like NewJSONRequestParser but
// accepts a protobuf jsonpb.Unmarshaler instead of jsonpb.AnyResolver.
func NewJSONRequestParserWithUnmarshaler(in io.Reader, unmarshaler jsonpb.Unmarshaler) RequestParser {
return &jsonRequestParser{
dec: json.NewDecoder(in),
unmarshaler: unmarshaler,
}
}
func (f *jsonRequestParser) Next(m proto.Message) error {
var msg json.RawMessage
if err := f.dec.Decode(&msg); err != nil {
@@ -69,7 +78,7 @@ func (f *jsonRequestParser) NumRequests() int {
}
const (
textSeparatorChar = 0x1e
textSeparatorChar = '\x1e'
)
type textRequestParser struct {
@@ -127,10 +136,25 @@ type Formatter func(proto.Message) (string, error)
func NewJSONFormatter(emitDefaults bool, resolver jsonpb.AnyResolver) Formatter {
marshaler := jsonpb.Marshaler{
EmitDefaults: emitDefaults,
Indent: " ",
AnyResolver: resolver,
}
return marshaler.MarshalToString
// Workaround for indentation issue in jsonpb with Any messages.
// Bug was originally fixed in https://github.com/golang/protobuf/pull/834
// but later re-introduced before the module was deprecated and frozen.
// If jsonpb is ever replaced with google.golang.org/protobuf/encoding/protojson
// this workaround will no longer be needed.
formatter := func(message proto.Message) (string, error) {
output, err := marshaler.MarshalToString(message)
if err != nil {
return "", err
}
var buf bytes.Buffer
if err := json.Indent(&buf, []byte(output), "", " "); err != nil {
return "", err
}
return buf.String(), nil
}
return formatter
}
// NewTextFormatter returns a formatter that returns strings in the protobuf
@@ -179,7 +203,7 @@ func (tf *textFormatter) format(m proto.Message) (string, error) {
// no trailing newline needed
str := buf.String()
if str[len(str)-1] == '\n' {
if len(str) > 0 && str[len(str)-1] == '\n' {
str = str[:len(str)-1]
}
@@ -188,10 +212,20 @@ func (tf *textFormatter) format(m proto.Message) (string, error) {
return str, nil
}
// Format of request data. The allowed values are 'json' or 'text'.
type Format string
const (
// FormatJSON specifies input data in JSON format. Multiple request values
// may be concatenated (messages with a JSON representation other than
// object must be separated by whitespace, such as a newline)
FormatJSON = Format("json")
// FormatText specifies input data must be in the protobuf text format.
// Multiple request values must be separated by the "record separator"
// ASCII character: 0x1E. The stream should not end in a record separator.
// If it does, it will be interpreted as a final, blank message after the
// separator.
FormatText = Format("text")
)
@@ -255,11 +289,11 @@ func (r *anyResolver) Resolve(typeUrl string) (proto.Message, error) {
if !ok {
return nil, fmt.Errorf("unknown message: %s", typeUrl)
}
// populate any extensions for this message, too
if exts, err := r.source.AllExtensionsForType(mname); err != nil {
return nil, err
} else if err := r.er.AddExtension(exts...); err != nil {
return nil, err
// populate any extensions for this message, too (if there are any)
if exts, err := r.source.AllExtensionsForType(mname); err == nil {
if err := r.er.AddExtension(exts...); err != nil {
return nil, err
}
}
if r.mf == nil {
@@ -296,6 +330,7 @@ func (r anyResolverWithFallback) Resolve(typeUrl string) (proto.Message, error)
if slash := strings.LastIndex(mname, "/"); slash >= 0 {
mname = mname[slash+1:]
}
//lint:ignore SA1019 new non-deprecated API requires other code changes; deferring...
mt := proto.MessageType(mname)
if mt != nil {
return reflect.New(mt.Elem()).Interface().(proto.Message), nil
@@ -342,31 +377,70 @@ func (a *unknownAny) ProtoMessage() {
var _ proto.Message = (*unknownAny)(nil)
// FormatOptions is a set of flags that are passed to a JSON or text formatter.
type FormatOptions struct {
// EmitJSONDefaultFields flag, when true, includes empty/default values in the output.
// FormatJSON only flag.
EmitJSONDefaultFields bool
// AllowUnknownFields is an option for the parser. When true,
// it accepts input which includes unknown fields. These unknown fields
// are skipped instead of returning an error.
// FormatJSON only flag.
AllowUnknownFields bool
// IncludeTextSeparator is true then, when invoked to format multiple messages,
// all messages after the first one will be prefixed with the
// ASCII 'Record Separator' character (0x1E).
// It might be useful when the output is piped to another grpcurl process.
// FormatText only flag.
IncludeTextSeparator bool
}
// RequestParserAndFormatter returns a request parser and formatter for the
// given format. The given descriptor source may be used for parsing message
// data (if needed by the format).
// It accepts a set of options. The field EmitJSONDefaultFields and IncludeTextSeparator
// are options for JSON and protobuf text formats, respectively. The AllowUnknownFields field
// is a JSON-only format flag.
// Requests will be parsed from the given in.
func RequestParserAndFormatter(format Format, descSource DescriptorSource, in io.Reader, opts FormatOptions) (RequestParser, Formatter, error) {
switch format {
case FormatJSON:
resolver := AnyResolverFromDescriptorSource(descSource)
unmarshaler := jsonpb.Unmarshaler{AnyResolver: resolver, AllowUnknownFields: opts.AllowUnknownFields}
return NewJSONRequestParserWithUnmarshaler(in, unmarshaler), NewJSONFormatter(opts.EmitJSONDefaultFields, anyResolverWithFallback{AnyResolver: resolver}), nil
case FormatText:
return NewTextRequestParser(in), NewTextFormatter(opts.IncludeTextSeparator), nil
default:
return nil, nil, fmt.Errorf("unknown format: %s", format)
}
}
// RequestParserAndFormatterFor returns a request parser and formatter for the
// given format. The given descriptor source may be used for parsing message
// data (if needed by the format). The flags emitJSONDefaultFields and
// includeTextSeparator are options for JSON and protobuf text formats,
// respectively. Requests will be parsed from the given in.
// This function is deprecated. Please use RequestParserAndFormatter instead.
// DEPRECATED
func RequestParserAndFormatterFor(format Format, descSource DescriptorSource, emitJSONDefaultFields, includeTextSeparator bool, in io.Reader) (RequestParser, Formatter, error) {
switch format {
case FormatJSON:
resolver := AnyResolverFromDescriptorSource(descSource)
return NewJSONRequestParser(in, resolver), NewJSONFormatter(emitJSONDefaultFields, anyResolverWithFallback{AnyResolver: resolver}), nil
case FormatText:
return NewTextRequestParser(in), NewTextFormatter(includeTextSeparator), nil
default:
return nil, nil, fmt.Errorf("unknown format: %s", format)
}
return RequestParserAndFormatter(format, descSource, in, FormatOptions{
EmitJSONDefaultFields: emitJSONDefaultFields,
IncludeTextSeparator: includeTextSeparator,
})
}
// DefaultEventHandler logs events to a writer. This is not thread-safe, but is
// safe for use with InvokeRPC as long as NumResponses and Status are not read
// until the call to InvokeRPC completes.
type DefaultEventHandler struct {
out io.Writer
descSource DescriptorSource
formatter func(proto.Message) (string, error)
verbose bool
Out io.Writer
Formatter Formatter
// 0 = default
// 1 = verbose
// 2 = very verbose
VerbosityLevel int
// NumResponses is the number of responses that have been received.
NumResponses int
@@ -378,54 +452,65 @@ type DefaultEventHandler struct {
// NewDefaultEventHandler returns an InvocationEventHandler that logs events to
// the given output. If verbose is true, all events are logged. Otherwise, only
// response messages are logged.
//
// Deprecated: NewDefaultEventHandler exists for compatibility.
// It doesn't allow fine control over the `VerbosityLevel`
// and provides only 0 and 1 options (which corresponds to the `verbose` argument).
// Use DefaultEventHandler{} initializer directly.
func NewDefaultEventHandler(out io.Writer, descSource DescriptorSource, formatter Formatter, verbose bool) *DefaultEventHandler {
verbosityLevel := 0
if verbose {
verbosityLevel = 1
}
return &DefaultEventHandler{
out: out,
descSource: descSource,
formatter: formatter,
verbose: verbose,
Out: out,
Formatter: formatter,
VerbosityLevel: verbosityLevel,
}
}
var _ InvocationEventHandler = (*DefaultEventHandler)(nil)
func (h *DefaultEventHandler) OnResolveMethod(md *desc.MethodDescriptor) {
if h.verbose {
txt, err := GetDescriptorText(md, h.descSource)
if h.VerbosityLevel > 0 {
txt, err := GetDescriptorText(md, nil)
if err == nil {
fmt.Fprintf(h.out, "\nResolved method descriptor:\n%s\n", txt)
fmt.Fprintf(h.Out, "\nResolved method descriptor:\n%s\n", txt)
}
}
}
func (h *DefaultEventHandler) OnSendHeaders(md metadata.MD) {
if h.verbose {
fmt.Fprintf(h.out, "\nRequest metadata to send:\n%s\n", MetadataToString(md))
if h.VerbosityLevel > 0 {
fmt.Fprintf(h.Out, "\nRequest metadata to send:\n%s\n", MetadataToString(md))
}
}
func (h *DefaultEventHandler) OnReceiveHeaders(md metadata.MD) {
if h.verbose {
fmt.Fprintf(h.out, "\nResponse headers received:\n%s\n", MetadataToString(md))
if h.VerbosityLevel > 0 {
fmt.Fprintf(h.Out, "\nResponse headers received:\n%s\n", MetadataToString(md))
}
}
func (h *DefaultEventHandler) OnReceiveResponse(resp proto.Message) {
h.NumResponses++
if h.verbose {
fmt.Fprint(h.out, "\nResponse contents:\n")
if h.VerbosityLevel > 1 {
fmt.Fprintf(h.Out, "\nEstimated response size: %d bytes\n", proto.Size(resp))
}
if respStr, err := h.formatter(resp); err != nil {
fmt.Fprintf(h.out, "Failed to format response message %d: %v\n", h.NumResponses, err)
if h.VerbosityLevel > 0 {
fmt.Fprint(h.Out, "\nResponse contents:\n")
}
if respStr, err := h.Formatter(resp); err != nil {
fmt.Fprintf(h.Out, "Failed to format response message %d: %v\n", h.NumResponses, err)
} else {
fmt.Fprintln(h.out, respStr)
fmt.Fprintln(h.Out, respStr)
}
}
func (h *DefaultEventHandler) OnReceiveTrailers(stat *status.Status, md metadata.MD) {
h.Status = stat
if h.verbose {
fmt.Fprintf(h.out, "\nResponse trailers received:\n%s\n", MetadataToString(md))
if h.VerbosityLevel > 0 {
fmt.Fprintf(h.Out, "\nResponse trailers received:\n%s\n", MetadataToString(md))
}
}

View File

@@ -7,15 +7,15 @@ import (
"strings"
"testing"
"github.com/golang/protobuf/jsonpb"
"github.com/golang/protobuf/proto"
"github.com/golang/protobuf/ptypes/struct"
"github.com/golang/protobuf/jsonpb" //lint:ignore SA1019 we have to import this because it appears in exported API
"github.com/golang/protobuf/proto" //lint:ignore SA1019 we have to import this because it appears in exported API
"github.com/jhump/protoreflect/desc"
"google.golang.org/grpc/metadata"
"google.golang.org/protobuf/types/known/structpb"
)
func TestRequestParser(t *testing.T) {
source, err := DescriptorSourceFromProtoSets("testing/example.protoset")
source, err := DescriptorSourceFromProtoSets("internal/testing/example.protoset")
if err != nil {
t.Fatalf("failed to create descriptor source: %v", err)
}
@@ -69,7 +69,7 @@ func TestRequestParser(t *testing.T) {
for i, tc := range testCases {
name := fmt.Sprintf("#%d, %s, %d message(s)", i+1, tc.format, len(tc.expectedOutput))
rf, _, err := RequestParserAndFormatterFor(tc.format, source, false, false, strings.NewReader(tc.input))
rf, _, err := RequestParserAndFormatter(tc.format, source, strings.NewReader(tc.input), FormatOptions{})
if err != nil {
t.Errorf("Failed to create parser and formatter: %v", err)
continue
@@ -97,7 +97,7 @@ func TestRequestParser(t *testing.T) {
// Handler prints response data (and headers/trailers in verbose mode).
// This verifies that we get the right output in both JSON and proto text modes.
func TestHandler(t *testing.T) {
source, err := DescriptorSourceFromProtoSets("testing/example.protoset")
source, err := DescriptorSourceFromProtoSets("internal/testing/example.protoset")
if err != nil {
t.Fatalf("failed to create descriptor source: %v", err)
}
@@ -120,20 +120,26 @@ func TestHandler(t *testing.T) {
for _, format := range []Format{FormatJSON, FormatText} {
for _, numMessages := range []int{1, 3} {
for _, verbose := range []bool{true, false} {
for verbosityLevel := 0; verbosityLevel <= 2; verbosityLevel++ {
name := fmt.Sprintf("%s, %d message(s)", format, numMessages)
if verbose {
name += ", verbose"
if verbosityLevel > 0 {
name += fmt.Sprintf(", verbosityLevel=%d", verbosityLevel)
}
_, formatter, err := RequestParserAndFormatterFor(format, source, false, !verbose, nil)
verbose := verbosityLevel > 0
_, formatter, err := RequestParserAndFormatter(format, source, nil, FormatOptions{IncludeTextSeparator: !verbose})
if err != nil {
t.Errorf("Failed to create parser and formatter: %v", err)
continue
}
var buf bytes.Buffer
h := NewDefaultEventHandler(&buf, source, formatter, verbose)
h := &DefaultEventHandler{
Out: &buf,
Formatter: formatter,
VerbosityLevel: verbosityLevel,
}
h.OnResolveMethod(md)
h.OnSendHeaders(reqHeaders)
@@ -148,6 +154,9 @@ func TestHandler(t *testing.T) {
expectedOutput += verbosePrefix
}
for i := 0; i < numMessages; i++ {
if verbosityLevel > 1 {
expectedOutput += verboseResponseSize
}
if verbose {
expectedOutput += verboseResponseHeader
}
@@ -226,6 +235,9 @@ Response trailers received:
a: 1
b: 2
c: 3
`
verboseResponseSize = `
Estimated response size: 100 bytes
`
verboseResponseHeader = `
Response contents:

31
go.mod
View File

@@ -1,8 +1,31 @@
module github.com/fullstorydev/grpcurl
go 1.18
require (
github.com/golang/protobuf v1.3.5
github.com/jhump/protoreflect v1.5.0
golang.org/x/net v0.0.0-20190311183353-d8887717615a
google.golang.org/grpc v1.28.0
github.com/golang/protobuf v1.5.3
github.com/jhump/protoreflect v1.15.2
google.golang.org/grpc v1.57.0
google.golang.org/protobuf v1.31.0
)
require (
cloud.google.com/go/compute v1.19.1 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
github.com/bufbuild/protocompile v0.6.0 // indirect
github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe // indirect
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 // indirect
github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f // indirect
github.com/envoyproxy/protoc-gen-validate v0.10.1 // indirect
golang.org/x/net v0.9.0 // indirect
golang.org/x/oauth2 v0.7.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/text v0.9.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect
)

80
go.sum
View File

@@ -1,58 +1,106 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY=
cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE=
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/bufbuild/protocompile v0.6.0 h1:Uu7WiSQ6Yj9DbkdnOe7U4mNKp58y9WDMKDn28/ZlunY=
github.com/bufbuild/protocompile v0.6.0/go.mod h1:YNP35qEYoYGme7QMtz5SBCoN4kL4g12jTtjuzRNdjpE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g=
github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe h1:QQ3GSy+MqSHxm/d8nCtnAiZdYFd45cYZPs8vOOIYKfk=
github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k=
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f h1:7T++XKzy4xg7PKy+bM+Sa9/oe1OC88yz2hXQUISoXfA=
github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8=
github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/jhump/protoreflect v1.5.0 h1:NgpVT+dX71c8hZnxHof2M7QDK7QtohIJ7DYycjnkyfc=
github.com/jhump/protoreflect v1.5.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
github.com/jhump/protoreflect v1.15.2 h1:7YppbATX94jEt9KLAc5hICx4h6Yt3SaavhQRsIUEHP0=
github.com/jhump/protoreflect v1.15.2/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g=
golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54 h1:9NWlQfY2ePejTmfwUH1OWwmznFa+0kKcHGPDvcPza9M=
google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk=
google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9 h1:m8v1xLLLzMe1m5P+gCTF8nJB9epwZQUBERm20Oy1poQ=
google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 h1:0nDDozoAU19Qb2HwhXadU8OcsiO/09cnTqhUtq2MEOM=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw=
google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@@ -8,6 +8,7 @@ package grpcurl
import (
"bytes"
"context"
"crypto/tls"
"crypto/x509"
"encoding/base64"
@@ -20,19 +21,19 @@ import (
"sort"
"strings"
"github.com/golang/protobuf/proto"
descpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
"github.com/golang/protobuf/ptypes"
"github.com/golang/protobuf/ptypes/empty"
"github.com/golang/protobuf/ptypes/struct"
"github.com/golang/protobuf/proto" //lint:ignore SA1019 we have to import this because it appears in exported API
"github.com/jhump/protoreflect/desc"
"github.com/jhump/protoreflect/desc/protoprint"
"github.com/jhump/protoreflect/dynamic"
"golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/metadata"
_ "google.golang.org/grpc/xds/experimental"
protov2 "google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/descriptorpb"
"google.golang.org/protobuf/types/known/anypb"
"google.golang.org/protobuf/types/known/emptypb"
"google.golang.org/protobuf/types/known/structpb"
)
// ListServices uses the given descriptor source to return a sorted list of fully-qualified
@@ -328,7 +329,7 @@ func fetchAllExtensions(source DescriptorSource, ext *dynamic.ExtensionRegistry,
return nil
}
// fullConvertToDynamic attempts to convert the given message to a dynamic message as well
// fullyConvertToDynamic attempts to convert the given message to a dynamic message as well
// as any nested messages it may contain as field values. If the given message factory has
// extensions registered that were not known when the given message was parsed, this effectively
// allows re-parsing to identify those extensions.
@@ -406,8 +407,9 @@ func makeTemplate(md *desc.MessageDescriptor, path []*desc.MessageDescriptor) pr
case "google.protobuf.Any":
// empty type URL is not allowed by JSON representation
// so we must give it a dummy type
msg, _ := ptypes.MarshalAny(&empty.Empty{})
return msg
var anyVal anypb.Any
_ = anypb.MarshalFrom(&anyVal, &emptypb.Empty{}, protov2.MarshalOptions{})
return &anyVal
case "google.protobuf.Value":
// unset kind is not allowed by JSON representation
// so we must give it something
@@ -462,42 +464,42 @@ func makeTemplate(md *desc.MessageDescriptor, path []*desc.MessageDescriptor) pr
for _, fd := range dm.GetMessageDescriptor().GetFields() {
if fd.IsRepeated() {
switch fd.GetType() {
case descpb.FieldDescriptorProto_TYPE_FIXED32,
descpb.FieldDescriptorProto_TYPE_UINT32:
case descriptorpb.FieldDescriptorProto_TYPE_FIXED32,
descriptorpb.FieldDescriptorProto_TYPE_UINT32:
dm.AddRepeatedField(fd, uint32(0))
case descpb.FieldDescriptorProto_TYPE_SFIXED32,
descpb.FieldDescriptorProto_TYPE_SINT32,
descpb.FieldDescriptorProto_TYPE_INT32,
descpb.FieldDescriptorProto_TYPE_ENUM:
case descriptorpb.FieldDescriptorProto_TYPE_SFIXED32,
descriptorpb.FieldDescriptorProto_TYPE_SINT32,
descriptorpb.FieldDescriptorProto_TYPE_INT32,
descriptorpb.FieldDescriptorProto_TYPE_ENUM:
dm.AddRepeatedField(fd, int32(0))
case descpb.FieldDescriptorProto_TYPE_FIXED64,
descpb.FieldDescriptorProto_TYPE_UINT64:
case descriptorpb.FieldDescriptorProto_TYPE_FIXED64,
descriptorpb.FieldDescriptorProto_TYPE_UINT64:
dm.AddRepeatedField(fd, uint64(0))
case descpb.FieldDescriptorProto_TYPE_SFIXED64,
descpb.FieldDescriptorProto_TYPE_SINT64,
descpb.FieldDescriptorProto_TYPE_INT64:
case descriptorpb.FieldDescriptorProto_TYPE_SFIXED64,
descriptorpb.FieldDescriptorProto_TYPE_SINT64,
descriptorpb.FieldDescriptorProto_TYPE_INT64:
dm.AddRepeatedField(fd, int64(0))
case descpb.FieldDescriptorProto_TYPE_STRING:
case descriptorpb.FieldDescriptorProto_TYPE_STRING:
dm.AddRepeatedField(fd, "")
case descpb.FieldDescriptorProto_TYPE_BYTES:
case descriptorpb.FieldDescriptorProto_TYPE_BYTES:
dm.AddRepeatedField(fd, []byte{})
case descpb.FieldDescriptorProto_TYPE_BOOL:
case descriptorpb.FieldDescriptorProto_TYPE_BOOL:
dm.AddRepeatedField(fd, false)
case descpb.FieldDescriptorProto_TYPE_FLOAT:
case descriptorpb.FieldDescriptorProto_TYPE_FLOAT:
dm.AddRepeatedField(fd, float32(0))
case descpb.FieldDescriptorProto_TYPE_DOUBLE:
case descriptorpb.FieldDescriptorProto_TYPE_DOUBLE:
dm.AddRepeatedField(fd, float64(0))
case descpb.FieldDescriptorProto_TYPE_MESSAGE,
descpb.FieldDescriptorProto_TYPE_GROUP:
case descriptorpb.FieldDescriptorProto_TYPE_MESSAGE,
descriptorpb.FieldDescriptorProto_TYPE_GROUP:
dm.AddRepeatedField(fd, makeTemplate(fd.GetMessageType(), path))
}
} else if fd.GetMessageType() != nil {
@@ -507,11 +509,25 @@ func makeTemplate(md *desc.MessageDescriptor, path []*desc.MessageDescriptor) pr
return dm
}
// ClientTransportCredentials builds transport credentials for a gRPC client using the
// ClientTransportCredentials is a helper function that constructs a TLS config with
// the given properties (see ClientTLSConfig) and then constructs and returns gRPC
// transport credentials using that config.
//
// Deprecated: Use grpcurl.ClientTLSConfig and credentials.NewTLS instead.
func ClientTransportCredentials(insecureSkipVerify bool, cacertFile, clientCertFile, clientKeyFile string) (credentials.TransportCredentials, error) {
tlsConf, err := ClientTLSConfig(insecureSkipVerify, cacertFile, clientCertFile, clientKeyFile)
if err != nil {
return nil, err
}
return credentials.NewTLS(tlsConf), nil
}
// ClientTLSConfig builds transport-layer config for a gRPC client using the
// given properties. If cacertFile is blank, only standard trusted certs are used to
// verify the server certs. If clientCertFile is blank, the client will not use a client
// certificate. If clientCertFile is not blank then clientKeyFile must not be blank.
func ClientTransportCredentials(insecureSkipVerify bool, cacertFile, clientCertFile, clientKeyFile string) (credentials.TransportCredentials, error) {
func ClientTLSConfig(insecureSkipVerify bool, cacertFile, clientCertFile, clientKeyFile string) (*tls.Config, error) {
var tlsConf tls.Config
if clientCertFile != "" {
@@ -541,7 +557,7 @@ func ClientTransportCredentials(insecureSkipVerify bool, cacertFile, clientCertF
tlsConf.RootCAs = certPool
}
return credentials.NewTLS(&tlsConf), nil
return &tlsConf, nil
}
// ServerTransportCredentials builds transport credentials for a gRPC server using the
@@ -617,11 +633,11 @@ func BlockingDial(ctx context.Context, network, address string, creds credential
dialer := func(ctx context.Context, address string) (net.Conn, error) {
// NB: We *could* handle the TLS handshake ourselves, in the custom
// dialer (instead of customizing both the dialer and the credentials).
// But that requires using WithInsecure dial option (so that the gRPC
// library doesn't *also* try to do a handshake). And that would mean
// that the library would send the wrong ":scheme" metaheader to
// servers: it would send "http" instead of "https" because it is
// unaware that TLS is actually in use.
// But that requires using insecure.NewCredentials() dial transport
// option (so that the gRPC library doesn't *also* try to do a
// handshake). And that would mean that the library would send the
// wrong ":scheme" metaheader to servers: it would send "http" instead
// of "https" because it is unaware that TLS is actually in use.
conn, err := (&net.Dialer{}).DialContext(ctx, network, address)
if err != nil {
writeResult(err)
@@ -634,13 +650,15 @@ func BlockingDial(ctx context.Context, network, address string, creds credential
// know when we're done. So we run it in a goroutine and then use result
// channel to either get the connection or fail-fast.
go func() {
opts = append(opts,
grpc.WithBlock(),
grpc.FailOnNonTempDialError(true),
grpc.WithContextDialer(dialer),
)
// We put grpc.FailOnNonTempDialError *before* the explicitly provided
// options so that it could be overridden.
opts = append([]grpc.DialOption{grpc.FailOnNonTempDialError(true)}, opts...)
// But we don't want caller to be able to override these two, so we put
// them *after* the explicitly provided options.
opts = append(opts, grpc.WithBlock(), grpc.WithContextDialer(dialer))
if creds == nil {
opts = append(opts, grpc.WithInsecure())
opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials()))
} else {
opts = append(opts, grpc.WithTransportCredentials(creds))
}

View File

@@ -1,6 +1,7 @@
package grpcurl_test
import (
"context"
"encoding/json"
"fmt"
"io"
@@ -11,22 +12,20 @@ import (
"testing"
"time"
"github.com/golang/protobuf/jsonpb"
jsonpbtest "github.com/golang/protobuf/jsonpb/jsonpb_test_proto"
"github.com/golang/protobuf/proto"
"github.com/golang/protobuf/jsonpb" //lint:ignore SA1019 we have to import this because it appears in exported API
"github.com/golang/protobuf/proto" //lint:ignore SA1019 we have to import this because it appears in exported API
"github.com/jhump/protoreflect/desc"
"github.com/jhump/protoreflect/grpcreflect"
"golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/interop/grpc_testing"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/reflection"
reflectpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
"google.golang.org/grpc/status"
. "github.com/fullstorydev/grpcurl"
grpcurl_testing "github.com/fullstorydev/grpcurl/testing"
grpcurl_testing "github.com/fullstorydev/grpcurl/internal/testing"
jsonpbtest "github.com/fullstorydev/grpcurl/internal/testing/jsonpb_test_proto"
)
var (
@@ -52,18 +51,18 @@ type descSourceCase struct {
func TestMain(m *testing.M) {
var err error
sourceProtoset, err = DescriptorSourceFromProtoSets("testing/test.protoset")
sourceProtoset, err = DescriptorSourceFromProtoSets("internal/testing/test.protoset")
if err != nil {
panic(err)
}
sourceProtoFiles, err = DescriptorSourceFromProtoFiles(nil, "testing/test.proto")
sourceProtoFiles, err = DescriptorSourceFromProtoFiles([]string{"internal/testing"}, "test.proto")
if err != nil {
panic(err)
}
// Create a server that includes the reflection service
svrReflect := grpc.NewServer()
grpc_testing.RegisterTestServiceServer(svrReflect, grpcurl_testing.TestServer{})
grpcurl_testing.RegisterTestServiceServer(svrReflect, grpcurl_testing.TestServer{})
reflection.Register(svrReflect)
var portReflect int
if l, err := net.Listen("tcp", "127.0.0.1:0"); err != nil {
@@ -78,18 +77,18 @@ func TestMain(m *testing.M) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if ccReflect, err = grpc.DialContext(ctx, fmt.Sprintf("127.0.0.1:%d", portReflect),
grpc.WithInsecure(), grpc.WithBlock()); err != nil {
grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock()); err != nil {
panic(err)
}
defer ccReflect.Close()
refClient := grpcreflect.NewClient(context.Background(), reflectpb.NewServerReflectionClient(ccReflect))
refClient := grpcreflect.NewClientAuto(context.Background(), ccReflect)
defer refClient.Reset()
sourceReflect = DescriptorSourceFromServer(context.Background(), refClient)
// Also create a server that does *not* include the reflection service
svrProtoset := grpc.NewServer()
grpc_testing.RegisterTestServiceServer(svrProtoset, grpcurl_testing.TestServer{})
grpcurl_testing.RegisterTestServiceServer(svrProtoset, grpcurl_testing.TestServer{})
var portProtoset int
if l, err := net.Listen("tcp", "127.0.0.1:0"); err != nil {
panic(err)
@@ -103,7 +102,7 @@ func TestMain(m *testing.M) {
ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if ccNoReflect, err = grpc.DialContext(ctx, fmt.Sprintf("127.0.0.1:%d", portProtoset),
grpc.WithInsecure(), grpc.WithBlock()); err != nil {
grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock()); err != nil {
panic(err)
}
defer ccNoReflect.Close()
@@ -118,7 +117,7 @@ func TestMain(m *testing.M) {
}
func TestServerDoesNotSupportReflection(t *testing.T) {
refClient := grpcreflect.NewClient(context.Background(), reflectpb.NewServerReflectionClient(ccNoReflect))
refClient := grpcreflect.NewClientAuto(context.Background(), ccNoReflect)
defer refClient.Reset()
refSource := DescriptorSourceFromServer(context.Background(), refClient)
@@ -141,7 +140,7 @@ func TestServerDoesNotSupportReflection(t *testing.T) {
}
func TestProtosetWithImports(t *testing.T) {
sourceProtoset, err := DescriptorSourceFromProtoSets("testing/example.protoset")
sourceProtoset, err := DescriptorSourceFromProtoSets("internal/testing/example.protoset")
if err != nil {
t.Fatalf("failed to load protoset: %v", err)
}
@@ -178,11 +177,11 @@ func doTestListServices(t *testing.T, source DescriptorSource, includeReflection
var expected []string
if includeReflection {
// when using server reflection, we see the TestService as well as the ServerReflection service
expected = []string{"grpc.reflection.v1alpha.ServerReflection", "grpc.testing.TestService"}
expected = []string{"grpc.reflection.v1.ServerReflection", "grpc.reflection.v1alpha.ServerReflection", "testing.TestService"}
} else {
// without reflection, we see all services defined in the same test.proto file, which is the
// TestService as well as UnimplementedService
expected = []string{"grpc.testing.TestService", "grpc.testing.UnimplementedService"}
expected = []string{"testing.TestService", "testing.UnimplementedService"}
}
if !reflect.DeepEqual(expected, names) {
t.Errorf("ListServices returned wrong results: wanted %v, got %v", expected, names)
@@ -198,17 +197,17 @@ func TestListMethods(t *testing.T) {
}
func doTestListMethods(t *testing.T, source DescriptorSource, includeReflection bool) {
names, err := ListMethods(source, "grpc.testing.TestService")
names, err := ListMethods(source, "testing.TestService")
if err != nil {
t.Fatalf("failed to list methods for TestService: %v", err)
}
expected := []string{
"grpc.testing.TestService.EmptyCall",
"grpc.testing.TestService.FullDuplexCall",
"grpc.testing.TestService.HalfDuplexCall",
"grpc.testing.TestService.StreamingInputCall",
"grpc.testing.TestService.StreamingOutputCall",
"grpc.testing.TestService.UnaryCall",
"testing.TestService.EmptyCall",
"testing.TestService.FullDuplexCall",
"testing.TestService.HalfDuplexCall",
"testing.TestService.StreamingInputCall",
"testing.TestService.StreamingOutputCall",
"testing.TestService.UnaryCall",
}
if !reflect.DeepEqual(expected, names) {
t.Errorf("ListMethods returned wrong results: wanted %v, got %v", expected, names)
@@ -216,19 +215,19 @@ func doTestListMethods(t *testing.T, source DescriptorSource, includeReflection
if includeReflection {
// when using server reflection, we see the TestService as well as the ServerReflection service
names, err = ListMethods(source, "grpc.reflection.v1alpha.ServerReflection")
names, err = ListMethods(source, "grpc.reflection.v1.ServerReflection")
if err != nil {
t.Fatalf("failed to list methods for ServerReflection: %v", err)
}
expected = []string{"grpc.reflection.v1alpha.ServerReflection.ServerReflectionInfo"}
expected = []string{"grpc.reflection.v1.ServerReflection.ServerReflectionInfo"}
} else {
// without reflection, we see all services defined in the same test.proto file, which is the
// TestService as well as UnimplementedService
names, err = ListMethods(source, "grpc.testing.UnimplementedService")
names, err = ListMethods(source, "testing.UnimplementedService")
if err != nil {
t.Fatalf("failed to list methods for ServerReflection: %v", err)
}
expected = []string{"grpc.testing.UnimplementedService.UnimplementedCall"}
expected = []string{"testing.UnimplementedService.UnimplementedCall"}
}
if !reflect.DeepEqual(expected, names) {
t.Errorf("ListMethods returned wrong results: wanted %v, got %v", expected, names)
@@ -242,10 +241,10 @@ func doTestListMethods(t *testing.T, source DescriptorSource, includeReflection
}
func TestGetAllFiles(t *testing.T) {
expectedFiles := []string{"testing/test.proto"}
// server reflection picks up filename from linked in Go package,
// which indicates "grpc_testing/test.proto", not our local copy.
expectedFilesWithReflection := []string{"grpc_reflection_v1alpha/reflection.proto", "grpc_testing/test.proto"}
expectedFiles := []string{"test.proto"}
expectedFilesWithReflection := []string{
"grpc/reflection/v1/reflection.proto", "grpc/reflection/v1alpha/reflection.proto", "test.proto",
}
for _, ds := range descSources {
t.Run(ds.name, func(t *testing.T) {
@@ -254,22 +253,26 @@ func TestGetAllFiles(t *testing.T) {
t.Fatalf("failed to get all files: %v", err)
}
names := fileNames(files)
expected := expectedFiles
match := false
var expected []string
if ds.includeRefl {
expected = expectedFilesWithReflection
} else {
expected = expectedFiles
}
if !reflect.DeepEqual(expected, names) {
match = reflect.DeepEqual(expected, names)
if !match {
t.Errorf("GetAllFiles returned wrong results: wanted %v, got %v", expected, names)
}
})
}
// try cases with more complicated set of files
otherSourceProtoset, err := DescriptorSourceFromProtoSets("testing/test.protoset", "testing/example.protoset")
otherSourceProtoset, err := DescriptorSourceFromProtoSets("internal/testing/test.protoset", "internal/testing/example.protoset")
if err != nil {
t.Fatal(err.Error())
}
otherSourceProtoFiles, err := DescriptorSourceFromProtoFiles(nil, "testing/test.proto", "testing/example.proto")
otherSourceProtoFiles, err := DescriptorSourceFromProtoFiles([]string{"internal/testing"}, "test.proto", "example.proto")
if err != nil {
t.Fatal(err.Error())
}
@@ -278,13 +281,13 @@ func TestGetAllFiles(t *testing.T) {
{"proto[b]", otherSourceProtoFiles, false},
}
expectedFiles = []string{
"example.proto",
"example2.proto",
"google/protobuf/any.proto",
"google/protobuf/descriptor.proto",
"google/protobuf/empty.proto",
"google/protobuf/timestamp.proto",
"testing/example.proto",
"testing/example2.proto",
"testing/test.proto",
"test.proto",
}
for _, ds := range otherDescSources {
t.Run(ds.name, func(t *testing.T) {
@@ -389,7 +392,7 @@ func TestDescribe(t *testing.T) {
}
func doTestDescribe(t *testing.T, source DescriptorSource) {
sym := "grpc.testing.TestService.EmptyCall"
sym := "testing.TestService.EmptyCall"
dsc, err := source.FindSymbol(sym)
if err != nil {
t.Fatalf("failed to get descriptor for %q: %v", sym, err)
@@ -400,14 +403,14 @@ func doTestDescribe(t *testing.T, source DescriptorSource) {
txt := proto.MarshalTextString(dsc.AsProto())
expected :=
`name: "EmptyCall"
input_type: ".grpc.testing.Empty"
output_type: ".grpc.testing.Empty"
input_type: ".testing.Empty"
output_type: ".testing.Empty"
`
if expected != txt {
t.Errorf("descriptor mismatch: expected %s, got %s", expected, txt)
}
sym = "grpc.testing.StreamingOutputCallResponse"
sym = "testing.StreamingOutputCallResponse"
dsc, err = source.FindSymbol(sym)
if err != nil {
t.Fatalf("failed to get descriptor for %q: %v", sym, err)
@@ -423,7 +426,7 @@ field: <
number: 1
label: LABEL_OPTIONAL
type: TYPE_MESSAGE
type_name: ".grpc.testing.Payload"
type_name: ".testing.Payload"
json_name: "payload"
>
`
@@ -479,12 +482,12 @@ func TestUnary(t *testing.T) {
func doTestUnary(t *testing.T, cc *grpc.ClientConn, source DescriptorSource) {
// Success
h := &handler{reqMessages: []string{payload1}}
err := InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/UnaryCall", makeHeaders(codes.OK), h, h.getRequestData)
err := InvokeRpc(context.Background(), source, cc, "testing.TestService/UnaryCall", makeHeaders(codes.OK), h, h.getRequestData)
if err != nil {
t.Fatalf("unexpected error during RPC: %v", err)
}
if h.check(t, "grpc.testing.TestService.UnaryCall", codes.OK, 1, 1) {
if h.check(t, "testing.TestService.UnaryCall", codes.OK, 1, 1) {
if h.respMessages[0] != payload1 {
t.Errorf("unexpected response from RPC: expecting %s; got %s", payload1, h.respMessages[0])
}
@@ -492,12 +495,12 @@ func doTestUnary(t *testing.T, cc *grpc.ClientConn, source DescriptorSource) {
// Failure
h = &handler{reqMessages: []string{payload1}}
err = InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/UnaryCall", makeHeaders(codes.NotFound), h, h.getRequestData)
err = InvokeRpc(context.Background(), source, cc, "testing.TestService/UnaryCall", makeHeaders(codes.NotFound), h, h.getRequestData)
if err != nil {
t.Fatalf("unexpected error during RPC: %v", err)
}
h.check(t, "grpc.testing.TestService.UnaryCall", codes.NotFound, 1, 0)
h.check(t, "testing.TestService.UnaryCall", codes.NotFound, 1, 0)
}
func TestClientStream(t *testing.T) {
@@ -511,12 +514,12 @@ func TestClientStream(t *testing.T) {
func doTestClientStream(t *testing.T, cc *grpc.ClientConn, source DescriptorSource) {
// Success
h := &handler{reqMessages: []string{payload1, payload2, payload3}}
err := InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/StreamingInputCall", makeHeaders(codes.OK), h, h.getRequestData)
err := InvokeRpc(context.Background(), source, cc, "testing.TestService/StreamingInputCall", makeHeaders(codes.OK), h, h.getRequestData)
if err != nil {
t.Fatalf("unexpected error during RPC: %v", err)
}
if h.check(t, "grpc.testing.TestService.StreamingInputCall", codes.OK, 3, 1) {
if h.check(t, "testing.TestService.StreamingInputCall", codes.OK, 3, 1) {
expected :=
`{
"aggregatedPayloadSize": 61
@@ -528,21 +531,21 @@ func doTestClientStream(t *testing.T, cc *grpc.ClientConn, source DescriptorSour
// Fail fast (server rejects as soon as possible)
h = &handler{reqMessages: []string{payload1, payload2, payload3}}
err = InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/StreamingInputCall", makeHeaders(codes.InvalidArgument), h, h.getRequestData)
err = InvokeRpc(context.Background(), source, cc, "testing.TestService/StreamingInputCall", makeHeaders(codes.InvalidArgument), h, h.getRequestData)
if err != nil {
t.Fatalf("unexpected error during RPC: %v", err)
}
h.check(t, "grpc.testing.TestService.StreamingInputCall", codes.InvalidArgument, -3, 0)
h.check(t, "testing.TestService.StreamingInputCall", codes.InvalidArgument, -3, 0)
// Fail late (server waits until stream is complete to reject)
h = &handler{reqMessages: []string{payload1, payload2, payload3}}
err = InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/StreamingInputCall", makeHeaders(codes.Internal, true), h, h.getRequestData)
err = InvokeRpc(context.Background(), source, cc, "testing.TestService/StreamingInputCall", makeHeaders(codes.Internal, true), h, h.getRequestData)
if err != nil {
t.Fatalf("unexpected error during RPC: %v", err)
}
h.check(t, "grpc.testing.TestService.StreamingInputCall", codes.Internal, 3, 0)
h.check(t, "testing.TestService.StreamingInputCall", codes.Internal, 3, 0)
}
func TestServerStream(t *testing.T) {
@@ -554,9 +557,9 @@ func TestServerStream(t *testing.T) {
}
func doTestServerStream(t *testing.T, cc *grpc.ClientConn, source DescriptorSource) {
req := &grpc_testing.StreamingOutputCallRequest{
ResponseType: grpc_testing.PayloadType_COMPRESSABLE,
ResponseParameters: []*grpc_testing.ResponseParameters{
req := &grpcurl_testing.StreamingOutputCallRequest{
ResponseType: grpcurl_testing.PayloadType_COMPRESSABLE,
ResponseParameters: []*grpcurl_testing.ResponseParameters{
{Size: 10}, {Size: 20}, {Size: 30}, {Size: 40}, {Size: 50},
},
}
@@ -567,19 +570,19 @@ func doTestServerStream(t *testing.T, cc *grpc.ClientConn, source DescriptorSour
// Success
h := &handler{reqMessages: []string{payload}}
err = InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/StreamingOutputCall", makeHeaders(codes.OK), h, h.getRequestData)
err = InvokeRpc(context.Background(), source, cc, "testing.TestService/StreamingOutputCall", makeHeaders(codes.OK), h, h.getRequestData)
if err != nil {
t.Fatalf("unexpected error during RPC: %v", err)
}
if h.check(t, "grpc.testing.TestService.StreamingOutputCall", codes.OK, 1, 5) {
resp := &grpc_testing.StreamingOutputCallResponse{}
if h.check(t, "testing.TestService.StreamingOutputCall", codes.OK, 1, 5) {
resp := &grpcurl_testing.StreamingOutputCallResponse{}
for i, msg := range h.respMessages {
if err := jsonpb.UnmarshalString(msg, resp); err != nil {
t.Errorf("failed to parse response %d: %v", i+1, err)
}
if resp.Payload.GetType() != grpc_testing.PayloadType_COMPRESSABLE {
t.Errorf("response %d has wrong payload type; expecting %v, got %v", i, grpc_testing.PayloadType_COMPRESSABLE, resp.Payload.Type)
if resp.Payload.GetType() != grpcurl_testing.PayloadType_COMPRESSABLE {
t.Errorf("response %d has wrong payload type; expecting %v, got %v", i, grpcurl_testing.PayloadType_COMPRESSABLE, resp.Payload.Type)
}
if len(resp.Payload.Body) != (i+1)*10 {
t.Errorf("response %d has wrong payload size; expecting %d, got %d", i, (i+1)*10, len(resp.Payload.Body))
@@ -590,21 +593,21 @@ func doTestServerStream(t *testing.T, cc *grpc.ClientConn, source DescriptorSour
// Fail fast (server rejects as soon as possible)
h = &handler{reqMessages: []string{payload}}
err = InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/StreamingOutputCall", makeHeaders(codes.Aborted), h, h.getRequestData)
err = InvokeRpc(context.Background(), source, cc, "testing.TestService/StreamingOutputCall", makeHeaders(codes.Aborted), h, h.getRequestData)
if err != nil {
t.Fatalf("unexpected error during RPC: %v", err)
}
h.check(t, "grpc.testing.TestService.StreamingOutputCall", codes.Aborted, 1, 0)
h.check(t, "testing.TestService.StreamingOutputCall", codes.Aborted, 1, 0)
// Fail late (server waits until stream is complete to reject)
h = &handler{reqMessages: []string{payload}}
err = InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/StreamingOutputCall", makeHeaders(codes.AlreadyExists, true), h, h.getRequestData)
err = InvokeRpc(context.Background(), source, cc, "testing.TestService/StreamingOutputCall", makeHeaders(codes.AlreadyExists, true), h, h.getRequestData)
if err != nil {
t.Fatalf("unexpected error during RPC: %v", err)
}
h.check(t, "grpc.testing.TestService.StreamingOutputCall", codes.AlreadyExists, 1, 5)
h.check(t, "testing.TestService.StreamingOutputCall", codes.AlreadyExists, 1, 5)
}
func TestHalfDuplexStream(t *testing.T) {
@@ -620,12 +623,12 @@ func doTestHalfDuplexStream(t *testing.T, cc *grpc.ClientConn, source Descriptor
// Success
h := &handler{reqMessages: reqs}
err := InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/HalfDuplexCall", makeHeaders(codes.OK), h, h.getRequestData)
err := InvokeRpc(context.Background(), source, cc, "testing.TestService/HalfDuplexCall", makeHeaders(codes.OK), h, h.getRequestData)
if err != nil {
t.Fatalf("unexpected error during RPC: %v", err)
}
if h.check(t, "grpc.testing.TestService.HalfDuplexCall", codes.OK, 3, 3) {
if h.check(t, "testing.TestService.HalfDuplexCall", codes.OK, 3, 3) {
for i, resp := range h.respMessages {
if resp != reqs[i] {
t.Errorf("unexpected response %d from RPC:\nexpecting %q\ngot %q", i, reqs[i], resp)
@@ -635,21 +638,21 @@ func doTestHalfDuplexStream(t *testing.T, cc *grpc.ClientConn, source Descriptor
// Fail fast (server rejects as soon as possible)
h = &handler{reqMessages: reqs}
err = InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/HalfDuplexCall", makeHeaders(codes.Canceled), h, h.getRequestData)
err = InvokeRpc(context.Background(), source, cc, "testing.TestService/HalfDuplexCall", makeHeaders(codes.Canceled), h, h.getRequestData)
if err != nil {
t.Fatalf("unexpected error during RPC: %v", err)
}
h.check(t, "grpc.testing.TestService.HalfDuplexCall", codes.Canceled, -3, 0)
h.check(t, "testing.TestService.HalfDuplexCall", codes.Canceled, -3, 0)
// Fail late (server waits until stream is complete to reject)
h = &handler{reqMessages: reqs}
err = InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/HalfDuplexCall", makeHeaders(codes.DataLoss, true), h, h.getRequestData)
err = InvokeRpc(context.Background(), source, cc, "testing.TestService/HalfDuplexCall", makeHeaders(codes.DataLoss, true), h, h.getRequestData)
if err != nil {
t.Fatalf("unexpected error during RPC: %v", err)
}
h.check(t, "grpc.testing.TestService.HalfDuplexCall", codes.DataLoss, 3, 3)
h.check(t, "testing.TestService.HalfDuplexCall", codes.DataLoss, 3, 3)
}
func TestFullDuplexStream(t *testing.T) {
@@ -662,11 +665,11 @@ func TestFullDuplexStream(t *testing.T) {
func doTestFullDuplexStream(t *testing.T, cc *grpc.ClientConn, source DescriptorSource) {
reqs := make([]string, 3)
req := &grpc_testing.StreamingOutputCallRequest{
ResponseType: grpc_testing.PayloadType_RANDOM,
req := &grpcurl_testing.StreamingOutputCallRequest{
ResponseType: grpcurl_testing.PayloadType_RANDOM,
}
for i := range reqs {
req.ResponseParameters = append(req.ResponseParameters, &grpc_testing.ResponseParameters{Size: int32((i + 1) * 10)})
req.ResponseParameters = append(req.ResponseParameters, &grpcurl_testing.ResponseParameters{Size: int32((i + 1) * 10)})
payload, err := (&jsonpb.Marshaler{}).MarshalToString(req)
if err != nil {
t.Fatalf("failed to construct request %d: %v", i, err)
@@ -676,13 +679,13 @@ func doTestFullDuplexStream(t *testing.T, cc *grpc.ClientConn, source Descriptor
// Success
h := &handler{reqMessages: reqs}
err := InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/FullDuplexCall", makeHeaders(codes.OK), h, h.getRequestData)
err := InvokeRpc(context.Background(), source, cc, "testing.TestService/FullDuplexCall", makeHeaders(codes.OK), h, h.getRequestData)
if err != nil {
t.Fatalf("unexpected error during RPC: %v", err)
}
if h.check(t, "grpc.testing.TestService.FullDuplexCall", codes.OK, 3, 6) {
resp := &grpc_testing.StreamingOutputCallResponse{}
if h.check(t, "testing.TestService.FullDuplexCall", codes.OK, 3, 6) {
resp := &grpcurl_testing.StreamingOutputCallResponse{}
i := 0
for j := 1; j < 3; j++ {
// three requests
@@ -692,8 +695,8 @@ func doTestFullDuplexStream(t *testing.T, cc *grpc.ClientConn, source Descriptor
if err := jsonpb.UnmarshalString(msg, resp); err != nil {
t.Errorf("failed to parse response %d: %v", i+1, err)
}
if resp.Payload.GetType() != grpc_testing.PayloadType_RANDOM {
t.Errorf("response %d has wrong payload type; expecting %v, got %v", i, grpc_testing.PayloadType_RANDOM, resp.Payload.Type)
if resp.Payload.GetType() != grpcurl_testing.PayloadType_RANDOM {
t.Errorf("response %d has wrong payload type; expecting %v, got %v", i, grpcurl_testing.PayloadType_RANDOM, resp.Payload.Type)
}
if len(resp.Payload.Body) != (k+1)*10 {
t.Errorf("response %d has wrong payload size; expecting %d, got %d", i, (k+1)*10, len(resp.Payload.Body))
@@ -707,21 +710,21 @@ func doTestFullDuplexStream(t *testing.T, cc *grpc.ClientConn, source Descriptor
// Fail fast (server rejects as soon as possible)
h = &handler{reqMessages: reqs}
err = InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/FullDuplexCall", makeHeaders(codes.PermissionDenied), h, h.getRequestData)
err = InvokeRpc(context.Background(), source, cc, "testing.TestService/FullDuplexCall", makeHeaders(codes.PermissionDenied), h, h.getRequestData)
if err != nil {
t.Fatalf("unexpected error during RPC: %v", err)
}
h.check(t, "grpc.testing.TestService.FullDuplexCall", codes.PermissionDenied, -3, 0)
h.check(t, "testing.TestService.FullDuplexCall", codes.PermissionDenied, -3, 0)
// Fail late (server waits until stream is complete to reject)
h = &handler{reqMessages: reqs}
err = InvokeRpc(context.Background(), source, cc, "grpc.testing.TestService/FullDuplexCall", makeHeaders(codes.ResourceExhausted, true), h, h.getRequestData)
err = InvokeRpc(context.Background(), source, cc, "testing.TestService/FullDuplexCall", makeHeaders(codes.ResourceExhausted, true), h, h.getRequestData)
if err != nil {
t.Fatalf("unexpected error during RPC: %v", err)
}
h.check(t, "grpc.testing.TestService.FullDuplexCall", codes.ResourceExhausted, 3, 6)
h.check(t, "testing.TestService.FullDuplexCall", codes.ResourceExhausted, 3, 6)
}
type handler struct {

View File

@@ -1,9 +1,9 @@
package main
import (
"context"
"strings"
"golang.org/x/net/context"
"google.golang.org/grpc/metadata"
)

View File

@@ -1,18 +1,18 @@
package main
import (
"context"
"fmt"
"time"
"github.com/golang/protobuf/ptypes"
"github.com/golang/protobuf/ptypes/empty"
"golang.org/x/net/context"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// bankServer implements the Bank gRPC service.
type bankServer struct {
UnimplementedBankServer
allAccounts *accounts
}
@@ -72,26 +72,29 @@ func (s *bankServer) GetTransactions(req *GetTransactionsRequest, stream Bank_Ge
var start, end time.Time
if req.Start != nil {
start, err = ptypes.Timestamp(req.Start)
err := req.Start.CheckValid()
if err != nil {
return err
}
start = req.Start.AsTime()
}
if req.End != nil {
end, err = ptypes.Timestamp(req.End)
err := req.End.CheckValid()
if err != nil {
return err
}
end = req.End.AsTime()
} else {
end = time.Date(9999, 12, 31, 23, 59, 59, 999999999, time.Local)
}
txns := acct.getTransactions()
for _, txn := range txns {
t, err := ptypes.Timestamp(txn.Date)
err := txn.Date.CheckValid()
if err != nil {
return err
}
t := txn.Date.AsTime()
if (t.After(start) || t.Equal(start)) &&
(t.Before(end) || t.Equal(end)) {

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
syntax = "proto3";
option go_package = "main";
option go_package = ".;main";
import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";

View File

@@ -0,0 +1,374 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
package main
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
emptypb "google.golang.org/protobuf/types/known/emptypb"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// BankClient is the client API for Bank service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type BankClient interface {
// OpenAccount creates an account with the type and given initial deposit
// as its balance.
OpenAccount(ctx context.Context, in *OpenAccountRequest, opts ...grpc.CallOption) (*Account, error)
// CloseAccount closes the indicated account. An account can only be
// closed if its balance is zero.
CloseAccount(ctx context.Context, in *CloseAccountRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
// GetAccounts lists all accounts for the current customer.
GetAccounts(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetAccountsResponse, error)
// GetTransactions streams all transactions that match the given criteria.
// If the given start date is not specified, transactions since beginning
// of time are included. Similarly, if the given end date is not specified,
// transactions all the way to the presnet are included.
GetTransactions(ctx context.Context, in *GetTransactionsRequest, opts ...grpc.CallOption) (Bank_GetTransactionsClient, error)
// Deposit increases the balance of an account by depositing funds into it.
Deposit(ctx context.Context, in *DepositRequest, opts ...grpc.CallOption) (*BalanceResponse, error)
// Withdraw decreases the balance of an account by withdrawing funds from it.
Withdraw(ctx context.Context, in *WithdrawRequest, opts ...grpc.CallOption) (*BalanceResponse, error)
// Transfer moves money from one account to another. The source and destination
// accounts can be with this bank (e.g. "local" account numbers) or can be
// external accounts, identified by their ACH routing and account numbers.
Transfer(ctx context.Context, in *TransferRequest, opts ...grpc.CallOption) (*TransferResponse, error)
}
type bankClient struct {
cc grpc.ClientConnInterface
}
func NewBankClient(cc grpc.ClientConnInterface) BankClient {
return &bankClient{cc}
}
func (c *bankClient) OpenAccount(ctx context.Context, in *OpenAccountRequest, opts ...grpc.CallOption) (*Account, error) {
out := new(Account)
err := c.cc.Invoke(ctx, "/Bank/OpenAccount", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *bankClient) CloseAccount(ctx context.Context, in *CloseAccountRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
out := new(emptypb.Empty)
err := c.cc.Invoke(ctx, "/Bank/CloseAccount", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *bankClient) GetAccounts(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetAccountsResponse, error) {
out := new(GetAccountsResponse)
err := c.cc.Invoke(ctx, "/Bank/GetAccounts", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *bankClient) GetTransactions(ctx context.Context, in *GetTransactionsRequest, opts ...grpc.CallOption) (Bank_GetTransactionsClient, error) {
stream, err := c.cc.NewStream(ctx, &Bank_ServiceDesc.Streams[0], "/Bank/GetTransactions", opts...)
if err != nil {
return nil, err
}
x := &bankGetTransactionsClient{stream}
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
}
type Bank_GetTransactionsClient interface {
Recv() (*Transaction, error)
grpc.ClientStream
}
type bankGetTransactionsClient struct {
grpc.ClientStream
}
func (x *bankGetTransactionsClient) Recv() (*Transaction, error) {
m := new(Transaction)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *bankClient) Deposit(ctx context.Context, in *DepositRequest, opts ...grpc.CallOption) (*BalanceResponse, error) {
out := new(BalanceResponse)
err := c.cc.Invoke(ctx, "/Bank/Deposit", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *bankClient) Withdraw(ctx context.Context, in *WithdrawRequest, opts ...grpc.CallOption) (*BalanceResponse, error) {
out := new(BalanceResponse)
err := c.cc.Invoke(ctx, "/Bank/Withdraw", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *bankClient) Transfer(ctx context.Context, in *TransferRequest, opts ...grpc.CallOption) (*TransferResponse, error) {
out := new(TransferResponse)
err := c.cc.Invoke(ctx, "/Bank/Transfer", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// BankServer is the server API for Bank service.
// All implementations must embed UnimplementedBankServer
// for forward compatibility
type BankServer interface {
// OpenAccount creates an account with the type and given initial deposit
// as its balance.
OpenAccount(context.Context, *OpenAccountRequest) (*Account, error)
// CloseAccount closes the indicated account. An account can only be
// closed if its balance is zero.
CloseAccount(context.Context, *CloseAccountRequest) (*emptypb.Empty, error)
// GetAccounts lists all accounts for the current customer.
GetAccounts(context.Context, *emptypb.Empty) (*GetAccountsResponse, error)
// GetTransactions streams all transactions that match the given criteria.
// If the given start date is not specified, transactions since beginning
// of time are included. Similarly, if the given end date is not specified,
// transactions all the way to the presnet are included.
GetTransactions(*GetTransactionsRequest, Bank_GetTransactionsServer) error
// Deposit increases the balance of an account by depositing funds into it.
Deposit(context.Context, *DepositRequest) (*BalanceResponse, error)
// Withdraw decreases the balance of an account by withdrawing funds from it.
Withdraw(context.Context, *WithdrawRequest) (*BalanceResponse, error)
// Transfer moves money from one account to another. The source and destination
// accounts can be with this bank (e.g. "local" account numbers) or can be
// external accounts, identified by their ACH routing and account numbers.
Transfer(context.Context, *TransferRequest) (*TransferResponse, error)
mustEmbedUnimplementedBankServer()
}
// UnimplementedBankServer must be embedded to have forward compatible implementations.
type UnimplementedBankServer struct {
}
func (UnimplementedBankServer) OpenAccount(context.Context, *OpenAccountRequest) (*Account, error) {
return nil, status.Errorf(codes.Unimplemented, "method OpenAccount not implemented")
}
func (UnimplementedBankServer) CloseAccount(context.Context, *CloseAccountRequest) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method CloseAccount not implemented")
}
func (UnimplementedBankServer) GetAccounts(context.Context, *emptypb.Empty) (*GetAccountsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetAccounts not implemented")
}
func (UnimplementedBankServer) GetTransactions(*GetTransactionsRequest, Bank_GetTransactionsServer) error {
return status.Errorf(codes.Unimplemented, "method GetTransactions not implemented")
}
func (UnimplementedBankServer) Deposit(context.Context, *DepositRequest) (*BalanceResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Deposit not implemented")
}
func (UnimplementedBankServer) Withdraw(context.Context, *WithdrawRequest) (*BalanceResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Withdraw not implemented")
}
func (UnimplementedBankServer) Transfer(context.Context, *TransferRequest) (*TransferResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Transfer not implemented")
}
func (UnimplementedBankServer) mustEmbedUnimplementedBankServer() {}
// UnsafeBankServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to BankServer will
// result in compilation errors.
type UnsafeBankServer interface {
mustEmbedUnimplementedBankServer()
}
func RegisterBankServer(s grpc.ServiceRegistrar, srv BankServer) {
s.RegisterService(&Bank_ServiceDesc, srv)
}
func _Bank_OpenAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(OpenAccountRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(BankServer).OpenAccount(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/Bank/OpenAccount",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(BankServer).OpenAccount(ctx, req.(*OpenAccountRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Bank_CloseAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CloseAccountRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(BankServer).CloseAccount(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/Bank/CloseAccount",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(BankServer).CloseAccount(ctx, req.(*CloseAccountRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Bank_GetAccounts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(emptypb.Empty)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(BankServer).GetAccounts(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/Bank/GetAccounts",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(BankServer).GetAccounts(ctx, req.(*emptypb.Empty))
}
return interceptor(ctx, in, info, handler)
}
func _Bank_GetTransactions_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(GetTransactionsRequest)
if err := stream.RecvMsg(m); err != nil {
return err
}
return srv.(BankServer).GetTransactions(m, &bankGetTransactionsServer{stream})
}
type Bank_GetTransactionsServer interface {
Send(*Transaction) error
grpc.ServerStream
}
type bankGetTransactionsServer struct {
grpc.ServerStream
}
func (x *bankGetTransactionsServer) Send(m *Transaction) error {
return x.ServerStream.SendMsg(m)
}
func _Bank_Deposit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DepositRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(BankServer).Deposit(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/Bank/Deposit",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(BankServer).Deposit(ctx, req.(*DepositRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Bank_Withdraw_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(WithdrawRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(BankServer).Withdraw(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/Bank/Withdraw",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(BankServer).Withdraw(ctx, req.(*WithdrawRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Bank_Transfer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(TransferRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(BankServer).Transfer(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/Bank/Transfer",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(BankServer).Transfer(ctx, req.(*TransferRequest))
}
return interceptor(ctx, in, info, handler)
}
// Bank_ServiceDesc is the grpc.ServiceDesc for Bank service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var Bank_ServiceDesc = grpc.ServiceDesc{
ServiceName: "Bank",
HandlerType: (*BankServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "OpenAccount",
Handler: _Bank_OpenAccount_Handler,
},
{
MethodName: "CloseAccount",
Handler: _Bank_CloseAccount_Handler,
},
{
MethodName: "GetAccounts",
Handler: _Bank_GetAccounts_Handler,
},
{
MethodName: "Deposit",
Handler: _Bank_Deposit_Handler,
},
{
MethodName: "Withdraw",
Handler: _Bank_Withdraw_Handler,
},
{
MethodName: "Transfer",
Handler: _Bank_Transfer_Handler,
},
},
Streams: []grpc.StreamDesc{
{
StreamName: "GetTransactions",
Handler: _Bank_GetTransactions_Handler,
ServerStreams: true,
},
},
Metadata: "bank.proto",
}

View File

@@ -1,20 +1,21 @@
package main
import (
"context"
"fmt"
"io"
"sync"
"github.com/golang/protobuf/ptypes"
"golang.org/x/net/context"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/timestamppb"
)
// chatServer implements the Support gRPC service, for providing
// a capability to connect customers and support agents in real-time
// chat.
type chatServer struct {
UnimplementedSupportServer
chatsBySession map[string]*session
chatsAwaitingAgent []string
lastSession int32
@@ -134,7 +135,7 @@ func (s *chatServer) ChatCustomer(stream Support_ChatCustomerServer) error {
}
entry := &ChatEntry{
Date: ptypes.TimestampNow(),
Date: timestamppb.Now(),
Entry: &ChatEntry_CustomerMsg{
CustomerMsg: req.Msg,
},
@@ -279,7 +280,7 @@ func (s *chatServer) ChatAgent(stream Support_ChatAgentServer) error {
}
entry := &ChatEntry{
Date: ptypes.TimestampNow(),
Date: timestamppb.Now(),
Entry: &ChatEntry_AgentMsg{
AgentMsg: &AgentMessage{
AgentName: agent,

View File

@@ -1,14 +1,13 @@
package main
import (
"bytes"
"fmt"
"sync"
"github.com/golang/protobuf/jsonpb"
"github.com/golang/protobuf/ptypes"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/types/known/timestamppb"
)
// In-memory database that is periodically saved to a JSON file.
@@ -43,7 +42,7 @@ func (a *accounts) openAccount(customer string, accountType Account_Type, initia
acct.Transactions = append(acct.Transactions, &Transaction{
AccountNumber: num,
SeqNumber: 1,
Date: ptypes.TimestampNow(),
Date: timestamppb.Now(),
AmountCents: initialBalanceCents,
Desc: "initial deposit",
})
@@ -130,7 +129,7 @@ func (a *account) newTransaction(amountCents int32, desc string) (newBalance int
a.BalanceCents = bal
a.Transactions = append(a.Transactions, &Transaction{
AccountNumber: a.AccountNumber,
Date: ptypes.TimestampNow(),
Date: timestamppb.Now(),
AmountCents: amountCents,
SeqNumber: uint64(len(a.Transactions) + 1),
Desc: desc,
@@ -139,16 +138,11 @@ func (a *account) newTransaction(amountCents int32, desc string) (newBalance int
}
func (t *Transaction) MarshalJSON() ([]byte, error) {
var jsm jsonpb.Marshaler
var buf bytes.Buffer
if err := jsm.Marshal(&buf, t); err != nil {
return nil, err
}
return buf.Bytes(), nil
return protojson.Marshal(t)
}
func (t *Transaction) UnmarshalJSON(b []byte) error {
return jsonpb.Unmarshal(bytes.NewReader(b), t)
return protojson.Unmarshal(b, t)
}
func (a *accounts) clone() *accounts {

View File

@@ -1,8 +1,9 @@
package main
//go:generate protoc --go_out=plugins=grpc:./ bank.proto support.proto
//go:generate protoc --go_out=. --go-grpc_out=. bank.proto support.proto
import (
"context"
"encoding/json"
"flag"
"fmt"
@@ -14,7 +15,6 @@ import (
"syscall"
"time"
"golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/peer"

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
syntax = "proto3";
option go_package = "main";
option go_package = ".;main";
import "google/protobuf/timestamp.proto";

View File

@@ -0,0 +1,217 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
package main
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// SupportClient is the client API for Support service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type SupportClient interface {
// ChatCustomer is used by a customer-facing app to send the customer's messages
// to a chat session. The customer is how initiates and terminates (via "hangup")
// a chat session. Only customers may invoke this method (e.g. requests must
// include customer auth credentials).
ChatCustomer(ctx context.Context, opts ...grpc.CallOption) (Support_ChatCustomerClient, error)
// ChatAgent is used by an agent-facing app to allow an agent to reply to a
// customer's messages in a chat session. The agent may accept a chat session,
// which defaults to the session awaiting an agent for the longest period of time
// (FIFO queue).
ChatAgent(ctx context.Context, opts ...grpc.CallOption) (Support_ChatAgentClient, error)
}
type supportClient struct {
cc grpc.ClientConnInterface
}
func NewSupportClient(cc grpc.ClientConnInterface) SupportClient {
return &supportClient{cc}
}
func (c *supportClient) ChatCustomer(ctx context.Context, opts ...grpc.CallOption) (Support_ChatCustomerClient, error) {
stream, err := c.cc.NewStream(ctx, &Support_ServiceDesc.Streams[0], "/Support/ChatCustomer", opts...)
if err != nil {
return nil, err
}
x := &supportChatCustomerClient{stream}
return x, nil
}
type Support_ChatCustomerClient interface {
Send(*ChatCustomerRequest) error
Recv() (*ChatCustomerResponse, error)
grpc.ClientStream
}
type supportChatCustomerClient struct {
grpc.ClientStream
}
func (x *supportChatCustomerClient) Send(m *ChatCustomerRequest) error {
return x.ClientStream.SendMsg(m)
}
func (x *supportChatCustomerClient) Recv() (*ChatCustomerResponse, error) {
m := new(ChatCustomerResponse)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *supportClient) ChatAgent(ctx context.Context, opts ...grpc.CallOption) (Support_ChatAgentClient, error) {
stream, err := c.cc.NewStream(ctx, &Support_ServiceDesc.Streams[1], "/Support/ChatAgent", opts...)
if err != nil {
return nil, err
}
x := &supportChatAgentClient{stream}
return x, nil
}
type Support_ChatAgentClient interface {
Send(*ChatAgentRequest) error
Recv() (*ChatAgentResponse, error)
grpc.ClientStream
}
type supportChatAgentClient struct {
grpc.ClientStream
}
func (x *supportChatAgentClient) Send(m *ChatAgentRequest) error {
return x.ClientStream.SendMsg(m)
}
func (x *supportChatAgentClient) Recv() (*ChatAgentResponse, error) {
m := new(ChatAgentResponse)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
// SupportServer is the server API for Support service.
// All implementations must embed UnimplementedSupportServer
// for forward compatibility
type SupportServer interface {
// ChatCustomer is used by a customer-facing app to send the customer's messages
// to a chat session. The customer is how initiates and terminates (via "hangup")
// a chat session. Only customers may invoke this method (e.g. requests must
// include customer auth credentials).
ChatCustomer(Support_ChatCustomerServer) error
// ChatAgent is used by an agent-facing app to allow an agent to reply to a
// customer's messages in a chat session. The agent may accept a chat session,
// which defaults to the session awaiting an agent for the longest period of time
// (FIFO queue).
ChatAgent(Support_ChatAgentServer) error
mustEmbedUnimplementedSupportServer()
}
// UnimplementedSupportServer must be embedded to have forward compatible implementations.
type UnimplementedSupportServer struct {
}
func (UnimplementedSupportServer) ChatCustomer(Support_ChatCustomerServer) error {
return status.Errorf(codes.Unimplemented, "method ChatCustomer not implemented")
}
func (UnimplementedSupportServer) ChatAgent(Support_ChatAgentServer) error {
return status.Errorf(codes.Unimplemented, "method ChatAgent not implemented")
}
func (UnimplementedSupportServer) mustEmbedUnimplementedSupportServer() {}
// UnsafeSupportServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to SupportServer will
// result in compilation errors.
type UnsafeSupportServer interface {
mustEmbedUnimplementedSupportServer()
}
func RegisterSupportServer(s grpc.ServiceRegistrar, srv SupportServer) {
s.RegisterService(&Support_ServiceDesc, srv)
}
func _Support_ChatCustomer_Handler(srv interface{}, stream grpc.ServerStream) error {
return srv.(SupportServer).ChatCustomer(&supportChatCustomerServer{stream})
}
type Support_ChatCustomerServer interface {
Send(*ChatCustomerResponse) error
Recv() (*ChatCustomerRequest, error)
grpc.ServerStream
}
type supportChatCustomerServer struct {
grpc.ServerStream
}
func (x *supportChatCustomerServer) Send(m *ChatCustomerResponse) error {
return x.ServerStream.SendMsg(m)
}
func (x *supportChatCustomerServer) Recv() (*ChatCustomerRequest, error) {
m := new(ChatCustomerRequest)
if err := x.ServerStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func _Support_ChatAgent_Handler(srv interface{}, stream grpc.ServerStream) error {
return srv.(SupportServer).ChatAgent(&supportChatAgentServer{stream})
}
type Support_ChatAgentServer interface {
Send(*ChatAgentResponse) error
Recv() (*ChatAgentRequest, error)
grpc.ServerStream
}
type supportChatAgentServer struct {
grpc.ServerStream
}
func (x *supportChatAgentServer) Send(m *ChatAgentResponse) error {
return x.ServerStream.SendMsg(m)
}
func (x *supportChatAgentServer) Recv() (*ChatAgentRequest, error) {
m := new(ChatAgentRequest)
if err := x.ServerStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
// Support_ServiceDesc is the grpc.ServiceDesc for Support service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var Support_ServiceDesc = grpc.ServiceDesc{
ServiceName: "Support",
HandlerType: (*SupportServer)(nil),
Methods: []grpc.MethodDesc{},
Streams: []grpc.StreamDesc{
{
StreamName: "ChatCustomer",
Handler: _Support_ChatCustomer_Handler,
ServerStreams: true,
ClientStreams: true,
},
{
StreamName: "ChatAgent",
Handler: _Support_ChatAgent_Handler,
ServerStreams: true,
ClientStreams: true,
},
},
Metadata: "support.proto",
}

View File

@@ -2,6 +2,7 @@
package main
import (
"context"
"flag"
"fmt"
"net"
@@ -9,17 +10,15 @@ import (
"sync/atomic"
"time"
"golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/interop/grpc_testing"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/reflection"
"google.golang.org/grpc/status"
"github.com/fullstorydev/grpcurl"
grpcurl_testing "github.com/fullstorydev/grpcurl/testing"
grpcurl_testing "github.com/fullstorydev/grpcurl/internal/testing"
)
var (
@@ -96,7 +95,7 @@ func main() {
svr := grpc.NewServer(opts...)
grpc_testing.RegisterTestServiceServer(svr, grpcurl_testing.TestServer{})
grpcurl_testing.RegisterTestServiceServer(svr, grpcurl_testing.TestServer{})
if !*noreflect {
reflection.Register(svr)
}

View File

@@ -1,3 +1,4 @@
//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
package main

View File

@@ -3,7 +3,7 @@ syntax = "proto3";
import "google/protobuf/descriptor.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";
import "testing/example2.proto";
import "example2.proto";
message TestRequest {
repeated string file_names = 1;

View File

@@ -0,0 +1,344 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.25.0-devel
// protoc v3.14.0
// source: test_objects.proto
package jsonpb
import (
proto "github.com/golang/protobuf/proto"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
anypb "google.golang.org/protobuf/types/known/anypb"
durationpb "google.golang.org/protobuf/types/known/durationpb"
structpb "google.golang.org/protobuf/types/known/structpb"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
wrapperspb "google.golang.org/protobuf/types/known/wrapperspb"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// This is a compile-time assertion that a sufficiently up-to-date version
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4
type KnownTypes struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
An *anypb.Any `protobuf:"bytes,14,opt,name=an" json:"an,omitempty"`
Dur *durationpb.Duration `protobuf:"bytes,1,opt,name=dur" json:"dur,omitempty"`
St *structpb.Struct `protobuf:"bytes,12,opt,name=st" json:"st,omitempty"`
Ts *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=ts" json:"ts,omitempty"`
Lv *structpb.ListValue `protobuf:"bytes,15,opt,name=lv" json:"lv,omitempty"`
Val *structpb.Value `protobuf:"bytes,16,opt,name=val" json:"val,omitempty"`
Dbl *wrapperspb.DoubleValue `protobuf:"bytes,3,opt,name=dbl" json:"dbl,omitempty"`
Flt *wrapperspb.FloatValue `protobuf:"bytes,4,opt,name=flt" json:"flt,omitempty"`
I64 *wrapperspb.Int64Value `protobuf:"bytes,5,opt,name=i64" json:"i64,omitempty"`
U64 *wrapperspb.UInt64Value `protobuf:"bytes,6,opt,name=u64" json:"u64,omitempty"`
I32 *wrapperspb.Int32Value `protobuf:"bytes,7,opt,name=i32" json:"i32,omitempty"`
U32 *wrapperspb.UInt32Value `protobuf:"bytes,8,opt,name=u32" json:"u32,omitempty"`
Bool *wrapperspb.BoolValue `protobuf:"bytes,9,opt,name=bool" json:"bool,omitempty"`
Str *wrapperspb.StringValue `protobuf:"bytes,10,opt,name=str" json:"str,omitempty"`
Bytes *wrapperspb.BytesValue `protobuf:"bytes,11,opt,name=bytes" json:"bytes,omitempty"`
}
func (x *KnownTypes) Reset() {
*x = KnownTypes{}
if protoimpl.UnsafeEnabled {
mi := &file_test_objects_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *KnownTypes) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*KnownTypes) ProtoMessage() {}
func (x *KnownTypes) ProtoReflect() protoreflect.Message {
mi := &file_test_objects_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use KnownTypes.ProtoReflect.Descriptor instead.
func (*KnownTypes) Descriptor() ([]byte, []int) {
return file_test_objects_proto_rawDescGZIP(), []int{0}
}
func (x *KnownTypes) GetAn() *anypb.Any {
if x != nil {
return x.An
}
return nil
}
func (x *KnownTypes) GetDur() *durationpb.Duration {
if x != nil {
return x.Dur
}
return nil
}
func (x *KnownTypes) GetSt() *structpb.Struct {
if x != nil {
return x.St
}
return nil
}
func (x *KnownTypes) GetTs() *timestamppb.Timestamp {
if x != nil {
return x.Ts
}
return nil
}
func (x *KnownTypes) GetLv() *structpb.ListValue {
if x != nil {
return x.Lv
}
return nil
}
func (x *KnownTypes) GetVal() *structpb.Value {
if x != nil {
return x.Val
}
return nil
}
func (x *KnownTypes) GetDbl() *wrapperspb.DoubleValue {
if x != nil {
return x.Dbl
}
return nil
}
func (x *KnownTypes) GetFlt() *wrapperspb.FloatValue {
if x != nil {
return x.Flt
}
return nil
}
func (x *KnownTypes) GetI64() *wrapperspb.Int64Value {
if x != nil {
return x.I64
}
return nil
}
func (x *KnownTypes) GetU64() *wrapperspb.UInt64Value {
if x != nil {
return x.U64
}
return nil
}
func (x *KnownTypes) GetI32() *wrapperspb.Int32Value {
if x != nil {
return x.I32
}
return nil
}
func (x *KnownTypes) GetU32() *wrapperspb.UInt32Value {
if x != nil {
return x.U32
}
return nil
}
func (x *KnownTypes) GetBool() *wrapperspb.BoolValue {
if x != nil {
return x.Bool
}
return nil
}
func (x *KnownTypes) GetStr() *wrapperspb.StringValue {
if x != nil {
return x.Str
}
return nil
}
func (x *KnownTypes) GetBytes() *wrapperspb.BytesValue {
if x != nil {
return x.Bytes
}
return nil
}
var File_test_objects_proto protoreflect.FileDescriptor
var file_test_objects_proto_rawDesc = []byte{
0x0a, 0x12, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x6a, 0x73, 0x6f, 0x6e, 0x70, 0x62, 0x1a, 0x19, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e,
0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xba, 0x05, 0x0a, 0x0a, 0x4b, 0x6e, 0x6f, 0x77, 0x6e,
0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x02, 0x61, 0x6e, 0x18, 0x0e, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x02, 0x61, 0x6e, 0x12, 0x2b, 0x0a, 0x03, 0x64,
0x75, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x52, 0x03, 0x64, 0x75, 0x72, 0x12, 0x27, 0x0a, 0x02, 0x73, 0x74, 0x18, 0x0c,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x02, 0x73,
0x74, 0x12, 0x2a, 0x0a, 0x02, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x02, 0x74, 0x73, 0x12, 0x2a, 0x0a,
0x02, 0x6c, 0x76, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4c, 0x69, 0x73, 0x74,
0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x02, 0x6c, 0x76, 0x12, 0x28, 0x0a, 0x03, 0x76, 0x61, 0x6c,
0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x03,
0x76, 0x61, 0x6c, 0x12, 0x2e, 0x0a, 0x03, 0x64, 0x62, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x03,
0x64, 0x62, 0x6c, 0x12, 0x2d, 0x0a, 0x03, 0x66, 0x6c, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x03, 0x66,
0x6c, 0x74, 0x12, 0x2d, 0x0a, 0x03, 0x69, 0x36, 0x34, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2e, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x03, 0x69, 0x36,
0x34, 0x12, 0x2e, 0x0a, 0x03, 0x75, 0x36, 0x34, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x03, 0x75, 0x36,
0x34, 0x12, 0x2d, 0x0a, 0x03, 0x69, 0x33, 0x32, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x03, 0x69, 0x33, 0x32,
0x12, 0x2e, 0x0a, 0x03, 0x75, 0x33, 0x32, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x03, 0x75, 0x33, 0x32,
0x12, 0x2e, 0x0a, 0x04, 0x62, 0x6f, 0x6f, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x04, 0x62, 0x6f, 0x6f, 0x6c,
0x12, 0x2e, 0x0a, 0x03, 0x73, 0x74, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x03, 0x73, 0x74, 0x72,
0x12, 0x31, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x62, 0x79,
0x74, 0x65, 0x73, 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x3b, 0x6a, 0x73, 0x6f, 0x6e, 0x70, 0x62,
}
var (
file_test_objects_proto_rawDescOnce sync.Once
file_test_objects_proto_rawDescData = file_test_objects_proto_rawDesc
)
func file_test_objects_proto_rawDescGZIP() []byte {
file_test_objects_proto_rawDescOnce.Do(func() {
file_test_objects_proto_rawDescData = protoimpl.X.CompressGZIP(file_test_objects_proto_rawDescData)
})
return file_test_objects_proto_rawDescData
}
var file_test_objects_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_test_objects_proto_goTypes = []interface{}{
(*KnownTypes)(nil), // 0: jsonpb.KnownTypes
(*anypb.Any)(nil), // 1: google.protobuf.Any
(*durationpb.Duration)(nil), // 2: google.protobuf.Duration
(*structpb.Struct)(nil), // 3: google.protobuf.Struct
(*timestamppb.Timestamp)(nil), // 4: google.protobuf.Timestamp
(*structpb.ListValue)(nil), // 5: google.protobuf.ListValue
(*structpb.Value)(nil), // 6: google.protobuf.Value
(*wrapperspb.DoubleValue)(nil), // 7: google.protobuf.DoubleValue
(*wrapperspb.FloatValue)(nil), // 8: google.protobuf.FloatValue
(*wrapperspb.Int64Value)(nil), // 9: google.protobuf.Int64Value
(*wrapperspb.UInt64Value)(nil), // 10: google.protobuf.UInt64Value
(*wrapperspb.Int32Value)(nil), // 11: google.protobuf.Int32Value
(*wrapperspb.UInt32Value)(nil), // 12: google.protobuf.UInt32Value
(*wrapperspb.BoolValue)(nil), // 13: google.protobuf.BoolValue
(*wrapperspb.StringValue)(nil), // 14: google.protobuf.StringValue
(*wrapperspb.BytesValue)(nil), // 15: google.protobuf.BytesValue
}
var file_test_objects_proto_depIdxs = []int32{
1, // 0: jsonpb.KnownTypes.an:type_name -> google.protobuf.Any
2, // 1: jsonpb.KnownTypes.dur:type_name -> google.protobuf.Duration
3, // 2: jsonpb.KnownTypes.st:type_name -> google.protobuf.Struct
4, // 3: jsonpb.KnownTypes.ts:type_name -> google.protobuf.Timestamp
5, // 4: jsonpb.KnownTypes.lv:type_name -> google.protobuf.ListValue
6, // 5: jsonpb.KnownTypes.val:type_name -> google.protobuf.Value
7, // 6: jsonpb.KnownTypes.dbl:type_name -> google.protobuf.DoubleValue
8, // 7: jsonpb.KnownTypes.flt:type_name -> google.protobuf.FloatValue
9, // 8: jsonpb.KnownTypes.i64:type_name -> google.protobuf.Int64Value
10, // 9: jsonpb.KnownTypes.u64:type_name -> google.protobuf.UInt64Value
11, // 10: jsonpb.KnownTypes.i32:type_name -> google.protobuf.Int32Value
12, // 11: jsonpb.KnownTypes.u32:type_name -> google.protobuf.UInt32Value
13, // 12: jsonpb.KnownTypes.bool:type_name -> google.protobuf.BoolValue
14, // 13: jsonpb.KnownTypes.str:type_name -> google.protobuf.StringValue
15, // 14: jsonpb.KnownTypes.bytes:type_name -> google.protobuf.BytesValue
15, // [15:15] is the sub-list for method output_type
15, // [15:15] is the sub-list for method input_type
15, // [15:15] is the sub-list for extension type_name
15, // [15:15] is the sub-list for extension extendee
0, // [0:15] is the sub-list for field type_name
}
func init() { file_test_objects_proto_init() }
func file_test_objects_proto_init() {
if File_test_objects_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_test_objects_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*KnownTypes); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_test_objects_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_test_objects_proto_goTypes,
DependencyIndexes: file_test_objects_proto_depIdxs,
MessageInfos: file_test_objects_proto_msgTypes,
}.Build()
File_test_objects_proto = out.File
file_test_objects_proto_rawDesc = nil
file_test_objects_proto_goTypes = nil
file_test_objects_proto_depIdxs = nil
}

View File

@@ -0,0 +1,30 @@
syntax = "proto2";
import "google/protobuf/any.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/wrappers.proto";
package jsonpb;
option go_package=".;jsonpb";
message KnownTypes {
optional google.protobuf.Any an = 14;
optional google.protobuf.Duration dur = 1;
optional google.protobuf.Struct st = 12;
optional google.protobuf.Timestamp ts = 2;
optional google.protobuf.ListValue lv = 15;
optional google.protobuf.Value val = 16;
optional google.protobuf.DoubleValue dbl = 3;
optional google.protobuf.FloatValue flt = 4;
optional google.protobuf.Int64Value i64 = 5;
optional google.protobuf.UInt64Value u64 = 6;
optional google.protobuf.Int32Value i32 = 7;
optional google.protobuf.UInt32Value u32 = 8;
optional google.protobuf.BoolValue bool = 9;
optional google.protobuf.StringValue str = 10;
optional google.protobuf.BytesValue bytes = 11;
}

1030
internal/testing/test.pb.go Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -18,7 +18,9 @@
// of unary/streaming requests/responses.
syntax = "proto3";
package grpc.testing;
package testing;
option go_package = ".;testing";
message Empty {}
@@ -172,5 +174,5 @@ service TestService {
// that case.
service UnimplementedService {
// A call that no server should implement
rpc UnimplementedCall(grpc.testing.Empty) returns (grpc.testing.Empty);
rpc UnimplementedCall(Empty) returns (Empty);
}

Binary file not shown.

View File

@@ -0,0 +1,523 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
package testing
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// TestServiceClient is the client API for TestService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type TestServiceClient interface {
// One empty request followed by one empty response.
EmptyCall(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error)
// One request followed by one response.
// The server returns the client payload as-is.
UnaryCall(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (*SimpleResponse, error)
// One request followed by a sequence of responses (streamed download).
// The server returns the payload with client desired type and sizes.
StreamingOutputCall(ctx context.Context, in *StreamingOutputCallRequest, opts ...grpc.CallOption) (TestService_StreamingOutputCallClient, error)
// A sequence of requests followed by one response (streamed upload).
// The server returns the aggregated size of client payload as the result.
StreamingInputCall(ctx context.Context, opts ...grpc.CallOption) (TestService_StreamingInputCallClient, error)
// A sequence of requests with each request served by the server immediately.
// As one request could lead to multiple responses, this interface
// demonstrates the idea of full duplexing.
FullDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_FullDuplexCallClient, error)
// A sequence of requests followed by a sequence of responses.
// The server buffers all the client requests and then serves them in order. A
// stream of responses are returned to the client when the server starts with
// first request.
HalfDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_HalfDuplexCallClient, error)
}
type testServiceClient struct {
cc grpc.ClientConnInterface
}
func NewTestServiceClient(cc grpc.ClientConnInterface) TestServiceClient {
return &testServiceClient{cc}
}
func (c *testServiceClient) EmptyCall(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) {
out := new(Empty)
err := c.cc.Invoke(ctx, "/testing.TestService/EmptyCall", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *testServiceClient) UnaryCall(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (*SimpleResponse, error) {
out := new(SimpleResponse)
err := c.cc.Invoke(ctx, "/testing.TestService/UnaryCall", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *testServiceClient) StreamingOutputCall(ctx context.Context, in *StreamingOutputCallRequest, opts ...grpc.CallOption) (TestService_StreamingOutputCallClient, error) {
stream, err := c.cc.NewStream(ctx, &TestService_ServiceDesc.Streams[0], "/testing.TestService/StreamingOutputCall", opts...)
if err != nil {
return nil, err
}
x := &testServiceStreamingOutputCallClient{stream}
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
}
type TestService_StreamingOutputCallClient interface {
Recv() (*StreamingOutputCallResponse, error)
grpc.ClientStream
}
type testServiceStreamingOutputCallClient struct {
grpc.ClientStream
}
func (x *testServiceStreamingOutputCallClient) Recv() (*StreamingOutputCallResponse, error) {
m := new(StreamingOutputCallResponse)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *testServiceClient) StreamingInputCall(ctx context.Context, opts ...grpc.CallOption) (TestService_StreamingInputCallClient, error) {
stream, err := c.cc.NewStream(ctx, &TestService_ServiceDesc.Streams[1], "/testing.TestService/StreamingInputCall", opts...)
if err != nil {
return nil, err
}
x := &testServiceStreamingInputCallClient{stream}
return x, nil
}
type TestService_StreamingInputCallClient interface {
Send(*StreamingInputCallRequest) error
CloseAndRecv() (*StreamingInputCallResponse, error)
grpc.ClientStream
}
type testServiceStreamingInputCallClient struct {
grpc.ClientStream
}
func (x *testServiceStreamingInputCallClient) Send(m *StreamingInputCallRequest) error {
return x.ClientStream.SendMsg(m)
}
func (x *testServiceStreamingInputCallClient) CloseAndRecv() (*StreamingInputCallResponse, error) {
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
m := new(StreamingInputCallResponse)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *testServiceClient) FullDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_FullDuplexCallClient, error) {
stream, err := c.cc.NewStream(ctx, &TestService_ServiceDesc.Streams[2], "/testing.TestService/FullDuplexCall", opts...)
if err != nil {
return nil, err
}
x := &testServiceFullDuplexCallClient{stream}
return x, nil
}
type TestService_FullDuplexCallClient interface {
Send(*StreamingOutputCallRequest) error
Recv() (*StreamingOutputCallResponse, error)
grpc.ClientStream
}
type testServiceFullDuplexCallClient struct {
grpc.ClientStream
}
func (x *testServiceFullDuplexCallClient) Send(m *StreamingOutputCallRequest) error {
return x.ClientStream.SendMsg(m)
}
func (x *testServiceFullDuplexCallClient) Recv() (*StreamingOutputCallResponse, error) {
m := new(StreamingOutputCallResponse)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *testServiceClient) HalfDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_HalfDuplexCallClient, error) {
stream, err := c.cc.NewStream(ctx, &TestService_ServiceDesc.Streams[3], "/testing.TestService/HalfDuplexCall", opts...)
if err != nil {
return nil, err
}
x := &testServiceHalfDuplexCallClient{stream}
return x, nil
}
type TestService_HalfDuplexCallClient interface {
Send(*StreamingOutputCallRequest) error
Recv() (*StreamingOutputCallResponse, error)
grpc.ClientStream
}
type testServiceHalfDuplexCallClient struct {
grpc.ClientStream
}
func (x *testServiceHalfDuplexCallClient) Send(m *StreamingOutputCallRequest) error {
return x.ClientStream.SendMsg(m)
}
func (x *testServiceHalfDuplexCallClient) Recv() (*StreamingOutputCallResponse, error) {
m := new(StreamingOutputCallResponse)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
// TestServiceServer is the server API for TestService service.
// All implementations must embed UnimplementedTestServiceServer
// for forward compatibility
type TestServiceServer interface {
// One empty request followed by one empty response.
EmptyCall(context.Context, *Empty) (*Empty, error)
// One request followed by one response.
// The server returns the client payload as-is.
UnaryCall(context.Context, *SimpleRequest) (*SimpleResponse, error)
// One request followed by a sequence of responses (streamed download).
// The server returns the payload with client desired type and sizes.
StreamingOutputCall(*StreamingOutputCallRequest, TestService_StreamingOutputCallServer) error
// A sequence of requests followed by one response (streamed upload).
// The server returns the aggregated size of client payload as the result.
StreamingInputCall(TestService_StreamingInputCallServer) error
// A sequence of requests with each request served by the server immediately.
// As one request could lead to multiple responses, this interface
// demonstrates the idea of full duplexing.
FullDuplexCall(TestService_FullDuplexCallServer) error
// A sequence of requests followed by a sequence of responses.
// The server buffers all the client requests and then serves them in order. A
// stream of responses are returned to the client when the server starts with
// first request.
HalfDuplexCall(TestService_HalfDuplexCallServer) error
mustEmbedUnimplementedTestServiceServer()
}
// UnimplementedTestServiceServer must be embedded to have forward compatible implementations.
type UnimplementedTestServiceServer struct {
}
func (UnimplementedTestServiceServer) EmptyCall(context.Context, *Empty) (*Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method EmptyCall not implemented")
}
func (UnimplementedTestServiceServer) UnaryCall(context.Context, *SimpleRequest) (*SimpleResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method UnaryCall not implemented")
}
func (UnimplementedTestServiceServer) StreamingOutputCall(*StreamingOutputCallRequest, TestService_StreamingOutputCallServer) error {
return status.Errorf(codes.Unimplemented, "method StreamingOutputCall not implemented")
}
func (UnimplementedTestServiceServer) StreamingInputCall(TestService_StreamingInputCallServer) error {
return status.Errorf(codes.Unimplemented, "method StreamingInputCall not implemented")
}
func (UnimplementedTestServiceServer) FullDuplexCall(TestService_FullDuplexCallServer) error {
return status.Errorf(codes.Unimplemented, "method FullDuplexCall not implemented")
}
func (UnimplementedTestServiceServer) HalfDuplexCall(TestService_HalfDuplexCallServer) error {
return status.Errorf(codes.Unimplemented, "method HalfDuplexCall not implemented")
}
func (UnimplementedTestServiceServer) mustEmbedUnimplementedTestServiceServer() {}
// UnsafeTestServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to TestServiceServer will
// result in compilation errors.
type UnsafeTestServiceServer interface {
mustEmbedUnimplementedTestServiceServer()
}
func RegisterTestServiceServer(s grpc.ServiceRegistrar, srv TestServiceServer) {
s.RegisterService(&TestService_ServiceDesc, srv)
}
func _TestService_EmptyCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Empty)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TestServiceServer).EmptyCall(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/testing.TestService/EmptyCall",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TestServiceServer).EmptyCall(ctx, req.(*Empty))
}
return interceptor(ctx, in, info, handler)
}
func _TestService_UnaryCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SimpleRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TestServiceServer).UnaryCall(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/testing.TestService/UnaryCall",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TestServiceServer).UnaryCall(ctx, req.(*SimpleRequest))
}
return interceptor(ctx, in, info, handler)
}
func _TestService_StreamingOutputCall_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(StreamingOutputCallRequest)
if err := stream.RecvMsg(m); err != nil {
return err
}
return srv.(TestServiceServer).StreamingOutputCall(m, &testServiceStreamingOutputCallServer{stream})
}
type TestService_StreamingOutputCallServer interface {
Send(*StreamingOutputCallResponse) error
grpc.ServerStream
}
type testServiceStreamingOutputCallServer struct {
grpc.ServerStream
}
func (x *testServiceStreamingOutputCallServer) Send(m *StreamingOutputCallResponse) error {
return x.ServerStream.SendMsg(m)
}
func _TestService_StreamingInputCall_Handler(srv interface{}, stream grpc.ServerStream) error {
return srv.(TestServiceServer).StreamingInputCall(&testServiceStreamingInputCallServer{stream})
}
type TestService_StreamingInputCallServer interface {
SendAndClose(*StreamingInputCallResponse) error
Recv() (*StreamingInputCallRequest, error)
grpc.ServerStream
}
type testServiceStreamingInputCallServer struct {
grpc.ServerStream
}
func (x *testServiceStreamingInputCallServer) SendAndClose(m *StreamingInputCallResponse) error {
return x.ServerStream.SendMsg(m)
}
func (x *testServiceStreamingInputCallServer) Recv() (*StreamingInputCallRequest, error) {
m := new(StreamingInputCallRequest)
if err := x.ServerStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func _TestService_FullDuplexCall_Handler(srv interface{}, stream grpc.ServerStream) error {
return srv.(TestServiceServer).FullDuplexCall(&testServiceFullDuplexCallServer{stream})
}
type TestService_FullDuplexCallServer interface {
Send(*StreamingOutputCallResponse) error
Recv() (*StreamingOutputCallRequest, error)
grpc.ServerStream
}
type testServiceFullDuplexCallServer struct {
grpc.ServerStream
}
func (x *testServiceFullDuplexCallServer) Send(m *StreamingOutputCallResponse) error {
return x.ServerStream.SendMsg(m)
}
func (x *testServiceFullDuplexCallServer) Recv() (*StreamingOutputCallRequest, error) {
m := new(StreamingOutputCallRequest)
if err := x.ServerStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func _TestService_HalfDuplexCall_Handler(srv interface{}, stream grpc.ServerStream) error {
return srv.(TestServiceServer).HalfDuplexCall(&testServiceHalfDuplexCallServer{stream})
}
type TestService_HalfDuplexCallServer interface {
Send(*StreamingOutputCallResponse) error
Recv() (*StreamingOutputCallRequest, error)
grpc.ServerStream
}
type testServiceHalfDuplexCallServer struct {
grpc.ServerStream
}
func (x *testServiceHalfDuplexCallServer) Send(m *StreamingOutputCallResponse) error {
return x.ServerStream.SendMsg(m)
}
func (x *testServiceHalfDuplexCallServer) Recv() (*StreamingOutputCallRequest, error) {
m := new(StreamingOutputCallRequest)
if err := x.ServerStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
// TestService_ServiceDesc is the grpc.ServiceDesc for TestService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var TestService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "testing.TestService",
HandlerType: (*TestServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "EmptyCall",
Handler: _TestService_EmptyCall_Handler,
},
{
MethodName: "UnaryCall",
Handler: _TestService_UnaryCall_Handler,
},
},
Streams: []grpc.StreamDesc{
{
StreamName: "StreamingOutputCall",
Handler: _TestService_StreamingOutputCall_Handler,
ServerStreams: true,
},
{
StreamName: "StreamingInputCall",
Handler: _TestService_StreamingInputCall_Handler,
ClientStreams: true,
},
{
StreamName: "FullDuplexCall",
Handler: _TestService_FullDuplexCall_Handler,
ServerStreams: true,
ClientStreams: true,
},
{
StreamName: "HalfDuplexCall",
Handler: _TestService_HalfDuplexCall_Handler,
ServerStreams: true,
ClientStreams: true,
},
},
Metadata: "test.proto",
}
// UnimplementedServiceClient is the client API for UnimplementedService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type UnimplementedServiceClient interface {
// A call that no server should implement
UnimplementedCall(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error)
}
type unimplementedServiceClient struct {
cc grpc.ClientConnInterface
}
func NewUnimplementedServiceClient(cc grpc.ClientConnInterface) UnimplementedServiceClient {
return &unimplementedServiceClient{cc}
}
func (c *unimplementedServiceClient) UnimplementedCall(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) {
out := new(Empty)
err := c.cc.Invoke(ctx, "/testing.UnimplementedService/UnimplementedCall", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// UnimplementedServiceServer is the server API for UnimplementedService service.
// All implementations must embed UnimplementedUnimplementedServiceServer
// for forward compatibility
type UnimplementedServiceServer interface {
// A call that no server should implement
UnimplementedCall(context.Context, *Empty) (*Empty, error)
mustEmbedUnimplementedUnimplementedServiceServer()
}
// UnimplementedUnimplementedServiceServer must be embedded to have forward compatible implementations.
type UnimplementedUnimplementedServiceServer struct {
}
func (UnimplementedUnimplementedServiceServer) UnimplementedCall(context.Context, *Empty) (*Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method UnimplementedCall not implemented")
}
func (UnimplementedUnimplementedServiceServer) mustEmbedUnimplementedUnimplementedServiceServer() {}
// UnsafeUnimplementedServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to UnimplementedServiceServer will
// result in compilation errors.
type UnsafeUnimplementedServiceServer interface {
mustEmbedUnimplementedUnimplementedServiceServer()
}
func RegisterUnimplementedServiceServer(s grpc.ServiceRegistrar, srv UnimplementedServiceServer) {
s.RegisterService(&UnimplementedService_ServiceDesc, srv)
}
func _UnimplementedService_UnimplementedCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Empty)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(UnimplementedServiceServer).UnimplementedCall(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/testing.UnimplementedService/UnimplementedCall",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(UnimplementedServiceServer).UnimplementedCall(ctx, req.(*Empty))
}
return interceptor(ctx, in, info, handler)
}
// UnimplementedService_ServiceDesc is the grpc.ServiceDesc for UnimplementedService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var UnimplementedService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "testing.UnimplementedService",
HandlerType: (*UnimplementedServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "UnimplementedCall",
Handler: _UnimplementedService_UnimplementedCall_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "test.proto",
}

View File

@@ -1,14 +1,17 @@
package testing
//go:generate protoc --go_out=. --go-grpc_out=. test.proto
//go:generate protoc --descriptor_set_out=./test.protoset test.proto
//go:generate protoc --descriptor_set_out=./example.protoset --include_imports example.proto
import (
"context"
"io"
"strconv"
"time"
"golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/interop/grpc_testing"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
@@ -16,10 +19,12 @@ import (
)
// TestServer implements the TestService interface defined in example.proto.
type TestServer struct{}
type TestServer struct {
UnimplementedTestServiceServer
}
// EmptyCall accepts one empty request and issues one empty response.
func (TestServer) EmptyCall(ctx context.Context, req *grpc_testing.Empty) (*grpc_testing.Empty, error) {
func (TestServer) EmptyCall(ctx context.Context, req *Empty) (*Empty, error) {
headers, trailers, failEarly, failLate := processMetadata(ctx)
grpc.SetHeader(ctx, headers)
grpc.SetTrailer(ctx, trailers)
@@ -35,7 +40,7 @@ func (TestServer) EmptyCall(ctx context.Context, req *grpc_testing.Empty) (*grpc
// UnaryCall accepts one request and issues one response. The response includes
// the client's payload as-is.
func (TestServer) UnaryCall(ctx context.Context, req *grpc_testing.SimpleRequest) (*grpc_testing.SimpleResponse, error) {
func (TestServer) UnaryCall(ctx context.Context, req *SimpleRequest) (*SimpleResponse, error) {
headers, trailers, failEarly, failLate := processMetadata(ctx)
grpc.SetHeader(ctx, headers)
grpc.SetTrailer(ctx, trailers)
@@ -46,7 +51,7 @@ func (TestServer) UnaryCall(ctx context.Context, req *grpc_testing.SimpleRequest
return nil, status.Error(failLate, "fail")
}
return &grpc_testing.SimpleResponse{
return &SimpleResponse{
Payload: req.Payload,
}, nil
}
@@ -54,7 +59,7 @@ func (TestServer) UnaryCall(ctx context.Context, req *grpc_testing.SimpleRequest
// StreamingOutputCall accepts one request and issues a sequence of responses
// (streamed download). The server returns the payload with client desired type
// and sizes as specified in the request's ResponseParameters.
func (TestServer) StreamingOutputCall(req *grpc_testing.StreamingOutputCallRequest, str grpc_testing.TestService_StreamingOutputCallServer) error {
func (TestServer) StreamingOutputCall(req *StreamingOutputCallRequest, str TestService_StreamingOutputCallServer) error {
headers, trailers, failEarly, failLate := processMetadata(str.Context())
str.SetHeader(headers)
str.SetTrailer(trailers)
@@ -62,7 +67,7 @@ func (TestServer) StreamingOutputCall(req *grpc_testing.StreamingOutputCallReque
return status.Error(failEarly, "fail")
}
rsp := &grpc_testing.StreamingOutputCallResponse{Payload: &grpc_testing.Payload{}}
rsp := &StreamingOutputCallResponse{Payload: &Payload{}}
for _, param := range req.ResponseParameters {
if str.Context().Err() != nil {
return str.Context().Err()
@@ -92,7 +97,7 @@ func (TestServer) StreamingOutputCall(req *grpc_testing.StreamingOutputCallReque
// StreamingInputCall accepts a sequence of requests and issues one response
// (streamed upload). The server returns the aggregated size of client payloads
// as the result.
func (TestServer) StreamingInputCall(str grpc_testing.TestService_StreamingInputCallServer) error {
func (TestServer) StreamingInputCall(str TestService_StreamingInputCallServer) error {
headers, trailers, failEarly, failLate := processMetadata(str.Context())
str.SetHeader(headers)
str.SetTrailer(trailers)
@@ -114,7 +119,7 @@ func (TestServer) StreamingInputCall(str grpc_testing.TestService_StreamingInput
sz += len(req.Payload.Body)
}
}
if err := str.SendAndClose(&grpc_testing.StreamingInputCallResponse{AggregatedPayloadSize: int32(sz)}); err != nil {
if err := str.SendAndClose(&StreamingInputCallResponse{AggregatedPayloadSize: int32(sz)}); err != nil {
return err
}
@@ -127,7 +132,7 @@ func (TestServer) StreamingInputCall(str grpc_testing.TestService_StreamingInput
// FullDuplexCall accepts a sequence of requests with each request served by the
// server immediately. As one request could lead to multiple responses, this
// interface demonstrates the idea of full duplexing.
func (TestServer) FullDuplexCall(str grpc_testing.TestService_FullDuplexCallServer) error {
func (TestServer) FullDuplexCall(str TestService_FullDuplexCallServer) error {
headers, trailers, failEarly, failLate := processMetadata(str.Context())
str.SetHeader(headers)
str.SetTrailer(trailers)
@@ -135,7 +140,7 @@ func (TestServer) FullDuplexCall(str grpc_testing.TestService_FullDuplexCallServ
return status.Error(failEarly, "fail")
}
rsp := &grpc_testing.StreamingOutputCallResponse{Payload: &grpc_testing.Payload{}}
rsp := &StreamingOutputCallResponse{Payload: &Payload{}}
for {
if str.Context().Err() != nil {
return str.Context().Err()
@@ -170,7 +175,7 @@ func (TestServer) FullDuplexCall(str grpc_testing.TestService_FullDuplexCallServ
// responses. The server buffers all the client requests and then serves them
// in order. A stream of responses is returned to the client once the client
// half-closes the stream.
func (TestServer) HalfDuplexCall(str grpc_testing.TestService_HalfDuplexCallServer) error {
func (TestServer) HalfDuplexCall(str TestService_HalfDuplexCallServer) error {
headers, trailers, failEarly, failLate := processMetadata(str.Context())
str.SetHeader(headers)
str.SetTrailer(trailers)
@@ -178,7 +183,7 @@ func (TestServer) HalfDuplexCall(str grpc_testing.TestService_HalfDuplexCallServ
return status.Error(failEarly, "fail")
}
var reqs []*grpc_testing.StreamingOutputCallRequest
var reqs []*StreamingOutputCallRequest
for {
if str.Context().Err() != nil {
return str.Context().Err()
@@ -192,7 +197,7 @@ func (TestServer) HalfDuplexCall(str grpc_testing.TestService_HalfDuplexCallServ
reqs = append(reqs, req)
}
}
rsp := &grpc_testing.StreamingOutputCallResponse{}
rsp := &StreamingOutputCallResponse{}
for _, req := range reqs {
rsp.Payload = req.Payload
if err := str.Send(rsp); err != nil {
@@ -251,4 +256,4 @@ func toCode(vals []string) codes.Code {
return codes.Code(i)
}
var _ grpc_testing.TestServiceServer = TestServer{}
var _ TestServiceServer = TestServer{}

View File

@@ -2,19 +2,19 @@ package grpcurl
import (
"bytes"
"context"
"fmt"
"io"
"strings"
"sync"
"sync/atomic"
"github.com/golang/protobuf/jsonpb"
"github.com/golang/protobuf/proto"
"github.com/golang/protobuf/jsonpb" //lint:ignore SA1019 we have to import this because it appears in exported API
"github.com/golang/protobuf/proto" //lint:ignore SA1019 we have to import this because it appears in exported API
"github.com/jhump/protoreflect/desc"
"github.com/jhump/protoreflect/dynamic"
"github.com/jhump/protoreflect/dynamic/grpcdynamic"
"github.com/jhump/protoreflect/grpcreflect"
"golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
@@ -93,9 +93,17 @@ func InvokeRPC(ctx context.Context, source DescriptorSource, ch grpcdynamic.Chan
if svc == "" || mth == "" {
return fmt.Errorf("given method name %q is not in expected format: 'service/method' or 'service.method'", methodName)
}
dsc, err := source.FindSymbol(svc)
if err != nil {
if isNotFoundError(err) {
// return a gRPC status error if hasStatus is true
errStatus, hasStatus := status.FromError(err)
switch {
case hasStatus && isNotFoundError(err):
return status.Errorf(errStatus.Code(), "target server does not expose service %q: %s", svc, errStatus.Message())
case hasStatus:
return status.Errorf(errStatus.Code(), "failed to query for service descriptor %q: %s", svc, errStatus.Message())
case isNotFoundError(err):
return fmt.Errorf("target server does not expose service %q", svc)
}
return fmt.Errorf("failed to query for service descriptor %q: %v", svc, err)
@@ -219,15 +227,19 @@ func invokeClientStream(ctx context.Context, stub grpcdynamic.Stub, md *desc.Met
return fmt.Errorf("grpc call for %q failed: %v", md.GetFullyQualifiedName(), err)
}
if respHeaders, err := str.Header(); err == nil {
handler.OnReceiveHeaders(respHeaders)
if str != nil {
if respHeaders, err := str.Header(); err == nil {
handler.OnReceiveHeaders(respHeaders)
}
}
if stat.Code() == codes.OK {
handler.OnReceiveResponse(resp)
}
handler.OnReceiveTrailers(stat, str.Trailer())
if str != nil {
handler.OnReceiveTrailers(stat, str.Trailer())
}
return nil
}
@@ -252,8 +264,10 @@ func invokeServerStream(ctx context.Context, stub grpcdynamic.Stub, md *desc.Met
// Now we can actually invoke the RPC!
str, err := stub.InvokeRpcServerStream(ctx, md, req)
if respHeaders, err := str.Header(); err == nil {
handler.OnReceiveHeaders(respHeaders)
if str != nil {
if respHeaders, err := str.Header(); err == nil {
handler.OnReceiveHeaders(respHeaders)
}
}
// Download each response message
@@ -276,7 +290,9 @@ func invokeServerStream(ctx context.Context, stub grpcdynamic.Stub, md *desc.Met
return fmt.Errorf("grpc call for %q failed: %v", md.GetFullyQualifiedName(), err)
}
handler.OnReceiveTrailers(stat, str.Trailer())
if str != nil {
handler.OnReceiveTrailers(stat, str.Trailer())
}
return nil
}
@@ -326,8 +342,10 @@ func invokeBidi(ctx context.Context, stub grpcdynamic.Stub, md *desc.MethodDescr
}()
}
if respHeaders, err := str.Header(); err == nil {
handler.OnReceiveHeaders(respHeaders)
if str != nil {
if respHeaders, err := str.Header(); err == nil {
handler.OnReceiveHeaders(respHeaders)
}
}
// Download each response message
@@ -354,7 +372,9 @@ func invokeBidi(ctx context.Context, stub grpcdynamic.Stub, md *desc.MethodDescr
return fmt.Errorf("grpc call for %q failed: %v", md.GetFullyQualifiedName(), err)
}
handler.OnReceiveTrailers(stat, str.Trailer())
if str != nil {
handler.OnReceiveTrailers(stat, str.Trailer())
}
return nil
}

View File

@@ -15,6 +15,9 @@ protoc testing/example.proto \
--include_imports \
--descriptor_set_out=testing/example.protoset
protoc testing/jsonpb_test_proto/test_objects.proto \
--go_out=paths=source_relative:.
echo "Creating certs for TLS testing..."
if ! hash certstrap 2>/dev/null; then
# certstrap not found: try to install it

79
releasing/README.md Normal file
View File

@@ -0,0 +1,79 @@
# Releases of gRPCurl
This document provides instructions for building a release of `grpcurl`.
The release process consists of a handful of tasks:
1. Drop a release tag in git.
2. Build binaries for various platforms. This is done using the local `go` tool and uses `GOOS` and `GOARCH` environment variables to cross-compile for supported platforms.
3. Creates a release in GitHub, uploads the binaries, and creates provisional release notes (in the form of a change log).
4. Build a docker image for the new release.
5. Push the docker image to Docker Hub, with both a version tag and the "latest" tag.
6. Submits a PR to update the [Homebrew](https://brew.sh/) recipe with the latest version.
Most of this is automated via a script in this same directory. The main thing you will need is a GitHub personal access token, which will be used for creating the release in GitHub (so you need write access to the fullstorydev/grpcurl repo) and to open a Homebrew pull request.
## Creating a new release
So, to actually create a new release, just run the script in this directory.
First, you need a version number for the new release, following sem-ver format: `v<Major>.<Minor>.<Patch>`. Second, you need a personal access token for GitHub.
We'll use `v2.3.4` as an example version and `abcdef0123456789abcdef` as an example GitHub token:
```sh
# from the root of the repo
GITHUB_TOKEN=abcdef0123456789abcd \
./releasing/do-release.sh v2.3.4
```
Wasn't that easy! There is one last step: update the release notes in GitHub. By default, the script just records a change log of commit descriptions. Use that log (and, if necessary, drill into individual PRs included in the release) to flesh out notes in the format of the `RELEASE_NOTES.md` file _in this directory_. Then login to GitHub, go to the new release, edit the notes, and paste in the markdown you just wrote.
That should be all there is to it! If things go wrong and you have to re-do part of the process, see the sections below.
----
### GitHub Releases
The GitHub release is the first step performed by the `do-release.sh` script. So generally, if there is an issue with that step, you can re-try the whole script.
Note, if running the script did something wrong, you may have to first login to GitHub and remove uploaded artifacts for a botched release attempt. In general, this is _very undesirable_. Releases should usually be considered immutable. Instead of removing uploaded assets and providing new ones, it is often better to remove uploaded assets (to make bad binaries no longer available) and then _release a new patch version_. (You can edit the release notes for the botched version explaining why there are no artifacts for it.)
The steps to do a GitHub-only release (vs. running the entire script) are the following:
```sh
# from the root of the repo
git tag v2.3.4
GITHUB_TOKEN=abcdef0123456789abcdef \
GO111MODULE=on \
make release
```
The `git tag ...` step is necessary because the release target requires that the current SHA have a sem-ver tag. That's the version it will use when creating the release.
This will create the release in GitHub with provisional release notes that just include a change log of commit messages. You still need to login to GitHub and revise those notes to adhere to the recommended format. (See `RELEASE_NOTES.md` in this directory.)
### Docker Hub Releases
To re-run only the Docker Hub release steps, you can manually run through each step in the "Docker" section of `do_release.sh`.
If the `docker push ...` steps fail, you may need to run `docker login`, enter your Docker Hub login credentials, and then try to push again.
### Homebrew Releases
The last step is to update the Homebrew recipe to use the latest version. First, we need to compute the SHA256 checksum for the source archive:
```sh
# download the source archive from GitHub
URL=https://github.com/fullstorydev/grpcurl/archive/v2.3.4.tar.gz
curl -L -o tmp.tgz $URL
# and compute the SHA
SHA="$(sha256sum < tmp.tgz | awk '{ print $1 }')"
```
To actually create the brew PR, you need your GitHub personal access token again, as well as the URL and SHA from the previous step:
```sh
HOMEBREW_GITHUB_API_TOKEN=abcdef0123456789abcdef \
brew bump-formula-pr --url $URL --sha256 $SHA grpcurl
```
This creates a PR to bump the formula to the new version. When this PR is merged by brew maintainers, the new version becomes available!

View File

@@ -0,0 +1,11 @@
## Changes
### Command-line tool
* _In this list, describe the changes to the command-line tool._
* _Use one bullet per change. Include both bug-fixes and improvements. Omit this section if there are no changes that impact the command-line tool._
### Go package "github.com/fullstorydev/grpcurl"
* _In this list, describe the changes to exported API in the main package in this repo: "github.com/fullstorydev/grpcurl". These will often be closely related to changes to the command-line tool, though not always: changes that only impact the cmd/grpcurl directory of this repo do not impact exported API._
* _Use one bullet per change. Include both bug-fixes and improvements. Omit this section if there are no changes that impact the exported API._

62
releasing/do-release.sh Executable file
View File

@@ -0,0 +1,62 @@
#!/bin/bash
# strict mode
set -euo pipefail
IFS=$'\n\t'
if [[ -z ${DRY_RUN:-} ]]; then
PREFIX=""
else
PREFIX="echo"
fi
# input validation
if [[ -z ${GITHUB_TOKEN:-} ]]; then
echo "GITHUB_TOKEN environment variable must be set before running." >&2
exit 1
fi
if [[ $# -ne 1 || $1 == "" ]]; then
echo "This program requires one argument: the version number, in 'vM.N.P' format." >&2
exit 1
fi
VERSION=$1
# Change to root of the repo
cd "$(dirname "$0")/.."
# GitHub release
$PREFIX git tag "$VERSION"
# make sure GITHUB_TOKEN is exported, for the benefit of this next command
export GITHUB_TOKEN
GO111MODULE=on $PREFIX make release
# if that was successful, it could have touched go.mod and go.sum, so revert those
$PREFIX git checkout go.mod go.sum
# Docker release
# make sure credentials are valid for later push steps; this might
# be interactive since this will prompt for username and password
# if there are no valid current credentials.
$PREFIX docker login
echo "$VERSION" > VERSION
# Docker Buildx support is included in Docker 19.03
# Below step installs emulators for different architectures on the host
# This enables running and building containers for below architectures mentioned using --platforms
$PREFIX docker run --privileged --rm tonistiigi/binfmt:qemu-v6.1.0 --install all
# Create a new builder instance
export DOCKER_CLI_EXPERIMENTAL=enabled
$PREFIX docker buildx create --use --name multiarch-builder --node multiarch-builder0
# push to docker hub, both the given version as a tag and for "latest" tag
$PREFIX docker buildx build --platform linux/amd64,linux/s390x,linux/arm64,linux/ppc64le --tag fullstorydev/grpcurl:${VERSION} --tag fullstorydev/grpcurl:latest --push --progress plain --no-cache .
$PREFIX docker buildx build --platform linux/amd64,linux/s390x,linux/arm64,linux/ppc64le --tag fullstorydev/grpcurl:${VERSION}-alpine --tag fullstorydev/grpcurl:latest-alpine --push --progress plain --no-cache --target alpine .
rm VERSION
# Homebrew release
URL="https://github.com/fullstorydev/grpcurl/archive/${VERSION}.tar.gz"
curl -L -o tmp.tgz "$URL"
SHA="$(sha256sum < tmp.tgz | awk '{ print $1 }')"
rm tmp.tgz
HOMEBREW_GITHUB_API_TOKEN="$GITHUB_TOKEN" $PREFIX brew bump-formula-pr --url "$URL" --sha256 "$SHA" grpcurl

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -1,19 +1,18 @@
package grpcurl_test
import (
"context"
"fmt"
"net"
"strings"
"testing"
"time"
"golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/interop/grpc_testing"
. "github.com/fullstorydev/grpcurl"
grpcurl_testing "github.com/fullstorydev/grpcurl/testing"
grpcurl_testing "github.com/fullstorydev/grpcurl/internal/testing"
)
func TestPlainText(t *testing.T) {
@@ -27,11 +26,11 @@ func TestPlainText(t *testing.T) {
}
func TestBasicTLS(t *testing.T) {
serverCreds, err := ServerTransportCredentials("", "testing/tls/server.crt", "testing/tls/server.key", false)
serverCreds, err := ServerTransportCredentials("", "internal/testing/tls/server.crt", "internal/testing/tls/server.key", false)
if err != nil {
t.Fatalf("failed to create server creds: %v", err)
}
clientCreds, err := ClientTransportCredentials(false, "testing/tls/ca.crt", "", "")
clientCreds, err := ClientTransportCredentials(false, "internal/testing/tls/ca.crt", "", "")
if err != nil {
t.Fatalf("failed to create server creds: %v", err)
}
@@ -46,7 +45,7 @@ func TestBasicTLS(t *testing.T) {
}
func TestInsecureClientTLS(t *testing.T) {
serverCreds, err := ServerTransportCredentials("", "testing/tls/server.crt", "testing/tls/server.key", false)
serverCreds, err := ServerTransportCredentials("", "internal/testing/tls/server.crt", "internal/testing/tls/server.key", false)
if err != nil {
t.Fatalf("failed to create server creds: %v", err)
}
@@ -65,11 +64,11 @@ func TestInsecureClientTLS(t *testing.T) {
}
func TestClientCertTLS(t *testing.T) {
serverCreds, err := ServerTransportCredentials("testing/tls/ca.crt", "testing/tls/server.crt", "testing/tls/server.key", false)
serverCreds, err := ServerTransportCredentials("internal/testing/tls/ca.crt", "internal/testing/tls/server.crt", "internal/testing/tls/server.key", false)
if err != nil {
t.Fatalf("failed to create server creds: %v", err)
}
clientCreds, err := ClientTransportCredentials(false, "testing/tls/ca.crt", "testing/tls/client.crt", "testing/tls/client.key")
clientCreds, err := ClientTransportCredentials(false, "internal/testing/tls/ca.crt", "internal/testing/tls/client.crt", "internal/testing/tls/client.key")
if err != nil {
t.Fatalf("failed to create server creds: %v", err)
}
@@ -84,11 +83,11 @@ func TestClientCertTLS(t *testing.T) {
}
func TestRequireClientCertTLS(t *testing.T) {
serverCreds, err := ServerTransportCredentials("testing/tls/ca.crt", "testing/tls/server.crt", "testing/tls/server.key", true)
serverCreds, err := ServerTransportCredentials("internal/testing/tls/ca.crt", "internal/testing/tls/server.crt", "internal/testing/tls/server.key", true)
if err != nil {
t.Fatalf("failed to create server creds: %v", err)
}
clientCreds, err := ClientTransportCredentials(false, "testing/tls/ca.crt", "testing/tls/client.crt", "testing/tls/client.key")
clientCreds, err := ClientTransportCredentials(false, "internal/testing/tls/ca.crt", "internal/testing/tls/client.crt", "internal/testing/tls/client.key")
if err != nil {
t.Fatalf("failed to create server creds: %v", err)
}
@@ -103,7 +102,7 @@ func TestRequireClientCertTLS(t *testing.T) {
}
func TestBrokenTLS_ClientPlainText(t *testing.T) {
serverCreds, err := ServerTransportCredentials("", "testing/tls/server.crt", "testing/tls/server.key", false)
serverCreds, err := ServerTransportCredentials("", "internal/testing/tls/server.crt", "internal/testing/tls/server.key", false)
if err != nil {
t.Fatalf("failed to create server creds: %v", err)
}
@@ -148,8 +147,8 @@ func TestBrokenTLS_ClientPlainText(t *testing.T) {
// but request fails because server closes connection upon seeing request
// bytes that are not a TLS handshake
cl := grpc_testing.NewTestServiceClient(e.cc)
_, err = cl.UnaryCall(context.Background(), &grpc_testing.SimpleRequest{})
cl := grpcurl_testing.NewTestServiceClient(e.cc)
_, err = cl.UnaryCall(context.Background(), &grpcurl_testing.SimpleRequest{})
if err == nil {
t.Fatal("expecting failure")
}
@@ -164,15 +163,15 @@ func TestBrokenTLS_ClientPlainText(t *testing.T) {
}
func TestBrokenTLS_ServerPlainText(t *testing.T) {
clientCreds, err := ClientTransportCredentials(false, "testing/tls/ca.crt", "", "")
clientCreds, err := ClientTransportCredentials(false, "internal/testing/tls/ca.crt", "", "")
if err != nil {
t.Fatalf("failed to create server creds: %v", err)
}
e, err := createTestServerAndClient(nil, clientCreds)
if err == nil {
t.Fatal("expecting TLS failure setting up server and client")
e.Close()
t.Fatal("expecting TLS failure setting up server and client")
}
if !strings.Contains(err.Error(), "first record does not look like a TLS handshake") {
t.Fatalf("expecting TLS handshake failure, got: %v", err)
@@ -180,19 +179,19 @@ func TestBrokenTLS_ServerPlainText(t *testing.T) {
}
func TestBrokenTLS_ServerUsesWrongCert(t *testing.T) {
serverCreds, err := ServerTransportCredentials("", "testing/tls/other.crt", "testing/tls/other.key", false)
serverCreds, err := ServerTransportCredentials("", "internal/testing/tls/other.crt", "internal/testing/tls/other.key", false)
if err != nil {
t.Fatalf("failed to create server creds: %v", err)
}
clientCreds, err := ClientTransportCredentials(false, "testing/tls/ca.crt", "", "")
clientCreds, err := ClientTransportCredentials(false, "internal/testing/tls/ca.crt", "", "")
if err != nil {
t.Fatalf("failed to create server creds: %v", err)
}
e, err := createTestServerAndClient(serverCreds, clientCreds)
if err == nil {
t.Fatal("expecting TLS failure setting up server and client")
e.Close()
t.Fatal("expecting TLS failure setting up server and client")
}
if !strings.Contains(err.Error(), "certificate is valid for") {
t.Fatalf("expecting TLS certificate error, got: %v", err)
@@ -200,39 +199,39 @@ func TestBrokenTLS_ServerUsesWrongCert(t *testing.T) {
}
func TestBrokenTLS_ClientHasExpiredCert(t *testing.T) {
serverCreds, err := ServerTransportCredentials("testing/tls/ca.crt", "testing/tls/server.crt", "testing/tls/server.key", false)
serverCreds, err := ServerTransportCredentials("internal/testing/tls/ca.crt", "internal/testing/tls/server.crt", "internal/testing/tls/server.key", false)
if err != nil {
t.Fatalf("failed to create server creds: %v", err)
}
clientCreds, err := ClientTransportCredentials(false, "testing/tls/ca.crt", "testing/tls/expired.crt", "testing/tls/expired.key")
clientCreds, err := ClientTransportCredentials(false, "internal/testing/tls/ca.crt", "internal/testing/tls/expired.crt", "internal/testing/tls/expired.key")
if err != nil {
t.Fatalf("failed to create server creds: %v", err)
}
e, err := createTestServerAndClient(serverCreds, clientCreds)
if err == nil {
t.Fatal("expecting TLS failure setting up server and client")
e.Close()
t.Fatal("expecting TLS failure setting up server and client")
}
if !strings.Contains(err.Error(), "bad certificate") {
if !strings.Contains(err.Error(), "certificate") {
t.Fatalf("expecting TLS certificate error, got: %v", err)
}
}
func TestBrokenTLS_ServerHasExpiredCert(t *testing.T) {
serverCreds, err := ServerTransportCredentials("", "testing/tls/expired.crt", "testing/tls/expired.key", false)
serverCreds, err := ServerTransportCredentials("", "internal/testing/tls/expired.crt", "internal/testing/tls/expired.key", false)
if err != nil {
t.Fatalf("failed to create server creds: %v", err)
}
clientCreds, err := ClientTransportCredentials(false, "testing/tls/ca.crt", "", "")
clientCreds, err := ClientTransportCredentials(false, "internal/testing/tls/ca.crt", "", "")
if err != nil {
t.Fatalf("failed to create server creds: %v", err)
}
e, err := createTestServerAndClient(serverCreds, clientCreds)
if err == nil {
t.Fatal("expecting TLS failure setting up server and client")
e.Close()
t.Fatal("expecting TLS failure setting up server and client")
}
if !strings.Contains(err.Error(), "certificate has expired or is not yet valid") {
t.Fatalf("expecting TLS certificate expired, got: %v", err)
@@ -240,19 +239,19 @@ func TestBrokenTLS_ServerHasExpiredCert(t *testing.T) {
}
func TestBrokenTLS_ClientNotTrusted(t *testing.T) {
serverCreds, err := ServerTransportCredentials("testing/tls/ca.crt", "testing/tls/server.crt", "testing/tls/server.key", true)
serverCreds, err := ServerTransportCredentials("internal/testing/tls/ca.crt", "internal/testing/tls/server.crt", "internal/testing/tls/server.key", true)
if err != nil {
t.Fatalf("failed to create server creds: %v", err)
}
clientCreds, err := ClientTransportCredentials(false, "testing/tls/ca.crt", "testing/tls/wrong-client.crt", "testing/tls/wrong-client.key")
clientCreds, err := ClientTransportCredentials(false, "internal/testing/tls/ca.crt", "internal/testing/tls/wrong-client.crt", "internal/testing/tls/wrong-client.key")
if err != nil {
t.Fatalf("failed to create server creds: %v", err)
}
e, err := createTestServerAndClient(serverCreds, clientCreds)
if err == nil {
t.Fatal("expecting TLS failure setting up server and client")
e.Close()
t.Fatal("expecting TLS failure setting up server and client")
}
if !strings.Contains(err.Error(), "bad certificate") {
t.Fatalf("expecting TLS certificate error, got: %v", err)
@@ -260,39 +259,39 @@ func TestBrokenTLS_ClientNotTrusted(t *testing.T) {
}
func TestBrokenTLS_ServerNotTrusted(t *testing.T) {
serverCreds, err := ServerTransportCredentials("", "testing/tls/server.crt", "testing/tls/server.key", false)
serverCreds, err := ServerTransportCredentials("", "internal/testing/tls/server.crt", "internal/testing/tls/server.key", false)
if err != nil {
t.Fatalf("failed to create server creds: %v", err)
}
clientCreds, err := ClientTransportCredentials(false, "", "testing/tls/client.crt", "testing/tls/client.key")
clientCreds, err := ClientTransportCredentials(false, "", "internal/testing/tls/client.crt", "internal/testing/tls/client.key")
if err != nil {
t.Fatalf("failed to create server creds: %v", err)
}
e, err := createTestServerAndClient(serverCreds, clientCreds)
if err == nil {
t.Fatal("expecting TLS failure setting up server and client")
e.Close()
t.Fatal("expecting TLS failure setting up server and client")
}
if !strings.Contains(err.Error(), "certificate signed by unknown authority") {
if !strings.Contains(err.Error(), "certificate") {
t.Fatalf("expecting TLS certificate error, got: %v", err)
}
}
func TestBrokenTLS_RequireClientCertButNonePresented(t *testing.T) {
serverCreds, err := ServerTransportCredentials("testing/tls/ca.crt", "testing/tls/server.crt", "testing/tls/server.key", true)
serverCreds, err := ServerTransportCredentials("internal/testing/tls/ca.crt", "internal/testing/tls/server.crt", "internal/testing/tls/server.key", true)
if err != nil {
t.Fatalf("failed to create server creds: %v", err)
}
clientCreds, err := ClientTransportCredentials(false, "testing/tls/ca.crt", "", "")
clientCreds, err := ClientTransportCredentials(false, "internal/testing/tls/ca.crt", "", "")
if err != nil {
t.Fatalf("failed to create server creds: %v", err)
}
e, err := createTestServerAndClient(serverCreds, clientCreds)
if err == nil {
t.Fatal("expecting TLS failure setting up server and client")
e.Close()
t.Fatal("expecting TLS failure setting up server and client")
}
if !strings.Contains(err.Error(), "bad certificate") {
t.Fatalf("expecting TLS certificate error, got: %v", err)
@@ -300,10 +299,10 @@ func TestBrokenTLS_RequireClientCertButNonePresented(t *testing.T) {
}
func simpleTest(t *testing.T, cc *grpc.ClientConn) {
cl := grpc_testing.NewTestServiceClient(cc)
cl := grpcurl_testing.NewTestServiceClient(cc)
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
_, err := cl.UnaryCall(ctx, &grpc_testing.SimpleRequest{}, grpc.WaitForReady(true))
_, err := cl.UnaryCall(ctx, &grpcurl_testing.SimpleRequest{}, grpc.WaitForReady(true))
if err != nil {
t.Errorf("simple RPC failed: %v", err)
}
@@ -323,7 +322,7 @@ func createTestServerAndClient(serverCreds, clientCreds credentials.TransportCre
svrOpts = []grpc.ServerOption{grpc.Creds(serverCreds)}
}
svr := grpc.NewServer(svrOpts...)
grpc_testing.RegisterTestServiceServer(svr, grpcurl_testing.TestServer{})
grpcurl_testing.RegisterTestServiceServer(svr, grpcurl_testing.TestServer{})
l, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
return e, err
@@ -350,7 +349,7 @@ type testEnv struct {
cc *grpc.ClientConn
}
func (e testEnv) Close() {
func (e *testEnv) Close() {
if e.cc != nil {
e.cc.Close()
e.cc = nil