Repository: googleapis/gapic-showcase Branch: main Commit: be113b34662e Files: 222 Total size: 2.3 MB Directory structure: gitextract_m2mww3pq/ ├── .bazeliskrc ├── .bazelrc ├── .github/ │ ├── CODEOWNERS │ ├── auto-label.yml │ ├── label-sync.yml │ ├── release-please.yml │ ├── snippet-bot.yml │ ├── sync-repo-settings.yaml │ └── workflows/ │ ├── assets.yaml │ └── ci.yaml ├── .gitignore ├── .gitmodules ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── README.md ├── SECURITY.md ├── WORKSPACE.bazel ├── client/ │ ├── auxiliary.go │ ├── auxiliary_go123.go │ ├── compliance_client.go │ ├── compliance_client_example_go123_test.go │ ├── compliance_client_example_test.go │ ├── doc.go │ ├── echo_client.go │ ├── echo_client_example_go123_test.go │ ├── echo_client_example_test.go │ ├── gapic_metadata.json │ ├── helpers.go │ ├── identity_client.go │ ├── identity_client_example_go123_test.go │ ├── identity_client_example_test.go │ ├── messaging_client.go │ ├── messaging_client_example_go123_test.go │ ├── messaging_client_example_test.go │ ├── sequence_client.go │ ├── sequence_client_example_go123_test.go │ ├── sequence_client_example_test.go │ ├── testing_client.go │ ├── testing_client_example_go123_test.go │ └── testing_client_example_test.go ├── cmd/ │ └── gapic-showcase/ │ ├── README.md │ ├── attempt-sequence.go │ ├── attempt-streaming-sequence.go │ ├── block.go │ ├── chat.go │ ├── collect.go │ ├── completion.go │ ├── compliance_service.go │ ├── compliance_suite_errors_test.go │ ├── compliance_suite_test.go │ ├── connect.go │ ├── create-blurb.go │ ├── create-room.go │ ├── create-sequence.go │ ├── create-session.go │ ├── create-streaming-sequence.go │ ├── create-user.go │ ├── defaults.go │ ├── delete-blurb.go │ ├── delete-room.go │ ├── delete-session.go │ ├── delete-test.go │ ├── delete-user.go │ ├── echo-error-details.go │ ├── echo.go │ ├── echo_service.go │ ├── endpoint.go │ ├── endpoint_test.go │ ├── expand.go │ ├── fail-echo-with-details.go │ ├── gapic-showcase.go │ ├── get-blurb.go │ ├── get-enum.go │ ├── get-room.go │ ├── get-sequence-report.go │ ├── get-session.go │ ├── get-streaming-sequence-report.go │ ├── get-user.go │ ├── identity_service.go │ ├── list-blurbs.go │ ├── list-rooms.go │ ├── list-sessions.go │ ├── list-tests.go │ ├── list-users.go │ ├── loggers.go │ ├── messaging_service.go │ ├── paged-expand-legacy-mapped.go │ ├── paged-expand.go │ ├── repeat-data-body-info.go │ ├── repeat-data-body-patch.go │ ├── repeat-data-body-put.go │ ├── repeat-data-body.go │ ├── repeat-data-path-resource.go │ ├── repeat-data-path-trailing-resource.go │ ├── repeat-data-query.go │ ├── repeat-data-simple-path.go │ ├── report-session.go │ ├── run.go │ ├── search-blurbs.go │ ├── send-blurbs.go │ ├── sequence_service.go │ ├── stream-blurbs.go │ ├── testing_service.go │ ├── update-blurb.go │ ├── update-room.go │ ├── update-user.go │ ├── verify-enum.go │ ├── verify-test.go │ ├── version.go │ └── wait.go ├── go.mod ├── go.sum ├── renovate.json ├── schema/ │ └── google/ │ └── showcase/ │ └── v1beta1/ │ ├── BUILD.bazel │ ├── compliance.proto │ ├── echo.proto │ ├── identity.proto │ ├── messaging.proto │ ├── rest_error.proto │ ├── sequence.proto │ ├── showcase_grpc_service_config.json │ ├── showcase_v1beta1.yaml │ └── testing.proto ├── server/ │ ├── genproto/ │ │ ├── compliance.pb.go │ │ ├── echo.pb.go │ │ ├── identity.pb.go │ │ ├── messaging.pb.go │ │ ├── rest_error.pb.go │ │ ├── sequence.pb.go │ │ └── testing.pb.go │ ├── genrest/ │ │ ├── README.md │ │ ├── compliance.go │ │ ├── echo.go │ │ ├── genrest.go │ │ ├── iampolicy.go │ │ ├── identity.go │ │ ├── locations.go │ │ ├── messaging.go │ │ ├── operations.go │ │ ├── sequenceservice.go │ │ ├── showcase-rest-sample-response.txt │ │ └── testing.go │ ├── observer.go │ ├── observer_test.go │ ├── page_token.go │ ├── page_token_test.go │ ├── services/ │ │ ├── compliance_service.go │ │ ├── compliance_service_test.go │ │ ├── compliance_suite.json │ │ ├── echo_service.go │ │ ├── echo_service_test.go │ │ ├── iam_policy_service.go │ │ ├── iam_policy_service_test.go │ │ ├── identity_service.go │ │ ├── identity_service_test.go │ │ ├── locations_service.go │ │ ├── locations_service_test.go │ │ ├── messaging_service.go │ │ ├── messaging_service_test.go │ │ ├── operations_service.go │ │ ├── operations_service_test.go │ │ ├── sequence_service.go │ │ ├── sequence_service_test.go │ │ ├── services.go │ │ ├── test_common.go │ │ ├── testing_service.go │ │ ├── testing_service_test.go │ │ └── util.go │ ├── session.go │ ├── session_test.go │ ├── spec/ │ │ ├── showcase_tests.go │ │ └── v1/ │ │ ├── unary.go │ │ └── unary_test.go │ ├── test.go │ ├── unique_id.go │ ├── unique_id_test.go │ ├── waiter.go │ └── waiter_test.go ├── util/ │ ├── cmd/ │ │ ├── compile_protos/ │ │ │ └── main.go │ │ ├── protoc-gen-go_rest_server/ │ │ │ ├── README.md │ │ │ └── main.go │ │ └── release/ │ │ └── main.go │ ├── compile_protos.go │ ├── execute.go │ └── genrest/ │ ├── README.md │ ├── errorhandling/ │ │ └── accumulator.go │ ├── genserver.go │ ├── gomodel/ │ │ ├── gomodel.go │ │ ├── pathtemplate.go │ │ ├── pathtemplate_test.go │ │ ├── pathtemplatematch.go │ │ ├── pathtemplatematch_test.go │ │ ├── pathtemplateparser.go │ │ └── pathtemplateparser_test.go │ ├── gomodelcreator.go │ ├── goview/ │ │ └── goview.go │ ├── goviewcreator.go │ ├── goviewcreator_test.go │ ├── internal/ │ │ └── pbinfo/ │ │ └── pbinfo.go │ ├── protomodel/ │ │ └── protomodel.go │ ├── protomodelcreator.go │ ├── resttools/ │ │ ├── checkrequestformat.go │ │ ├── checkrequestformat_test.go │ │ ├── constants.go │ │ ├── error_response.go │ │ ├── error_response_test.go │ │ ├── headers.go │ │ ├── json.go │ │ ├── keysmatching.go │ │ ├── keysmatching_test.go │ │ ├── populatefield.go │ │ ├── populatefield_test.go │ │ ├── server_streamer.go │ │ ├── server_streamer_test.go │ │ ├── systemparam.go │ │ └── systemparam_test.go │ └── testdata/ │ └── TestConstructServerStreamer.go.baseline ├── version.go └── version.txt ================================================ FILE CONTENTS ================================================ ================================================ FILE: .bazeliskrc ================================================ # See https://github.com/bazelbuild/bazelisk # Should match https://github.com/googleapis/googleapis/blob/master/.bazeliskrc USE_BAZEL_VERSION=6.3.0 ================================================ FILE: .bazelrc ================================================ # To make proto_library rules to include source info in the descriptor build --protocopt=--include_source_info # Required because showcase protos include proto3_optional fields build --protocopt=--experimental_allow_proto3_optional # New boringssl requires C++14 # Copied from googleapis. build --repo_env=BAZEL_CXXOPTS="-std=c++14" ================================================ FILE: .github/CODEOWNERS ================================================ # Code owners file. # This file controls who is tagged for review for any given pull request. # For syntax help see: # https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax * @googleapis/cloud-sdk @googleapis/cloud-sdk-java-team ================================================ FILE: .github/auto-label.yml ================================================ --- product: false ================================================ FILE: .github/label-sync.yml ================================================ --- ignored: true ================================================ FILE: .github/release-please.yml ================================================ handleGHRelease: true releaseType: simple ================================================ FILE: .github/snippet-bot.yml ================================================ aggregateChecks: false alwaysCreateStatusCheck: false ================================================ FILE: .github/sync-repo-settings.yaml ================================================ rebaseMergeAllowed: false squashMergeAllowed: true mergeCommitAllowed: false branchProtectionRules: - pattern: main isAdminEnforced: true requiredStatusCheckContexts: - 'regenerate' - 'lint' - 'tests' - 'probes' - 'protobufjs-load-test' - 'cla/google' requiredApprovingReviewCount: 1 requiresCodeOwnerReviews: true requiresStrictStatusChecks: true permissionRules: - team: actools permission: admin ================================================ FILE: .github/workflows/assets.yaml ================================================ --- name: assets on: release: types: - created workflow_dispatch: inputs: tag: description: 'Release tag to checkout' required: true type: string env: # e.g. v1.0.0 (use release tag on release events or the provided tag on manual invocation) TAG_NAME: ${{ github.event.release.tag_name || github.event.inputs.tag }} jobs: get-upload-url: outputs: automated_upload_url: ${{ steps.automated-upload-url.outputs.AUTO_UPLOAD_URL }} manual_upload_url: ${{ steps.manual-upload-url.outputs.MANUAL_UPLOAD_URL }} runs-on: ubuntu-latest steps: - name: Get upload URL for automated releases id: automated-upload-url if: ${{ github.event.release.tag_name }} run: echo "AUTO_UPLOAD_URL=${{ github.event.release.upload_url }}" >> "$GITHUB_OUTPUT" - name: Get upload URL for manually triggered releases id: manual-upload-url if: ${{ github.event.inputs.tag }} uses: actions/github-script@v9 with: script: | const release = await github.rest.repos.getReleaseByTag({ owner: context.repo.owner, repo: context.repo.repo, tag: "${{ github.event.inputs.tag }}" }); core.setOutput("MANUAL_UPLOAD_URL", release.data.upload_url); proto-assets: runs-on: ubuntu-latest permissions: contents: write steps: - uses: actions/setup-go@v6 with: go-version: '1.26' - uses: actions/checkout@v6 - name: Init submodule run: git submodule init && git submodule update - name: Set raw version id: raw_tag # Strips the 'v' from the actual semver version. run: echo ::set-output name=raw_version::"${TAG_NAME#v}" - name: Install Protoc uses: arduino/setup-protoc@v1 - name: Compile proto release assets run: go run ./util/cmd/release -version=${{ steps.raw_tag.outputs.raw_version }} - name: Upload proto release assets uses: svenstaro/upload-release-action@v2 with: repo_token: ${{ secrets.GITHUB_TOKEN }} file: ./dist/* tag: ${{ env.TAG_NAME }} overwrite: true file_glob: true binary-assets: runs-on: ubuntu-latest permissions: contents: write needs: [get-upload-url, proto-assets] env: AUTO_UPLOAD_URL: ${{ needs.get-upload-url.outputs.automated_upload_url }} MANUAL_UPLOAD_URL: ${{ needs.get-upload-url.outputs.manual_upload_url }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} strategy: matrix: osarch: - os: linux arch: amd64 - os: linux arch: arm - os: darwin arch: amd64 - os: darwin arch: arm64 - os: windows arch: amd64 steps: - name: Determine which upload URL to use id: determine_upload_url run: | echo "automated URL: $AUTO_UPLOAD_URL" echo "manual URL: $MANUAL_UPLOAD_URL" if [[ -n "$AUTO_UPLOAD_URL" ]]; then echo "GITHUB_UPLOAD_URL=$AUTO_UPLOAD_URL" >> "$GITHUB_OUTPUT" else echo "GITHUB_UPLOAD_URL=$MANUAL_UPLOAD_URL" >> "$GITHUB_OUTPUT" fi - uses: actions/setup-go@v6 with: go-version: '1.26' - name: Install gox run: go install github.com/mitchellh/gox@latest - uses: actions/checkout@v6 - name: Set raw version id: raw_tag # Strips the 'v' from the actual semver version. run: echo ::set-output name=raw_version::"${TAG_NAME#v}" # The generator does not use this, but we need it to build the # binaries. # # Mousetrap is installed individually because it is needed for the # Windows build. Since we are building on Linux, it is not installed # automatically as a dependency. - name: Install the cross-platform build dependency. run: go get github.com/inconshreveable/mousetrap - name: Build for the ${{ matrix.osarch.os }}/${{ matrix.osarch.arch }} platform. run: | gox -osarch ${{ matrix.osarch.os }}/${{ matrix.osarch.arch }} -output gapic-showcase ./cmd/gapic-showcase && \ tar cvfz gapic-showcase.tar.gz gapic-showcase* - name: Upload the ${{ matrix.osarch.os }}/${{ matrix.osarch.arch }} release. uses: actions/upload-release-asset@v1 with: upload_url: ${{ steps.determine_upload_url.outputs.GITHUB_UPLOAD_URL }} asset_path: ./gapic-showcase.tar.gz asset_name: gapic-showcase-${{ steps.raw_tag.outputs.raw_version }}-${{ matrix.osarch.os }}-${{ matrix.osarch.arch }}.tar.gz asset_content_type: application/tar+gzip # Note: Disabled until better solution for storing the GCR key is found. # push_to_registry: # needs: # - inspect # - release # runs-on: ubuntu-latest # steps: # - name: Check out the repo # uses: actions/checkout@v2 # - name: Login to GCR # uses: docker/login-action@v1 # with: # registry: gcr.io # username: _json_key # password: ${{ secrets.GCR_JSON_KEY }} # - name: Push to GCR # uses: docker/build-push-action@v2 # with: # tags: gcr.io/gapic-images/gapic-showcase:${{ needs.inspect.outputs.raw_version }},gcr.io/gapic-images/gapic-showcase:latest # push: true # context: . ================================================ FILE: .github/workflows/ci.yaml ================================================ --- name: Showcase CI on: push: branches: - main pull_request: workflow_dispatch: jobs: regenerate: runs-on: ubuntu-latest outputs: modified_files: ${{ steps.mod.outputs.modified_files }} steps: - uses: actions/setup-go@v6 with: go-version: '1.26' - name: Install Protoc uses: arduino/setup-protoc@v1 - name: Install external generators run: | go install github.com/golang/protobuf/protoc-gen-go@latest go install github.com/googleapis/gapic-generator-go/cmd/protoc-gen-go_cli@latest go install github.com/googleapis/gapic-generator-go/cmd/protoc-gen-go_gapic@latest - uses: actions/checkout@v6 - name: Checkout common protos run: git submodule init && git submodule update - name: Download go deps run: go mod download - name: Install REST server generator run: go install ./util/cmd/protoc-gen-go_rest_server - name: Regenerate sources run: go run ./util/cmd/compile_protos - name: Capture modified files id: mod run: | files=$(git ls-files --deleted --modified --other --directory --exclude-standard cmd client server/genproto server/genrest) echo ::set-output name=modified_files::$files - name: Prepare regenerated sources if: steps.mod.outputs.modified_files run: tar czf regen.tgz ${{ steps.mod.outputs.modified_files }} - uses: actions/upload-artifact@v7 if: steps.mod.outputs.modified_files with: name: regenerated-sources path: regen.tgz lint: needs: regenerate runs-on: ubuntu-latest steps: - uses: actions/setup-go@v6 with: go-version: '1.26' - name: Install golint run: go install golang.org/x/lint/golint@latest - uses: actions/checkout@v6 - uses: actions/download-artifact@v8 if: needs.regenerate.outputs.modified_files with: name: regenerated-sources - name: Expand regen archive if: needs.regenerate.outputs.modified_files run: | tar xvzf regen.tgz rm regen.tgz - name: Check formatting run: gofmt -l ./server/services > gofmt.txt && ! [ -s gofmt.txt ] if: ${{ always() }} - name: Lint service implementations run: golint ./server/services >> golint.txt && ! [ -s golint.txt ] if: ${{ always() }} - name: Vet service implementations # The mod download is there to prevent go vet from logging mod downloads # which would mess up the empty vetting results check. run: go mod download && go vet ./server/services 2> govet.txt && ! [ -s govet.txt ] if: ${{ always() }} - uses: actions/upload-artifact@v7 if: ${{ always() }} with: name: linting-results path: | gofmt.txt golint.txt govet.txt tests: needs: regenerate runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: actions/setup-go@v6 with: go-version: '1.26' - uses: actions/download-artifact@v8 if: needs.regenerate.outputs.modified_files with: name: regenerated-sources - name: Expand regen archive if: needs.regenerate.outputs.modified_files run: | tar xvzf regen.tgz rm regen.tgz - name: Run mod tidy run: go mod tidy - name: Build the code run: go build ./... - name: Run unit tests run: go test ./... - name: Run server coverage run: go test ./server/... -coverprofile=coverage.txt -covermode=atomic probes: needs: regenerate runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: actions/setup-go@v6 with: go-version: '1.26' - uses: actions/download-artifact@v8 if: needs.regenerate.outputs.modified_files with: name: regenerated-sources - name: Expand regen archive if: needs.regenerate.outputs.modified_files run: | tar xvzf regen.tgz rm regen.tgz - name: Run mod tidy run: go mod tidy - name: Install gapic-showcase CLI run: go install ./cmd/gapic-showcase - name: Probe gRPC and REST servers run: | gapic-showcase run & gapic-showcase echo echo --response content --response.content "hello!" GRPC_EXIT_CODE=$? STATUSCODE=$(curl --silent --output /dev/null --write-out "%{http_code}" http://localhost:7469/hello) echo "gRPC exit code: $GRPC_EXIT_CODE" echo "REST status code: $STATUSCODE" [ $STATUSCODE = "200" ] && [ GRPC_EXIT_CODE != 0 ] # Disabled until https://github.com/googleapis/gapic-generator-typescript/pull/955 is merged/released. # typescript-smoke-test: # runs-on: ubuntu-latest # steps: # - uses: actions/checkout@v2 # - uses: actions/setup-node@v2 # with: # node-version: '12' # - name: Run gapic-generator-typescript # run: | # mkdir tsout # docker run --rm --user $UID \ # --mount type=bind,source="$(pwd)"/schema,destination=/in/protos/google/showcase/v1beta1,readonly \ # --mount type=bind,source="$(pwd)"/tsout,destination=/out/ \ # gcr.io/gapic-images/gapic-generator-typescript:latest # - name: Run auto-generated tests # run: | # cd tsout # npm install # npm test # npm run system-test protobufjs-load-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: node-version: '24' - name: Install protobuf loader run: npm install google-proto-files - name: Verify protos can be loaded by protobufjs run: | node -e "require('google-proto-files').loadSync('schema/google/showcase/v1beta1/echo.proto');" node -e "require('google-proto-files').loadSync('schema/google/showcase/v1beta1/identity.proto');" node -e "require('google-proto-files').loadSync('schema/google/showcase/v1beta1/messaging.proto');" node -e "require('google-proto-files').loadSync('schema/google/showcase/v1beta1/rest_error.proto');" node -e "require('google-proto-files').loadSync('schema/google/showcase/v1beta1/testing.proto');" node -e "require('google-proto-files').loadSync('schema/google/showcase/v1beta1/compliance.proto');" node -e "require('google-proto-files').loadSync('schema/google/showcase/v1beta1/sequence.proto');" push-generated-sources: needs: [regenerate, lint, tests, probes] runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' && needs.regenerate.outputs.modified_files steps: - uses: actions/checkout@v6 with: ref: main - uses: actions/download-artifact@v8 with: name: regenerated-sources - name: Expand regen archive run: | tar xvzf regen.tgz rm regen.tgz - uses: googleapis/code-suggester@v5 id: code_suggester env: ACCESS_TOKEN: ${{ secrets.YOSHI_CODE_BOT_TOKEN }} with: command: pr upstream_owner: googleapis upstream_repo: gapic-showcase description: 'Regenerated sources resulting from most recent commit to main' title: 'chore: regenerate sources' message: 'chore: regenerate sources' primary: 'main' branch: regen git_dir: '.' force: true - name: Add automerge label to pull request uses: actions/github-script@v9 with: script: | github.rest.issues.addLabels({ issue_number: ${{ steps.code_suggester.outputs.pull }}, owner: context.repo.owner, repo: context.repo.repo, labels: ['automerge'] }) bazel_build_protos: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: bazel-contrib/setup-bazel@0.19.0 with: # Avoid downloading Bazel every time. bazelisk-cache: true # Store build cache per workflow. disk-cache: ${{ github.workflow }} # Share repository cache between workflows. repository-cache: true - run: bazelisk build //schema/google/showcase/v1beta1:showcase_proto ================================================ FILE: .gitignore ================================================ # Temp directories tmp/ dist/ coverage.txt .vscode *~ bazel-* golint.txt gofmt.txt govet.txt ================================================ FILE: .gitmodules ================================================ [submodule "googleapis"] path = schema/googleapis url = https://github.com/googleapis/googleapis.git ================================================ FILE: CHANGELOG.md ================================================ # Release History ## [0.39.0](https://github.com/googleapis/gapic-showcase/compare/v0.38.0...v0.39.0) (2026-03-30) ### Features * Echo W3C trace propagation headers in showcase ([#1621](https://github.com/googleapis/gapic-showcase/issues/1621)) ([e8cd646](https://github.com/googleapis/gapic-showcase/commit/e8cd646fb411a9ca4e266a5d97e072794757fa4b)) ## [0.38.0](https://github.com/googleapis/gapic-showcase/compare/v0.37.0...v0.38.0) (2026-02-10) ### Features * **compliance:** Add optional fields for all primitive types ([#1602](https://github.com/googleapis/gapic-showcase/issues/1602)) ([ec41cbd](https://github.com/googleapis/gapic-showcase/commit/ec41cbde514ec092ce0da86d791bdef3c525aff6)) * Support apiVersion system parameter ([#1607](https://github.com/googleapis/gapic-showcase/issues/1607)) ([3fd9cb2](https://github.com/googleapis/gapic-showcase/commit/3fd9cb2f682d5f8263d913eaba8b78e045acc4d2)) ## [0.37.0](https://github.com/googleapis/gapic-showcase/compare/v0.36.2...v0.37.0) (2025-10-21) ### Features * Update dependencies and regenerate clients ([#1597](https://github.com/googleapis/gapic-showcase/issues/1597)) ([0ae044d](https://github.com/googleapis/gapic-showcase/commit/0ae044d8dda556672eaf6b2eb24a82ef0d2e4c4e)) ## [0.36.2](https://github.com/googleapis/gapic-showcase/compare/v0.36.1...v0.36.2) (2025-04-16) ### Bug Fixes * Name code_suggester step to fix CI action ([#1586](https://github.com/googleapis/gapic-showcase/issues/1586)) ([08c981d](https://github.com/googleapis/gapic-showcase/commit/08c981d696f1d5841119d97b131a39f182d8acb7)) ## [0.36.1](https://github.com/googleapis/gapic-showcase/compare/v0.36.0...v0.36.1) (2025-04-16) ### Bug Fixes * Update generated files to reflect proto changes ([#1579](https://github.com/googleapis/gapic-showcase/pull/1579)) ([6579d3a](https://github.com/googleapis/gapic-showcase/commit/6579d3aaf4bd541c43d3c2f8e981e94caf446dbe)) * Expand echo.proto comments ([#1580](https://github.com/googleapis/gapic-showcase/issues/1580)) ([076cb09](https://github.com/googleapis/gapic-showcase/commit/076cb0923e02f60a791ad82e6fc2c94c57e6671f)) ## [0.36.0](https://github.com/googleapis/gapic-showcase/compare/v0.35.5...v0.36.0) (2025-04-10) ### Features * Add Echo.FailEchoWithDetails RPC that always fails with all standard and one custom error detail ([#1576](https://github.com/googleapis/gapic-showcase/issues/1576)) ([709b57d](https://github.com/googleapis/gapic-showcase/commit/709b57d724327abe091965c54f402042155aa178)) ### Bug Fixes * Return AIP/193-compliant errors over rest transport ([#1573](https://github.com/googleapis/gapic-showcase/issues/1573)) ([d47045b](https://github.com/googleapis/gapic-showcase/commit/d47045be1ee31f373d5a6ded287cbc9c5b9b605a)) * Typos in some proto comments ([#1563](https://github.com/googleapis/gapic-showcase/issues/1563)) ([ae41e96](https://github.com/googleapis/gapic-showcase/commit/ae41e96133b36fa86f8d08c0f839ab9fb12e3e96)) ## [0.35.5](https://github.com/googleapis/gapic-showcase/compare/v0.35.4...v0.35.5) (2024-12-04) ### Bug Fixes * Replace use of github.com/golang/protobuf/proto where possible ([#1557](https://github.com/googleapis/gapic-showcase/issues/1557)) ([0215dd6](https://github.com/googleapis/gapic-showcase/commit/0215dd637e130ca0c0a74adcc74d34d3373060d8)), closes [#1525](https://github.com/googleapis/gapic-showcase/issues/1525) ## [0.35.4](https://github.com/googleapis/gapic-showcase/compare/v0.35.3...v0.35.4) (2024-12-03) ### Bug Fixes * Revert replace use of github.com/golang/protobuf/proto ([#1534](https://github.com/googleapis/gapic-showcase/issues/1534))" ([#1553](https://github.com/googleapis/gapic-showcase/issues/1553)) ([b82e7c5](https://github.com/googleapis/gapic-showcase/commit/b82e7c5d8b63ba11cc21361a4b84d0cb29a59826)) ## [0.35.3](https://github.com/googleapis/gapic-showcase/compare/v0.35.2...v0.35.3) (2024-12-03) ### Bug Fixes * Downgrade go version to 1.21 ([#1551](https://github.com/googleapis/gapic-showcase/issues/1551)) ([36831cf](https://github.com/googleapis/gapic-showcase/commit/36831cfe255e13e3a5328ad548ddba9c3174434e)) ## [0.35.2](https://github.com/googleapis/gapic-showcase/compare/v0.35.1...v0.35.2) (2024-12-03) ### Bug Fixes * **deps:** Update bazel-contrib/setup-bazel action to v0.9.1 ([#1546](https://github.com/googleapis/gapic-showcase/issues/1546)) ([bc936fb](https://github.com/googleapis/gapic-showcase/commit/bc936fb7c3607853bbc58fcd8f4d0aa7ccbc4a1c)) ## [0.35.1](https://github.com/googleapis/gapic-showcase/compare/v0.35.0...v0.35.1) (2024-07-08) ### Bug Fixes * Use io.ReadAll ([#1520](https://github.com/googleapis/gapic-showcase/issues/1520)) ([6dddadd](https://github.com/googleapis/gapic-showcase/commit/6dddadd9fcdfed197209271a1201178a57951660)) ## [0.35.0](https://github.com/googleapis/gapic-showcase/compare/v0.34.0...v0.35.0) (2024-04-29) ### Features * Echo request headers in response over REST transport ([#1509](https://github.com/googleapis/gapic-showcase/issues/1509)) ([de93c4c](https://github.com/googleapis/gapic-showcase/commit/de93c4c5e33b4e1a8ec3ebbeb7af36143dbc19dd)) ## [0.34.0](https://github.com/googleapis/gapic-showcase/compare/v0.33.0...v0.34.0) (2024-04-23) ### Features * Add ability to echo request headers in trailing metadata ([#1501](https://github.com/googleapis/gapic-showcase/issues/1501)) ([48f9b74](https://github.com/googleapis/gapic-showcase/commit/48f9b742970e2199431066807d3f7a5cd2f31728)) ## [0.33.0](https://github.com/googleapis/gapic-showcase/compare/v0.32.2...v0.33.0) (2024-04-15) ### Features * Add google.api.api_version annotation to echo.proto ([#1484](https://github.com/googleapis/gapic-showcase/issues/1484)) ([9a2298b](https://github.com/googleapis/gapic-showcase/commit/9a2298b90a90d812c331f2c0d9971b2312ae167d)) * Log REST request headers ([#1497](https://github.com/googleapis/gapic-showcase/issues/1497)) ([05605c6](https://github.com/googleapis/gapic-showcase/commit/05605c60b41b95be07ca7cf38ae12e2fdbe82094)) ## [0.32.2](https://github.com/googleapis/gapic-showcase/compare/v0.32.1...v0.32.2) (2024-03-22) ### Bug Fixes * **bazel:** Fix bazel build and add presubmit ([#1479](https://github.com/googleapis/gapic-showcase/issues/1479)) ([e446229](https://github.com/googleapis/gapic-showcase/commit/e44622986d706bcbdb5de710484318f40b571c20)) ## [0.32.1](https://github.com/googleapis/gapic-showcase/compare/v0.32.0...v0.32.1) (2024-03-21) ### Bug Fixes * Add missing dependency in bazel rule ([#1477](https://github.com/googleapis/gapic-showcase/issues/1477)) ([f08b26d](https://github.com/googleapis/gapic-showcase/commit/f08b26d62da0a3c3214382915167b33633eb9558)) ## [0.32.0](https://github.com/googleapis/gapic-showcase/compare/v0.31.0...v0.32.0) (2024-03-20) ### Features * Add autopopulated proto3 optional field to echo ([#1471](https://github.com/googleapis/gapic-showcase/issues/1471)) ([dba317f](https://github.com/googleapis/gapic-showcase/commit/dba317ff2ef63899bcc20de6a29c21f63afc7acc)) ## [0.31.0](https://github.com/googleapis/gapic-showcase/compare/v0.30.0...v0.31.0) (2024-02-08) ### Features * Add request id as part of EchoResponse ([#1440](https://github.com/googleapis/gapic-showcase/issues/1440)) ([fe3c90e](https://github.com/googleapis/gapic-showcase/commit/fe3c90eba35a5d94fb419d495178ff90c9bcc795)) ## [0.30.0](https://github.com/googleapis/gapic-showcase/compare/v0.29.0...v0.30.0) (2024-01-10) ### Features * Add autopopulated request id field to echo ([#1404](https://github.com/googleapis/gapic-showcase/issues/1404)) ([196b665](https://github.com/googleapis/gapic-showcase/commit/196b6650ff01483246d5c3fe67ca2ad29d1a21dc)) * Replace api-common-protos submodule with googleapis ([#1395](https://github.com/googleapis/gapic-showcase/issues/1395)) ([d72c489](https://github.com/googleapis/gapic-showcase/commit/d72c4899c111e8c870b552cd1721166434096348)) ## [0.29.0](https://github.com/googleapis/gapic-showcase/compare/v0.28.4...v0.29.0) (2023-11-08) ### Features * Add EchoErrorDetails RPC for Any testing ([#1385](https://github.com/googleapis/gapic-showcase/issues/1385)) ([c839a8e](https://github.com/googleapis/gapic-showcase/commit/c839a8ec6973b6c5189c9cba8b6a81f1663b8fd1)) ## [0.28.4](https://github.com/googleapis/gapic-showcase/compare/v0.28.3...v0.28.4) (2023-08-14) ### Bug Fixes * Add fail index to streaming sequence ([#1364](https://github.com/googleapis/gapic-showcase/issues/1364)) ([567e756](https://github.com/googleapis/gapic-showcase/commit/567e7567600a0c3cb369a98ac25351f10000fcec)) ## [0.28.3](https://github.com/googleapis/gapic-showcase/compare/v0.28.2...v0.28.3) (2023-07-07) ### Bug Fixes * Remove content_sent from StreamingSequences ([#1351](https://github.com/googleapis/gapic-showcase/issues/1351)) ([ae910cc](https://github.com/googleapis/gapic-showcase/commit/ae910cca182787fb5babbfe1005b086d4f2f8c4b)) ## [0.28.2](https://github.com/googleapis/gapic-showcase/compare/v0.28.1...v0.28.2) (2023-07-05) ### Bug Fixes * Update HttpJson regex for URL paths ([#1340](https://github.com/googleapis/gapic-showcase/issues/1340)) ([4110fee](https://github.com/googleapis/gapic-showcase/commit/4110fee63a22f8d32cae7f8ba318919bee94e752)) ## [0.28.1](https://github.com/googleapis/gapic-showcase/compare/v0.28.0...v0.28.1) (2023-05-10) ### Bug Fixes * Remove non-exist fields from method signature in sequence.proto ([#1315](https://github.com/googleapis/gapic-showcase/issues/1315)) ([a7c8ffc](https://github.com/googleapis/gapic-showcase/commit/a7c8ffca1fec5f25b630ac1d2aa83bc3db0fe521)) ## [0.28.0](https://github.com/googleapis/gapic-showcase/compare/v0.27.0...v0.28.0) (2023-05-09) ### Features * Add a configurable wait time between messages sent for server streaming RPCs ([#1309](https://github.com/googleapis/gapic-showcase/issues/1309)) ([dd11687](https://github.com/googleapis/gapic-showcase/commit/dd1168792054cfccb16e53753764cda3431d6170)) ## [0.27.0](https://github.com/googleapis/gapic-showcase/compare/v0.26.1...v0.27.0) (2023-04-19) ### Features * Add iam and location mixin rest handlers ([#1300](https://github.com/googleapis/gapic-showcase/issues/1300)) ([6adab7b](https://github.com/googleapis/gapic-showcase/commit/6adab7bb4e7c979f90441a37cde36ecda0bee68f)) * Add proto + logic for streaming sequence ([#1266](https://github.com/googleapis/gapic-showcase/issues/1266)) ([82814d8](https://github.com/googleapis/gapic-showcase/commit/82814d8a8ada26bf9a831497b667183edf1f0e4f)) ### Bug Fixes * Handle already quoted protojson wkt ([#1294](https://github.com/googleapis/gapic-showcase/issues/1294)) ([f74f03d](https://github.com/googleapis/gapic-showcase/commit/f74f03d50ea8aa5832f830a6f92e16e99fb3e623)) ## [0.26.1](https://github.com/googleapis/gapic-showcase/compare/v0.26.0...v0.26.1) (2023-03-28) ### Bug Fixes * **rest:** Properly handle string-encoded well-known types in URLs ([#1282](https://github.com/googleapis/gapic-showcase/issues/1282)) ([579fe72](https://github.com/googleapis/gapic-showcase/commit/579fe729c0b506cdf48cd834beb14a8ffb4b5994)) ## [0.26.0](https://github.com/googleapis/gapic-showcase/compare/v0.25.0...v0.26.0) (2023-03-07) ### Features * **go:** Update Go version to 1.19 ([#1225](https://github.com/googleapis/gapic-showcase/issues/1225)) ([d4b108e](https://github.com/googleapis/gapic-showcase/commit/d4b108e16dc91c0ea6d4dec3dca4d3270d3bf47a)) ### Bug Fixes * Build assets for darwin/arm64 ([#1267](https://github.com/googleapis/gapic-showcase/issues/1267)) ([0833a57](https://github.com/googleapis/gapic-showcase/commit/0833a579131c14582b053f26698fdfe93e465d87)) * Export showcase_v1beta1.yaml from BUILD.bazel to support external GAPIC generation ([#1223](https://github.com/googleapis/gapic-showcase/issues/1223)) ([5076348](https://github.com/googleapis/gapic-showcase/commit/507634898e208b7ff88784e4ec5f0efd22bff9ab)) * Handle x-http-method-override for PATCH as POST ([#1262](https://github.com/googleapis/gapic-showcase/issues/1262)) ([4070ce3](https://github.com/googleapis/gapic-showcase/commit/4070ce331bd5e852ccb2f4f2267dce80a9dda9c4)) * Use quotes around extreme int64 values ([#1206](https://github.com/googleapis/gapic-showcase/issues/1206)) ([c9d9ff1](https://github.com/googleapis/gapic-showcase/commit/c9d9ff191bfd72fe8563625be4074fe4659585d6)), closes [#1205](https://github.com/googleapis/gapic-showcase/issues/1205) ## [0.25.0](https://github.com/googleapis/gapic-showcase/compare/v0.24.0...v0.25.0) (2022-09-01) ### Features * Support FieldMask in Updates ([#1197](https://github.com/googleapis/gapic-showcase/issues/1197)) ([cdb4ce6](https://github.com/googleapis/gapic-showcase/commit/cdb4ce63778a8ea6bcef0006c1e4c4a50da45a6c)) ### Bug Fixes * Use resource field in http body for Updates ([#1198](https://github.com/googleapis/gapic-showcase/issues/1198)) ([48a2632](https://github.com/googleapis/gapic-showcase/commit/48a2632b5f25af24b239216f1ff079ed60de2a61)) ## [0.24.0](https://github.com/googleapis/gapic-showcase/compare/v0.23.0...v0.24.0) (2022-07-28) ### Features * **regapic:** accept numeric enums, allow testing enum round trips ([#1159](https://github.com/googleapis/gapic-showcase/issues/1159)) ([1e863ae](https://github.com/googleapis/gapic-showcase/commit/1e863ae834ad58453c1d74cf593be1188ff15033)) ## [0.23.0](https://github.com/googleapis/gapic-showcase/compare/v0.22.0...v0.23.0) (2022-07-27) ### Features * add binding testing and multiple bindings test data to compliance service ([#1150](https://github.com/googleapis/gapic-showcase/issues/1150)) ([9d43ed0](https://github.com/googleapis/gapic-showcase/commit/9d43ed0621e4c9549a3d92a53dedc5dd57e9bec2)) ### Bug Fixes * remove broken test cases in compliance ([#1151](https://github.com/googleapis/gapic-showcase/issues/1151)) ([a56df9a](https://github.com/googleapis/gapic-showcase/commit/a56df9ab5ad9cdd6cb0385ba9c74263b95538ad8)) ## [0.22.0](https://github.com/googleapis/gapic-showcase/compare/v0.21.0...v0.22.0) (2022-06-13) ### Features * Support LRO mixins over REST ([#1118](https://github.com/googleapis/gapic-showcase/issues/1118)) ([5ca6fe1](https://github.com/googleapis/gapic-showcase/commit/5ca6fe1b8ea7e5645e87718e84b1198ad8ce9c63)) ## [0.21.0](https://github.com/googleapis/gapic-showcase/compare/v0.20.0...v0.21.0) (2022-06-08) ### Features * respond to requests specifying response enum values be JSON-encoded as ints ([#1111](https://github.com/googleapis/gapic-showcase/issues/1111)) ([5389bd1](https://github.com/googleapis/gapic-showcase/commit/5389bd17aedb7f0c8a8de562421222e703589823)) ### Bug Fixes * **genrest:** pass http request context to service handler ([#1088](https://github.com/googleapis/gapic-showcase/issues/1088)) ([bad9b6b](https://github.com/googleapis/gapic-showcase/commit/bad9b6b89b0f75d3ec8408610d329068775703e5)) ## [0.20.0](https://github.com/googleapis/gapic-showcase/compare/v0.19.5...v0.20.0) (2022-05-10) ### Features * **genrest:** format rest errors as Google Errors ([#1082](https://github.com/googleapis/gapic-showcase/issues/1082)) ([e49f134](https://github.com/googleapis/gapic-showcase/commit/e49f134dc54ae734c716f8649fc3279efd68916f)) ### [0.19.5](https://github.com/googleapis/gapic-showcase/compare/v0.19.4...v0.19.5) (2022-03-08) ### Bug Fixes * add a routing.proto dependency to showcase proto bazel target ([#1033](https://github.com/googleapis/gapic-showcase/issues/1033)) ([e2aa303](https://github.com/googleapis/gapic-showcase/commit/e2aa3033e67c0c50c5650512211001e1ad29d36a)) ### [0.19.4](https://github.com/googleapis/gapic-showcase/compare/v0.19.3...v0.19.4) (2022-03-03) ### Bug Fixes * **ci:** yet another attempt to fix asset ci ([#1026](https://github.com/googleapis/gapic-showcase/issues/1026)) ([32a2603](https://github.com/googleapis/gapic-showcase/commit/32a2603550220dcd0a86d533a883fa1ba860a3b1)) ### [0.19.3](https://github.com/googleapis/gapic-showcase/compare/v0.19.2...v0.19.3) (2022-03-03) ### Bug Fixes * **ci:** asset version shouldn't include the leading v ([#1023](https://github.com/googleapis/gapic-showcase/issues/1023)) ([a78d624](https://github.com/googleapis/gapic-showcase/commit/a78d6243b9cbfa088b6863954b0bf6dec91c6786)) ### [0.19.2](https://github.com/googleapis/gapic-showcase/compare/v0.19.1...v0.19.2) (2022-03-02) ### Bug Fixes * use tag_name for proto-assets upload ([#1021](https://github.com/googleapis/gapic-showcase/issues/1021)) ([c3f2f36](https://github.com/googleapis/gapic-showcase/commit/c3f2f36128a3c7b5c51fc1bd87c83f8f833adf9a)) ### [0.19.1](https://github.com/googleapis/gapic-showcase/compare/v0.19.0...v0.19.1) (2022-03-02) ### Bug Fixes * ruby package name ([#1015](https://github.com/googleapis/gapic-showcase/issues/1015)) ([7289f2e](https://github.com/googleapis/gapic-showcase/commit/7289f2e20afa198695d3da9d5a5362a161032244)) ### v0.19.0 / 2022-01-31 - update api-common-protos submodule - add ability to echo headers and added several routing annotations to the `Echo` method - enable generation of both grpc and rest clients ### v0.18.0 / 2021-12-06 - add `parent` to method signature for `Messaging.SearchBlurbs()` - update `RELEASING.md` instructions ### v0.17.0 / 2021-11-02 - Implement server streaming RPCs over REST, using chunked encoding. - Implement RPCs that map to PUT and PATCH HTTP verbs - Check that REST RPCs using HTTP GET or DELETE don't contain bodies. - Disable TypeScript smoke tests pending upstream fixes (TS generator Docker image). ### v0.16.0 / 2021-06-16 - Require incoming REST requests to have expected `x-goog-api-client` header tokens - Allow mTLS to work over gRPC when using `cmux` to also listen to REST requests on the same port - Make REST `PATCH` methods work - Fix multi-line truncation in release notes - Add Docker push instructions to RELEASING.md ### v0.15.0 / 2021-05-05 - Enforce `Content-Type: application/json` in the bodies of REST requests - Enforce correct `optional` field presence/absence in test suite requests (bodies and query strings) - Lower-camel-case field names in `compliance_suite.json` ### v0.14.0 / 2021-04-27 - Fix collision between operation helper for `Echo.Wait` and generated mixin `Operations.WaitOpertation` - REST endpoints: ensure enum values are received as string values - REST endpoints: ensure full body responses - Rest endpoints: enforce lower-camel-cased field names in request bodies and query params - fix windows binary upload - fix go vet/lint warnings - pin Go version in CI - fix release asset version - add Code of Conduct - add `SECURITY.md` ### v0.13.0 / 2021-02-24 - Auto-generate REST endpoints for Showcase services via `genrest` (partial) - Add Compliance service for generators to use to test REST-transcoding their protos and RPCs (partial) - Add mix-in service implementations - Update API Service config with mix-ins and more - Add Bazel proto_library targets for schema/ - Migrated to GitHub Actions - Regen client & CLI with small updates - Update dependencies ### v0.12.0 / 2020-08-12 - Add client-side retry/deadline testing surface - Regen client & CLI with small updates - Update dependencies ### v0.11.0 / 2020-05-26 - Add non-slash resource name patterns to Blurb resource - Fix typo in User-parented Blurb resource patterns - Add an enum to EchoRequest/EchoResponse - Regen CLI with new fields - Update dependencies ### v0.10.1 / 2020-05-20 - Fix UpdateUser handler response to send entire updated resource - Note: non-slash resource name changes are not included in this release ### v0.10.0 / 2020-05-18 - Add use of proto3_optional in schema - Upgrade CI protoc to v3.12.0 - Regen CLI with new proto3_optional fields - Update dependencies ### v0.9.0 / 2020-04-22 - Print gRPC request headers in verbose mode (`gapic-showcase run -v`) - Add TypeScript smoke tests - Fix Kotlin smoke tests ### v0.8.1 / 2020-04-15 - Fix bug in mTLS configuration resolution ### v0.8.0 / 2020-04-14 - Add mtls support with user provided cert/key to server - Regen cli: - Paginated RPCs only collect a single page - Default page_size changed from 0 to 10 to avoid short circuiting - Regen client: - clientHook support added - Update CI use of go.mod - Update dependencies ### v0.7.0 / 2020-02-06 - Regen client and protobuf code for Go grpc.ClientConn interface - Update dependencies ### v0.6.1 / 2019-11-01 - Fix the resource name for Blurb. ### v0.6.0 / 2019-11-01 - Add a gRPC ServiceConfig for microgenerator retry config - Regen client code with retry config - Update dependencies ### v0.5.0 / 2019-09-04 - Update to Go version 1.13 - Update dependencies - Add trailers testing support to Echo - Fix pagination in operations service ### v0.4.0 / 2019-08-13 - Add dummy LRO service - Dependency updates ### v0.3.0 / 2019-08-09 - Remove nodejs server implementation - Update dependencies - Update golang docker tag to v1.12 - Add Block method to Echo service - Enable kotlin smoke test - Add renovate.json ### v0.2.4 / 2019-07-11 - Update `grpc-fallback-go` version to `v0.1.3` ### v0.2.3 / 2019-07-09 - Update `grpc-fallback-go` version to `v0.1.2` ### v0.2.2 / 2019-07-09 - Update `grpc-fallback-go` version to `v0.1.1` ### v0.2.1 / 2019-07-03 - Add fallback-proxy to `gapic-showcase run` via grpc-fallback-go - Expose fallback-proxy port in Dockerfile - Tidy `go.mod` ### v0.2.0 / 2019-05-24 - Regenerate GAPIC & GCLI with small updates - Update resource annotations - Fix bug in README - Add Node.js EchoService implementation - Remove extraneous logging ### v0.1.1 / 2019-04-17 - Regenerate GAPIC & GCLI to capture fixes for paged RPCs & commands ### v0.1.0 / 2019-04-04 - Beta release. ### v0.0.16 / 2019-03-25 - Fixing some field names in path templates ### v0.0.15 / 2019-03-25 - Fixing path templates to make sure curly braces match - Use Go modules ### v0.0.14 / 2019-03-25 - Serve Testing service CLI service - Ensure all path templates start with `/` ### v0.0.13 / 2019-03-01 - Fix issue which tombstones users. ### v0.0.12 / 2019-02-20 - Remove google.api.client_package proto annotations. ### v0.0.11 / 2019-02-19 - Update GAPIC config proto annotations. ### v0.0.10 / 2019-01-29 - Expose messaging and identity services when running `gapic-showcase run`. - Refactor `Echo.WaitRequest` to follow API style for denoting time to live. - Use GCLI Generated Code for the CLI cmd. ================================================ FILE: CODE_OF_CONDUCT.md ================================================ # Contributor Code of Conduct As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery * Personal attacks * Trolling or insulting/derogatory comments * Public or private harassment * Publishing other's private information, such as physical or electronic addresses, without explicit permission * Other unethical or unprofessional conduct. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers. This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/) ================================================ FILE: CONTRIBUTING.md ================================================ Contributing ============ We are thrilled that you are interested in contributing to this project. Please open an issue or pull request with your ideas. Contributor License Agreements ------------------------------ Before we can accept your pull requests, you will need to sign a Contributor License Agreement (CLA): - **If you are an individual writing original source code** and **you own the intellectual property**, then you'll need to sign an [individual CLA]. - **If you work for a company that wants to allow you to contribute your work**, then you'll need to sign a [corporate CLA]. You can sign these electronically (just scroll to the bottom). After that, we'll be able to accept your pull requests. [individual CLA]: https://developers.google.com/open-source/cla/individual [corporate CLA]: https://developers.google.com/open-source/cla/corporate ================================================ FILE: Dockerfile ================================================ FROM golang:1.26-alpine AS builder # Install git and gcc. RUN apk add --no-cache git gcc musl-dev # Setup directory. WORKDIR /go/src/github.com/googleapis/gapic-showcase COPY . . # Compile for Linux. ENV CGO_ENABLED 0 ENV GOOS linux ENV GOARCH amd64 # Install showcase. RUN go get ./... RUN go build -installsuffix cgo \ -ldflags="-w -s" \ -o /go/bin/gapic-showcase \ ./cmd/gapic-showcase # Start a fresh image, and only copy the built binary. FROM scratch COPY --from=builder /go/bin/gapic-showcase /go/bin/gapic-showcase # Expose ports EXPOSE 7469 EXPOSE 1337 # Run the server. ENTRYPOINT ["/go/bin/gapic-showcase"] CMD ["run"] ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================ # GAPIC Showcase [![Release Level][releaselevelimg]][releaselevel] [![Code Coverage][codecovimg]][codecov] [![GoDoc][godocimg]][godoc] GAPIC Showcase is an API that demonstrates Generated API Client (GAPIC) features and common API patterns used by Google. It follows the [Cloud APIs design guide](https://cloud.google.com/apis/design/). This project provides a server and client implementation of the API that can be run locally over both gRPC and HTTP/JSON. ## Installation The GAPIC Showcase CLI can be installed using three different mechanisms: pulling a docker image from [Google Container Registry](https://gcr.io/gapic-images/gapic-showcase), downloading the compiled binary from our our [releases](https://github.com/googleapis/gapic-showcase/releases) page, or simply by installing from source using go. ### Docker **NOTE**: The "latest" Docker image is currently stale. We expect to update it in the near future. (We're upgrading our processes.) ```sh $ docker pull gcr.io/gapic-images/gapic-showcase:latest $ docker run \ --rm \ -p 7469:7469/tcp \ -p 7469:7469/udp \ gcr.io/gapic-images/gapic-showcase:latest \ --help > Root command of gapic-showcase > > Usage: > gapic-showcase [command] > > Available Commands: > completion Emits bash a completion for gapic-showcase > echo This service is used showcase the four main types... > help Help about any command > identity A simple identity service. > messaging A simple messaging service that implements chat... > run Runs the showcase server > testing A service to facilitate running discrete sets of... > > Flags: > -h, --help help for gapic-showcase > -j, --json Print JSON output > -v, --verbose Print verbose output > --version version for gapic-showcase > > Use "gapic-showcase [command] --help" for more information about a command. ``` ### Binary ```sh $ export GAPIC_SHOWCASE_VERSION=0.36.1 # use the current version here $ export OS=linux $ export ARCH=amd64 $ curl -L https://github.com/googleapis/gapic-showcase/releases/download/v${GAPIC_SHOWCASE_VERSION}/gapic-showcase-${GAPIC_SHOWCASE_VERSION}-${OS}-${ARCH}.tar.gz | sudo tar -zx --directory /usr/local/bin/ $ gapic-showcase --help ... ``` ### Source ```sh $ go install github.com/googleapis/gapic-showcase/cmd/gapic-showcase@latest $ PATH=$PATH:`go env GOPATH`/bin $ gapic-showcase --help ... ``` _* Bear in mind this is not a versioned installation so no versioning guarantees hold using this installation method._ ## Schema The schema of GAPIC Showcase API can be found in [schema/google/showcase/v1beta1](schema/google/showcase/v1beta1) Its dependencies can be found in the [googleapis/googleapis](https://github.com/googleapis/googleapis) submodule. ## Development Environment To set up this repository for local development, follow these steps: 1. Install `protoc` from the protobuf [release page](https://github.com/protocolbuffers/protobuf/releases) or your OS package manager. This API utilizes `proto3_optional`, thus `v3.12.0` is the minimum supported version of `protoc`. 1. Initialize the `googleapis` submodule: ```sh git submodule update --init --recursive ``` 1. Install Go 1. Linux: `sudo apt-get install golang` 2. Mac, Windows, or other options: Please see the [official set-up docs](https://golang.org/doc/install). 1. Clone this repository. 1. Set up Go protobuf tools: ```sh go install github.com/golang/protobuf/protoc-gen-go@latest go install github.com/googleapis/gapic-generator-go/cmd/protoc-gen-go_cli@latest go install github.com/googleapis/gapic-generator-go/cmd/protoc-gen-go_gapic@latest ``` 1. Export the Go binaries to your environment path. ```sh PATH=$PATH:`go env GOPATH`/bin ``` 1. To compile the Showcase binary, as well as associated development utilities in this repository, run the following after you make changes: ```sh go install ./... ``` ### Making changes to the protos If there are any changes to the protobuf files, the generated support code must be regenerated. This can be done by executing the following command: go install ./util/cmd/... && go run ./util/cmd/compile_protos If successful, you may see changes in the following directories: * `server/genproto` * `server/genrest` * `client/` * `cmd/gapic-showcase` Then, update the binaries: go install ./... ## Quick Start This quick start guide will show you how to start the server and make a request to it. ### Step 1. Run the server Run the showcase server to allow requests to be sent to it. This opens port :7469 to send and receive requests. ```sh $ gapic-showcase run > 2018/09/19 02:13:09 Showcase listening on port: :7469 ``` ### Step 2. Make a request Open a new terminal window and make a request to the server. ```sh $ gapic-showcase \ identity \ # Service name create-user \ # Message name --user.display_name Rumble \ # Request fields --user.email rumble@goodboi.com > name:"users/0" display_name:"Rumble" email:"rumble@goodboi.com" create_time: update_time: ``` **_Note: You can make requests to this server from your own client but an insecure channel must be used since the server does not implement auth. Client library generators with Showcase-based integration tests need to provide the insecure channel to the client library in the tests._** #### Example for Node.js: ```js const grpc = require('@grpc/grpc-js'); const showcase = require('showcase'); const client = new showcase.EchoClient({ grpc, sslCreds: grpc.credentials.createInsecure() }); ``` #### Example for Go: ```go package main import ( "context" "fmt" "log" "github.com/googleapis/gapic-showcase/client" "google.golang.org/api/option" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ) func main() { conn, err := grpc.Dial("localhost:7469", grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { log.Fatal(err) } opt := option.WithGRPCConn(conn) ctx := context.Background() _, err = client.NewEchoClient(ctx, opt) if err != nil { log.Fatal(err) } } ``` #### Example for Java (gRPC): ```java EchoSettings echoSettings = EchoSettings.newBuilder() .setCredentialsProvider(NoCredentialsProvider.create()) .setTransportChannelProvider( InstantiatingGrpcChannelProvider.newBuilder() .setChannelConfigurator( new ApiFunction() { @Override public ManagedChannelBuilder apply(ManagedChannelBuilder input) { return input.usePlaintext(); } }) .build()) .build(); EchoClient echoClient = EchoClient.create(echoSettings); ``` #### Example for Java (httpJson): ```java EchoSettings echoSettings = EchoSettings.newHttpJsonBuilder() .setTransportChannelProvider(EchoSettings.defaultHttpJsonTransportProviderBuilder() .setHttpTransport(new NetHttpTransport.Builder().doNotValidateCertificate().build()) .setEndpoint("http://localhost:7469") .build()) .build(); EchoClient echoClient = EchoClient.create(echoSettings); ``` #### Example for Python ```python from google import showcase_v1beta1 from google.auth import credentials import grpc # ... if do_grpc: transport_cls = showcase_v1beta1.EchoClient.get_transport_class("grpc") transport = transport_cls( credentials=credentials.AnonymousCredentials(), channel=grpc.insecure_channel("localhost:7469"), host="localhost:7469", ) else: transport_cls = showcase_v1beta1.EchoClient.get_transport_class("rest") transport = transport_cls( credentials=credentials.AnonymousCredentials(), host="localhost:7469", url_scheme="http", ) ``` ## Released Artifacts GAPIC Showcase releases three main artifacts, a CLI tool, the gapic-showcase service protobuf files staged alongside its dependencies, and a protocol buffer descriptor set compiled from the gapic-showcase service protos. Check out our [releases](https://github.com/googleapis/gapic-showcase/releases) page to see our released artifacts. ## Versioning GAPIC Showcase follows semantic versioning. All artifacts that are released for a certain version are guaranteed to be compatible with one another. ## Releases Releases are made by [release-please](https://github.com/googleapis/release-please) based on the contents of the Conventional Commits made to the project. Assets are then uploaded to the releases that are created. ## Supported Go Versions GAPIC Showcase is supported for go versions 1.16 and later. ## FAQ ### Is this Showcase API publicly served? This API is not publicly served. ## Disclaimer This is not an official Google product. [codecovimg]: https://codecov.io/github/googleapis/gapic-showcase/coverage.svg?branch=main [codecov]: https://codecov.io/github/googleapis/gapic-showcase?branch=main [godoc]: https://godoc.org/github.com/googleapis/gapic-showcase/server [godocimg]: https://godoc.org/github.com/googleapis/gapic-showcase/server?status.svg [releaselevel]: https://cloud.google.com/terms/launch-stages [releaselevelimg]: https://img.shields.io/badge/release%20level-beta-red.svg?style=flat ================================================ FILE: SECURITY.md ================================================ # Security Policy To report a security issue, please use [g.co/vulnz](https://g.co/vulnz). The Google Security Team will respond within 5 working days of your report on g.co/vulnz. We use g.co/vulnz for our intake, and do coordination and disclosure here using GitHub Security Advisory to privately discuss and fix the issue. ================================================ FILE: WORKSPACE.bazel ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ A workspace for gapic-showcase """ workspace(name = "gapic_showcase") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") ## # googleapis for the common protos # http_archive( name = "com_google_googleapis", strip_prefix = "googleapis-7976ffadc0f21ee9149708c0c97ef000e15de1eb", urls = ["https://github.com/googleapis/googleapis/archive/7976ffadc0f21ee9149708c0c97ef000e15de1eb.zip"], sha256 = "935fb7ebbc65f43e293fac7240471c24d9d52249f5c8bf09c0d04327b2191053" ) load("@com_google_googleapis//:repository_rules.bzl", "switched_rules_by_language") switched_rules_by_language(name = "com_google_googleapis_imports", grpc = True) ## # protobuf for the protobuf protos # http_archive( name = "com_google_protobuf", sha256 = "ddd0f5271f31b549efc74eb39061e142132653d5d043071fcec265bd571e73c4", urls = ["https://github.com/protocolbuffers/protobuf/archive/v25.2.zip"], strip_prefix = "protobuf-25.2", ) load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") protobuf_deps() http_archive( name = "bazel_features", sha256 = "5d7e4eb0bb17aee392143cd667b67d9044c270a9345776a5e5a3cccbc44aa4b3", strip_prefix = "bazel_features-1.13.0", url = "https://github.com/bazel-contrib/bazel_features/releases/download/v1.13.0/bazel_features-v1.13.0.tar.gz", ) load("@bazel_features//:deps.bzl", "bazel_features_deps") bazel_features_deps() ## # rules_proto for the proto_library rule # http_archive( name = "rules_proto", sha256 = "6fb6767d1bef535310547e03247f7518b03487740c11b6c6adb7952033fe1295", # Using a release candidate because the latest stable release is too old for # our needs, and we want to stay closer to the latest without pinning to a # specific commit. strip_prefix = "rules_proto-6.0.2", url = "https://github.com/bazelbuild/rules_proto/releases/download/6.0.2/rules_proto-6.0.2.tar.gz", ) load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies","rules_proto_toolchains") rules_proto_dependencies() rules_proto_toolchains() ================================================ FILE: client/auxiliary.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go_gapic. DO NOT EDIT. package client import ( "context" "time" "cloud.google.com/go/longrunning" longrunningpb "cloud.google.com/go/longrunning/autogen/longrunningpb" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" gax "github.com/googleapis/gax-go/v2" "google.golang.org/api/iterator" locationpb "google.golang.org/genproto/googleapis/cloud/location" ) // SearchBlurbsOperation manages a long-running operation from SearchBlurbs. type SearchBlurbsOperation struct { lro *longrunning.Operation pollPath string } // Wait blocks until the long-running operation is completed, returning the response and any errors encountered. // // See documentation of Poll for error-handling information. func (op *SearchBlurbsOperation) Wait(ctx context.Context, opts ...gax.CallOption) (*genprotopb.SearchBlurbsResponse, error) { opts = append([]gax.CallOption{gax.WithPath(op.pollPath)}, opts...) var resp genprotopb.SearchBlurbsResponse if err := op.lro.WaitWithInterval(ctx, &resp, time.Minute, opts...); err != nil { return nil, err } return &resp, nil } // Poll fetches the latest state of the long-running operation. // // Poll also fetches the latest metadata, which can be retrieved by Metadata. // // If Poll fails, the error is returned and op is unmodified. If Poll succeeds and // the operation has completed with failure, the error is returned and op.Done will return true. // If Poll succeeds and the operation has completed successfully, // op.Done will return true, and the response of the operation is returned. // If Poll succeeds and the operation has not completed, the returned response and error are both nil. func (op *SearchBlurbsOperation) Poll(ctx context.Context, opts ...gax.CallOption) (*genprotopb.SearchBlurbsResponse, error) { opts = append([]gax.CallOption{gax.WithPath(op.pollPath)}, opts...) var resp genprotopb.SearchBlurbsResponse if err := op.lro.Poll(ctx, &resp, opts...); err != nil { return nil, err } if !op.Done() { return nil, nil } return &resp, nil } // Metadata returns metadata associated with the long-running operation. // Metadata itself does not contact the server, but Poll does. // To get the latest metadata, call this method after a successful call to Poll. // If the metadata is not available, the returned metadata and error are both nil. func (op *SearchBlurbsOperation) Metadata() (*genprotopb.SearchBlurbsMetadata, error) { var meta genprotopb.SearchBlurbsMetadata if err := op.lro.Metadata(&meta); err == longrunning.ErrNoMetadata { return nil, nil } else if err != nil { return nil, err } return &meta, nil } // Done reports whether the long-running operation has completed. func (op *SearchBlurbsOperation) Done() bool { return op.lro.Done() } // Name returns the name of the long-running operation. // The name is assigned by the server and is unique within the service from which the operation is created. func (op *SearchBlurbsOperation) Name() string { return op.lro.Name() } // WaitOperation manages a long-running operation from Wait. type WaitOperation struct { lro *longrunning.Operation pollPath string } // Wait blocks until the long-running operation is completed, returning the response and any errors encountered. // // See documentation of Poll for error-handling information. func (op *WaitOperation) Wait(ctx context.Context, opts ...gax.CallOption) (*genprotopb.WaitResponse, error) { opts = append([]gax.CallOption{gax.WithPath(op.pollPath)}, opts...) var resp genprotopb.WaitResponse if err := op.lro.WaitWithInterval(ctx, &resp, time.Minute, opts...); err != nil { return nil, err } return &resp, nil } // Poll fetches the latest state of the long-running operation. // // Poll also fetches the latest metadata, which can be retrieved by Metadata. // // If Poll fails, the error is returned and op is unmodified. If Poll succeeds and // the operation has completed with failure, the error is returned and op.Done will return true. // If Poll succeeds and the operation has completed successfully, // op.Done will return true, and the response of the operation is returned. // If Poll succeeds and the operation has not completed, the returned response and error are both nil. func (op *WaitOperation) Poll(ctx context.Context, opts ...gax.CallOption) (*genprotopb.WaitResponse, error) { opts = append([]gax.CallOption{gax.WithPath(op.pollPath)}, opts...) var resp genprotopb.WaitResponse if err := op.lro.Poll(ctx, &resp, opts...); err != nil { return nil, err } if !op.Done() { return nil, nil } return &resp, nil } // Metadata returns metadata associated with the long-running operation. // Metadata itself does not contact the server, but Poll does. // To get the latest metadata, call this method after a successful call to Poll. // If the metadata is not available, the returned metadata and error are both nil. func (op *WaitOperation) Metadata() (*genprotopb.WaitMetadata, error) { var meta genprotopb.WaitMetadata if err := op.lro.Metadata(&meta); err == longrunning.ErrNoMetadata { return nil, nil } else if err != nil { return nil, err } return &meta, nil } // Done reports whether the long-running operation has completed. func (op *WaitOperation) Done() bool { return op.lro.Done() } // Name returns the name of the long-running operation. // The name is assigned by the server and is unique within the service from which the operation is created. func (op *WaitOperation) Name() string { return op.lro.Name() } // BlurbIterator manages a stream of *genprotopb.Blurb. type BlurbIterator struct { items []*genprotopb.Blurb pageInfo *iterator.PageInfo nextFunc func() error // Response is the raw response for the current page. // It must be cast to the RPC response type. // Calling Next() or InternalFetch() updates this value. Response interface{} // InternalFetch is for use by the Google Cloud Libraries only. // It is not part of the stable interface of this package. // // InternalFetch returns results from a single call to the underlying RPC. // The number of results is no greater than pageSize. // If there are no more results, nextPageToken is empty and err is nil. InternalFetch func(pageSize int, pageToken string) (results []*genprotopb.Blurb, nextPageToken string, err error) } // PageInfo supports pagination. See the [google.golang.org/api/iterator] package for details. func (it *BlurbIterator) PageInfo() *iterator.PageInfo { return it.pageInfo } // Next returns the next result. Its second return value is iterator.Done if there are no more // results. Once Next returns Done, all subsequent calls will return Done. func (it *BlurbIterator) Next() (*genprotopb.Blurb, error) { var item *genprotopb.Blurb if err := it.nextFunc(); err != nil { return item, err } item = it.items[0] it.items = it.items[1:] return item, nil } func (it *BlurbIterator) bufLen() int { return len(it.items) } func (it *BlurbIterator) takeBuf() interface{} { b := it.items it.items = nil return b } // EchoResponseIterator manages a stream of *genprotopb.EchoResponse. type EchoResponseIterator struct { items []*genprotopb.EchoResponse pageInfo *iterator.PageInfo nextFunc func() error // Response is the raw response for the current page. // It must be cast to the RPC response type. // Calling Next() or InternalFetch() updates this value. Response interface{} // InternalFetch is for use by the Google Cloud Libraries only. // It is not part of the stable interface of this package. // // InternalFetch returns results from a single call to the underlying RPC. // The number of results is no greater than pageSize. // If there are no more results, nextPageToken is empty and err is nil. InternalFetch func(pageSize int, pageToken string) (results []*genprotopb.EchoResponse, nextPageToken string, err error) } // PageInfo supports pagination. See the [google.golang.org/api/iterator] package for details. func (it *EchoResponseIterator) PageInfo() *iterator.PageInfo { return it.pageInfo } // Next returns the next result. Its second return value is iterator.Done if there are no more // results. Once Next returns Done, all subsequent calls will return Done. func (it *EchoResponseIterator) Next() (*genprotopb.EchoResponse, error) { var item *genprotopb.EchoResponse if err := it.nextFunc(); err != nil { return item, err } item = it.items[0] it.items = it.items[1:] return item, nil } func (it *EchoResponseIterator) bufLen() int { return len(it.items) } func (it *EchoResponseIterator) takeBuf() interface{} { b := it.items it.items = nil return b } // LocationIterator manages a stream of *locationpb.Location. type LocationIterator struct { items []*locationpb.Location pageInfo *iterator.PageInfo nextFunc func() error // Response is the raw response for the current page. // It must be cast to the RPC response type. // Calling Next() or InternalFetch() updates this value. Response interface{} // InternalFetch is for use by the Google Cloud Libraries only. // It is not part of the stable interface of this package. // // InternalFetch returns results from a single call to the underlying RPC. // The number of results is no greater than pageSize. // If there are no more results, nextPageToken is empty and err is nil. InternalFetch func(pageSize int, pageToken string) (results []*locationpb.Location, nextPageToken string, err error) } // PageInfo supports pagination. See the [google.golang.org/api/iterator] package for details. func (it *LocationIterator) PageInfo() *iterator.PageInfo { return it.pageInfo } // Next returns the next result. Its second return value is iterator.Done if there are no more // results. Once Next returns Done, all subsequent calls will return Done. func (it *LocationIterator) Next() (*locationpb.Location, error) { var item *locationpb.Location if err := it.nextFunc(); err != nil { return item, err } item = it.items[0] it.items = it.items[1:] return item, nil } func (it *LocationIterator) bufLen() int { return len(it.items) } func (it *LocationIterator) takeBuf() interface{} { b := it.items it.items = nil return b } // OperationIterator manages a stream of *longrunningpb.Operation. type OperationIterator struct { items []*longrunningpb.Operation pageInfo *iterator.PageInfo nextFunc func() error // Response is the raw response for the current page. // It must be cast to the RPC response type. // Calling Next() or InternalFetch() updates this value. Response interface{} // InternalFetch is for use by the Google Cloud Libraries only. // It is not part of the stable interface of this package. // // InternalFetch returns results from a single call to the underlying RPC. // The number of results is no greater than pageSize. // If there are no more results, nextPageToken is empty and err is nil. InternalFetch func(pageSize int, pageToken string) (results []*longrunningpb.Operation, nextPageToken string, err error) } // PageInfo supports pagination. See the [google.golang.org/api/iterator] package for details. func (it *OperationIterator) PageInfo() *iterator.PageInfo { return it.pageInfo } // Next returns the next result. Its second return value is iterator.Done if there are no more // results. Once Next returns Done, all subsequent calls will return Done. func (it *OperationIterator) Next() (*longrunningpb.Operation, error) { var item *longrunningpb.Operation if err := it.nextFunc(); err != nil { return item, err } item = it.items[0] it.items = it.items[1:] return item, nil } func (it *OperationIterator) bufLen() int { return len(it.items) } func (it *OperationIterator) takeBuf() interface{} { b := it.items it.items = nil return b } // PagedExpandResponseListPair is a holder type for string/*genprotopb.PagedExpandResponseList map entries type PagedExpandResponseListPair struct { Key string Value *genprotopb.PagedExpandResponseList } // PagedExpandResponseListPairIterator manages a stream of PagedExpandResponseListPair. type PagedExpandResponseListPairIterator struct { items []PagedExpandResponseListPair pageInfo *iterator.PageInfo nextFunc func() error // Response is the raw response for the current page. // It must be cast to the RPC response type. // Calling Next() or InternalFetch() updates this value. Response interface{} // InternalFetch is for use by the Google Cloud Libraries only. // It is not part of the stable interface of this package. // // InternalFetch returns results from a single call to the underlying RPC. // The number of results is no greater than pageSize. // If there are no more results, nextPageToken is empty and err is nil. InternalFetch func(pageSize int, pageToken string) (results []PagedExpandResponseListPair, nextPageToken string, err error) } // PageInfo supports pagination. See the [google.golang.org/api/iterator] package for details. func (it *PagedExpandResponseListPairIterator) PageInfo() *iterator.PageInfo { return it.pageInfo } // Next returns the next result. Its second return value is iterator.Done if there are no more // results. Once Next returns Done, all subsequent calls will return Done. func (it *PagedExpandResponseListPairIterator) Next() (PagedExpandResponseListPair, error) { var item PagedExpandResponseListPair if err := it.nextFunc(); err != nil { return item, err } item = it.items[0] it.items = it.items[1:] return item, nil } func (it *PagedExpandResponseListPairIterator) bufLen() int { return len(it.items) } func (it *PagedExpandResponseListPairIterator) takeBuf() interface{} { b := it.items it.items = nil return b } // RoomIterator manages a stream of *genprotopb.Room. type RoomIterator struct { items []*genprotopb.Room pageInfo *iterator.PageInfo nextFunc func() error // Response is the raw response for the current page. // It must be cast to the RPC response type. // Calling Next() or InternalFetch() updates this value. Response interface{} // InternalFetch is for use by the Google Cloud Libraries only. // It is not part of the stable interface of this package. // // InternalFetch returns results from a single call to the underlying RPC. // The number of results is no greater than pageSize. // If there are no more results, nextPageToken is empty and err is nil. InternalFetch func(pageSize int, pageToken string) (results []*genprotopb.Room, nextPageToken string, err error) } // PageInfo supports pagination. See the [google.golang.org/api/iterator] package for details. func (it *RoomIterator) PageInfo() *iterator.PageInfo { return it.pageInfo } // Next returns the next result. Its second return value is iterator.Done if there are no more // results. Once Next returns Done, all subsequent calls will return Done. func (it *RoomIterator) Next() (*genprotopb.Room, error) { var item *genprotopb.Room if err := it.nextFunc(); err != nil { return item, err } item = it.items[0] it.items = it.items[1:] return item, nil } func (it *RoomIterator) bufLen() int { return len(it.items) } func (it *RoomIterator) takeBuf() interface{} { b := it.items it.items = nil return b } // SessionIterator manages a stream of *genprotopb.Session. type SessionIterator struct { items []*genprotopb.Session pageInfo *iterator.PageInfo nextFunc func() error // Response is the raw response for the current page. // It must be cast to the RPC response type. // Calling Next() or InternalFetch() updates this value. Response interface{} // InternalFetch is for use by the Google Cloud Libraries only. // It is not part of the stable interface of this package. // // InternalFetch returns results from a single call to the underlying RPC. // The number of results is no greater than pageSize. // If there are no more results, nextPageToken is empty and err is nil. InternalFetch func(pageSize int, pageToken string) (results []*genprotopb.Session, nextPageToken string, err error) } // PageInfo supports pagination. See the [google.golang.org/api/iterator] package for details. func (it *SessionIterator) PageInfo() *iterator.PageInfo { return it.pageInfo } // Next returns the next result. Its second return value is iterator.Done if there are no more // results. Once Next returns Done, all subsequent calls will return Done. func (it *SessionIterator) Next() (*genprotopb.Session, error) { var item *genprotopb.Session if err := it.nextFunc(); err != nil { return item, err } item = it.items[0] it.items = it.items[1:] return item, nil } func (it *SessionIterator) bufLen() int { return len(it.items) } func (it *SessionIterator) takeBuf() interface{} { b := it.items it.items = nil return b } // TestIterator manages a stream of *genprotopb.Test. type TestIterator struct { items []*genprotopb.Test pageInfo *iterator.PageInfo nextFunc func() error // Response is the raw response for the current page. // It must be cast to the RPC response type. // Calling Next() or InternalFetch() updates this value. Response interface{} // InternalFetch is for use by the Google Cloud Libraries only. // It is not part of the stable interface of this package. // // InternalFetch returns results from a single call to the underlying RPC. // The number of results is no greater than pageSize. // If there are no more results, nextPageToken is empty and err is nil. InternalFetch func(pageSize int, pageToken string) (results []*genprotopb.Test, nextPageToken string, err error) } // PageInfo supports pagination. See the [google.golang.org/api/iterator] package for details. func (it *TestIterator) PageInfo() *iterator.PageInfo { return it.pageInfo } // Next returns the next result. Its second return value is iterator.Done if there are no more // results. Once Next returns Done, all subsequent calls will return Done. func (it *TestIterator) Next() (*genprotopb.Test, error) { var item *genprotopb.Test if err := it.nextFunc(); err != nil { return item, err } item = it.items[0] it.items = it.items[1:] return item, nil } func (it *TestIterator) bufLen() int { return len(it.items) } func (it *TestIterator) takeBuf() interface{} { b := it.items it.items = nil return b } // UserIterator manages a stream of *genprotopb.User. type UserIterator struct { items []*genprotopb.User pageInfo *iterator.PageInfo nextFunc func() error // Response is the raw response for the current page. // It must be cast to the RPC response type. // Calling Next() or InternalFetch() updates this value. Response interface{} // InternalFetch is for use by the Google Cloud Libraries only. // It is not part of the stable interface of this package. // // InternalFetch returns results from a single call to the underlying RPC. // The number of results is no greater than pageSize. // If there are no more results, nextPageToken is empty and err is nil. InternalFetch func(pageSize int, pageToken string) (results []*genprotopb.User, nextPageToken string, err error) } // PageInfo supports pagination. See the [google.golang.org/api/iterator] package for details. func (it *UserIterator) PageInfo() *iterator.PageInfo { return it.pageInfo } // Next returns the next result. Its second return value is iterator.Done if there are no more // results. Once Next returns Done, all subsequent calls will return Done. func (it *UserIterator) Next() (*genprotopb.User, error) { var item *genprotopb.User if err := it.nextFunc(); err != nil { return item, err } item = it.items[0] it.items = it.items[1:] return item, nil } func (it *UserIterator) bufLen() int { return len(it.items) } func (it *UserIterator) takeBuf() interface{} { b := it.items it.items = nil return b } ================================================ FILE: client/auxiliary_go123.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go_gapic. DO NOT EDIT. //go:build go1.23 package client import ( "iter" longrunningpb "cloud.google.com/go/longrunning/autogen/longrunningpb" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/googleapis/gax-go/v2/iterator" locationpb "google.golang.org/genproto/googleapis/cloud/location" ) // All returns an iterator. If an error is returned by the iterator, the // iterator will stop after that iteration. func (it *BlurbIterator) All() iter.Seq2[*genprotopb.Blurb, error] { return iterator.RangeAdapter(it.Next) } // All returns an iterator. If an error is returned by the iterator, the // iterator will stop after that iteration. func (it *EchoResponseIterator) All() iter.Seq2[*genprotopb.EchoResponse, error] { return iterator.RangeAdapter(it.Next) } // All returns an iterator. If an error is returned by the iterator, the // iterator will stop after that iteration. func (it *LocationIterator) All() iter.Seq2[*locationpb.Location, error] { return iterator.RangeAdapter(it.Next) } // All returns an iterator. If an error is returned by the iterator, the // iterator will stop after that iteration. func (it *OperationIterator) All() iter.Seq2[*longrunningpb.Operation, error] { return iterator.RangeAdapter(it.Next) } // All returns an iterator. If an error is returned by the iterator, the // iterator will stop after that iteration. func (it *PagedExpandResponseListPairIterator) All() iter.Seq2[PagedExpandResponseListPair, error] { return iterator.RangeAdapter(it.Next) } // All returns an iterator. If an error is returned by the iterator, the // iterator will stop after that iteration. func (it *RoomIterator) All() iter.Seq2[*genprotopb.Room, error] { return iterator.RangeAdapter(it.Next) } // All returns an iterator. If an error is returned by the iterator, the // iterator will stop after that iteration. func (it *SessionIterator) All() iter.Seq2[*genprotopb.Session, error] { return iterator.RangeAdapter(it.Next) } // All returns an iterator. If an error is returned by the iterator, the // iterator will stop after that iteration. func (it *TestIterator) All() iter.Seq2[*genprotopb.Test, error] { return iterator.RangeAdapter(it.Next) } // All returns an iterator. If an error is returned by the iterator, the // iterator will stop after that iteration. func (it *UserIterator) All() iter.Seq2[*genprotopb.User, error] { return iterator.RangeAdapter(it.Next) } ================================================ FILE: client/compliance_client.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go_gapic. DO NOT EDIT. package client import ( "bytes" "context" "fmt" "log/slog" "math" "net/http" "net/url" iampb "cloud.google.com/go/iam/apiv1/iampb" longrunningpb "cloud.google.com/go/longrunning/autogen/longrunningpb" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" gax "github.com/googleapis/gax-go/v2" "google.golang.org/api/iterator" "google.golang.org/api/option" "google.golang.org/api/option/internaloption" gtransport "google.golang.org/api/transport/grpc" httptransport "google.golang.org/api/transport/http" locationpb "google.golang.org/genproto/googleapis/cloud/location" "google.golang.org/grpc" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" ) var newComplianceClientHook clientHook // ComplianceCallOptions contains the retry settings for each method of ComplianceClient. type ComplianceCallOptions struct { RepeatDataBody []gax.CallOption RepeatDataBodyInfo []gax.CallOption RepeatDataQuery []gax.CallOption RepeatDataSimplePath []gax.CallOption RepeatDataPathResource []gax.CallOption RepeatDataPathTrailingResource []gax.CallOption RepeatDataBodyPut []gax.CallOption RepeatDataBodyPatch []gax.CallOption GetEnum []gax.CallOption VerifyEnum []gax.CallOption ListLocations []gax.CallOption GetLocation []gax.CallOption SetIamPolicy []gax.CallOption GetIamPolicy []gax.CallOption TestIamPermissions []gax.CallOption ListOperations []gax.CallOption GetOperation []gax.CallOption DeleteOperation []gax.CallOption CancelOperation []gax.CallOption } func defaultComplianceGRPCClientOptions() []option.ClientOption { return []option.ClientOption{ internaloption.WithDefaultEndpoint("localhost:7469"), internaloption.WithDefaultEndpointTemplate("localhost:7469"), internaloption.WithDefaultMTLSEndpoint("localhost:7469"), internaloption.WithDefaultUniverseDomain("googleapis.com"), internaloption.WithDefaultAudience("https://localhost/"), internaloption.WithDefaultScopes(DefaultAuthScopes()...), internaloption.EnableJwtWithScope(), internaloption.EnableNewAuthLibrary(), option.WithGRPCDialOption(grpc.WithDefaultCallOptions( grpc.MaxCallRecvMsgSize(math.MaxInt32))), } } func defaultComplianceCallOptions() *ComplianceCallOptions { return &ComplianceCallOptions{ RepeatDataBody: []gax.CallOption{}, RepeatDataBodyInfo: []gax.CallOption{}, RepeatDataQuery: []gax.CallOption{}, RepeatDataSimplePath: []gax.CallOption{}, RepeatDataPathResource: []gax.CallOption{}, RepeatDataPathTrailingResource: []gax.CallOption{}, RepeatDataBodyPut: []gax.CallOption{}, RepeatDataBodyPatch: []gax.CallOption{}, GetEnum: []gax.CallOption{}, VerifyEnum: []gax.CallOption{}, ListLocations: []gax.CallOption{}, GetLocation: []gax.CallOption{}, SetIamPolicy: []gax.CallOption{}, GetIamPolicy: []gax.CallOption{}, TestIamPermissions: []gax.CallOption{}, ListOperations: []gax.CallOption{}, GetOperation: []gax.CallOption{}, DeleteOperation: []gax.CallOption{}, CancelOperation: []gax.CallOption{}, } } func defaultComplianceRESTCallOptions() *ComplianceCallOptions { return &ComplianceCallOptions{ RepeatDataBody: []gax.CallOption{}, RepeatDataBodyInfo: []gax.CallOption{}, RepeatDataQuery: []gax.CallOption{}, RepeatDataSimplePath: []gax.CallOption{}, RepeatDataPathResource: []gax.CallOption{}, RepeatDataPathTrailingResource: []gax.CallOption{}, RepeatDataBodyPut: []gax.CallOption{}, RepeatDataBodyPatch: []gax.CallOption{}, GetEnum: []gax.CallOption{}, VerifyEnum: []gax.CallOption{}, ListLocations: []gax.CallOption{}, GetLocation: []gax.CallOption{}, SetIamPolicy: []gax.CallOption{}, GetIamPolicy: []gax.CallOption{}, TestIamPermissions: []gax.CallOption{}, ListOperations: []gax.CallOption{}, GetOperation: []gax.CallOption{}, DeleteOperation: []gax.CallOption{}, CancelOperation: []gax.CallOption{}, } } // internalComplianceClient is an interface that defines the methods available from Client Libraries Showcase API. type internalComplianceClient interface { Close() error setGoogleClientInfo(...string) Connection() *grpc.ClientConn RepeatDataBody(context.Context, *genprotopb.RepeatRequest, ...gax.CallOption) (*genprotopb.RepeatResponse, error) RepeatDataBodyInfo(context.Context, *genprotopb.RepeatRequest, ...gax.CallOption) (*genprotopb.RepeatResponse, error) RepeatDataQuery(context.Context, *genprotopb.RepeatRequest, ...gax.CallOption) (*genprotopb.RepeatResponse, error) RepeatDataSimplePath(context.Context, *genprotopb.RepeatRequest, ...gax.CallOption) (*genprotopb.RepeatResponse, error) RepeatDataPathResource(context.Context, *genprotopb.RepeatRequest, ...gax.CallOption) (*genprotopb.RepeatResponse, error) RepeatDataPathTrailingResource(context.Context, *genprotopb.RepeatRequest, ...gax.CallOption) (*genprotopb.RepeatResponse, error) RepeatDataBodyPut(context.Context, *genprotopb.RepeatRequest, ...gax.CallOption) (*genprotopb.RepeatResponse, error) RepeatDataBodyPatch(context.Context, *genprotopb.RepeatRequest, ...gax.CallOption) (*genprotopb.RepeatResponse, error) GetEnum(context.Context, *genprotopb.EnumRequest, ...gax.CallOption) (*genprotopb.EnumResponse, error) VerifyEnum(context.Context, *genprotopb.EnumResponse, ...gax.CallOption) (*genprotopb.EnumResponse, error) ListLocations(context.Context, *locationpb.ListLocationsRequest, ...gax.CallOption) *LocationIterator GetLocation(context.Context, *locationpb.GetLocationRequest, ...gax.CallOption) (*locationpb.Location, error) SetIamPolicy(context.Context, *iampb.SetIamPolicyRequest, ...gax.CallOption) (*iampb.Policy, error) GetIamPolicy(context.Context, *iampb.GetIamPolicyRequest, ...gax.CallOption) (*iampb.Policy, error) TestIamPermissions(context.Context, *iampb.TestIamPermissionsRequest, ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error) ListOperations(context.Context, *longrunningpb.ListOperationsRequest, ...gax.CallOption) *OperationIterator GetOperation(context.Context, *longrunningpb.GetOperationRequest, ...gax.CallOption) (*longrunningpb.Operation, error) DeleteOperation(context.Context, *longrunningpb.DeleteOperationRequest, ...gax.CallOption) error CancelOperation(context.Context, *longrunningpb.CancelOperationRequest, ...gax.CallOption) error } // ComplianceClient is a client for interacting with Client Libraries Showcase API. // Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls. // // This service is used to test that GAPICs implement various REST-related features correctly. This mostly means transcoding proto3 requests to REST format // correctly for various types of HTTP annotations, but it also includes verifying that unknown (numeric) enums received by clients can be round-tripped // correctly. type ComplianceClient struct { // The internal transport-dependent client. internalClient internalComplianceClient // The call options for this service. CallOptions *ComplianceCallOptions } // Wrapper methods routed to the internal client. // Close closes the connection to the API service. The user should invoke this when // the client is no longer required. func (c *ComplianceClient) Close() error { return c.internalClient.Close() } // setGoogleClientInfo sets the name and version of the application in // the `x-goog-api-client` header passed on each request. Intended for // use by Google-written clients. func (c *ComplianceClient) setGoogleClientInfo(keyval ...string) { c.internalClient.setGoogleClientInfo(keyval...) } // Connection returns a connection to the API service. // // Deprecated: Connections are now pooled so this method does not always // return the same resource. func (c *ComplianceClient) Connection() *grpc.ClientConn { return c.internalClient.Connection() } // RepeatDataBody this method echoes the ComplianceData request. This method exercises // sending the entire request object in the REST body. func (c *ComplianceClient) RepeatDataBody(ctx context.Context, req *genprotopb.RepeatRequest, opts ...gax.CallOption) (*genprotopb.RepeatResponse, error) { return c.internalClient.RepeatDataBody(ctx, req, opts...) } // RepeatDataBodyInfo this method echoes the ComplianceData request. This method exercises // sending the a message-type field in the REST body. Per AIP-127, only // top-level, non-repeated fields can be sent this way. func (c *ComplianceClient) RepeatDataBodyInfo(ctx context.Context, req *genprotopb.RepeatRequest, opts ...gax.CallOption) (*genprotopb.RepeatResponse, error) { return c.internalClient.RepeatDataBodyInfo(ctx, req, opts...) } // RepeatDataQuery this method echoes the ComplianceData request. This method exercises // sending all request fields as query parameters. func (c *ComplianceClient) RepeatDataQuery(ctx context.Context, req *genprotopb.RepeatRequest, opts ...gax.CallOption) (*genprotopb.RepeatResponse, error) { return c.internalClient.RepeatDataQuery(ctx, req, opts...) } // RepeatDataSimplePath this method echoes the ComplianceData request. This method exercises // sending some parameters as “simple” path variables (i.e., of the form // “/bar/{foo}” rather than “/{foo=bar/*}”), and the rest as query parameters. func (c *ComplianceClient) RepeatDataSimplePath(ctx context.Context, req *genprotopb.RepeatRequest, opts ...gax.CallOption) (*genprotopb.RepeatResponse, error) { return c.internalClient.RepeatDataSimplePath(ctx, req, opts...) } // RepeatDataPathResource same as RepeatDataSimplePath, but with a path resource. func (c *ComplianceClient) RepeatDataPathResource(ctx context.Context, req *genprotopb.RepeatRequest, opts ...gax.CallOption) (*genprotopb.RepeatResponse, error) { return c.internalClient.RepeatDataPathResource(ctx, req, opts...) } // RepeatDataPathTrailingResource same as RepeatDataSimplePath, but with a trailing resource. func (c *ComplianceClient) RepeatDataPathTrailingResource(ctx context.Context, req *genprotopb.RepeatRequest, opts ...gax.CallOption) (*genprotopb.RepeatResponse, error) { return c.internalClient.RepeatDataPathTrailingResource(ctx, req, opts...) } // RepeatDataBodyPut this method echoes the ComplianceData request, using the HTTP PUT method. func (c *ComplianceClient) RepeatDataBodyPut(ctx context.Context, req *genprotopb.RepeatRequest, opts ...gax.CallOption) (*genprotopb.RepeatResponse, error) { return c.internalClient.RepeatDataBodyPut(ctx, req, opts...) } // RepeatDataBodyPatch this method echoes the ComplianceData request, using the HTTP PATCH method. func (c *ComplianceClient) RepeatDataBodyPatch(ctx context.Context, req *genprotopb.RepeatRequest, opts ...gax.CallOption) (*genprotopb.RepeatResponse, error) { return c.internalClient.RepeatDataBodyPatch(ctx, req, opts...) } // GetEnum this method requests an enum value from the server. Depending on the contents of EnumRequest, the enum value returned will be a known enum declared in the // .proto file, or a made-up enum value the is unknown to the client. To verify that clients can round-trip unknown enum values they receive, use the // response from this RPC as the request to VerifyEnum() // // The values of enums sent by the server when a known or unknown value is requested will be the same within a single Showcase server run (this is needed for // VerifyEnum() to work) but are not guaranteed to be the same across separate Showcase server runs. func (c *ComplianceClient) GetEnum(ctx context.Context, req *genprotopb.EnumRequest, opts ...gax.CallOption) (*genprotopb.EnumResponse, error) { return c.internalClient.GetEnum(ctx, req, opts...) } // VerifyEnum this method is used to verify that clients can round-trip enum values, which is particularly important for unknown enum values over REST. VerifyEnum() // verifies that its request, which is presumably the response that the client previously got to a GetEnum(), contains the correct data. If so, it responds // with the same EnumResponse; otherwise, the RPC errors. // // This works because the values of enums sent by the server when a known or unknown value is requested will be the same within a single Showcase server run, // although they are not guaranteed to be the same across separate Showcase server runs. func (c *ComplianceClient) VerifyEnum(ctx context.Context, req *genprotopb.EnumResponse, opts ...gax.CallOption) (*genprotopb.EnumResponse, error) { return c.internalClient.VerifyEnum(ctx, req, opts...) } // ListLocations is a utility method from google.cloud.location.Locations. func (c *ComplianceClient) ListLocations(ctx context.Context, req *locationpb.ListLocationsRequest, opts ...gax.CallOption) *LocationIterator { return c.internalClient.ListLocations(ctx, req, opts...) } // GetLocation is a utility method from google.cloud.location.Locations. func (c *ComplianceClient) GetLocation(ctx context.Context, req *locationpb.GetLocationRequest, opts ...gax.CallOption) (*locationpb.Location, error) { return c.internalClient.GetLocation(ctx, req, opts...) } // SetIamPolicy is a utility method from google.iam.v1.IAMPolicy. func (c *ComplianceClient) SetIamPolicy(ctx context.Context, req *iampb.SetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { return c.internalClient.SetIamPolicy(ctx, req, opts...) } // GetIamPolicy is a utility method from google.iam.v1.IAMPolicy. func (c *ComplianceClient) GetIamPolicy(ctx context.Context, req *iampb.GetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { return c.internalClient.GetIamPolicy(ctx, req, opts...) } // TestIamPermissions is a utility method from google.iam.v1.IAMPolicy. func (c *ComplianceClient) TestIamPermissions(ctx context.Context, req *iampb.TestIamPermissionsRequest, opts ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error) { return c.internalClient.TestIamPermissions(ctx, req, opts...) } // ListOperations is a utility method from google.longrunning.Operations. func (c *ComplianceClient) ListOperations(ctx context.Context, req *longrunningpb.ListOperationsRequest, opts ...gax.CallOption) *OperationIterator { return c.internalClient.ListOperations(ctx, req, opts...) } // GetOperation is a utility method from google.longrunning.Operations. func (c *ComplianceClient) GetOperation(ctx context.Context, req *longrunningpb.GetOperationRequest, opts ...gax.CallOption) (*longrunningpb.Operation, error) { return c.internalClient.GetOperation(ctx, req, opts...) } // DeleteOperation is a utility method from google.longrunning.Operations. func (c *ComplianceClient) DeleteOperation(ctx context.Context, req *longrunningpb.DeleteOperationRequest, opts ...gax.CallOption) error { return c.internalClient.DeleteOperation(ctx, req, opts...) } // CancelOperation is a utility method from google.longrunning.Operations. func (c *ComplianceClient) CancelOperation(ctx context.Context, req *longrunningpb.CancelOperationRequest, opts ...gax.CallOption) error { return c.internalClient.CancelOperation(ctx, req, opts...) } // complianceGRPCClient is a client for interacting with Client Libraries Showcase API over gRPC transport. // // Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls. type complianceGRPCClient struct { // Connection pool of gRPC connections to the service. connPool gtransport.ConnPool // Points back to the CallOptions field of the containing ComplianceClient CallOptions **ComplianceCallOptions // The gRPC API client. complianceClient genprotopb.ComplianceClient operationsClient longrunningpb.OperationsClient iamPolicyClient iampb.IAMPolicyClient locationsClient locationpb.LocationsClient // The x-goog-* metadata to be sent with each request. xGoogHeaders []string logger *slog.Logger } // NewComplianceClient creates a new compliance client based on gRPC. // The returned client must be Closed when it is done being used to clean up its underlying connections. // // This service is used to test that GAPICs implement various REST-related features correctly. This mostly means transcoding proto3 requests to REST format // correctly for various types of HTTP annotations, but it also includes verifying that unknown (numeric) enums received by clients can be round-tripped // correctly. func NewComplianceClient(ctx context.Context, opts ...option.ClientOption) (*ComplianceClient, error) { clientOpts := defaultComplianceGRPCClientOptions() if newComplianceClientHook != nil { hookOpts, err := newComplianceClientHook(ctx, clientHookParams{}) if err != nil { return nil, err } clientOpts = append(clientOpts, hookOpts...) } connPool, err := gtransport.DialPool(ctx, append(clientOpts, opts...)...) if err != nil { return nil, err } client := ComplianceClient{CallOptions: defaultComplianceCallOptions()} c := &complianceGRPCClient{ connPool: connPool, complianceClient: genprotopb.NewComplianceClient(connPool), CallOptions: &client.CallOptions, logger: internaloption.GetLogger(opts), operationsClient: longrunningpb.NewOperationsClient(connPool), iamPolicyClient: iampb.NewIAMPolicyClient(connPool), locationsClient: locationpb.NewLocationsClient(connPool), } c.setGoogleClientInfo() client.internalClient = c return &client, nil } // Connection returns a connection to the API service. // // Deprecated: Connections are now pooled so this method does not always // return the same resource. func (c *complianceGRPCClient) Connection() *grpc.ClientConn { return c.connPool.Conn() } // setGoogleClientInfo sets the name and version of the application in // the `x-goog-api-client` header passed on each request. Intended for // use by Google-written clients. func (c *complianceGRPCClient) setGoogleClientInfo(keyval ...string) { kv := append([]string{"gl-go", gax.GoVersion}, keyval...) kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "grpc", grpc.Version, "pb", protoVersion) c.xGoogHeaders = []string{ "x-goog-api-client", gax.XGoogHeader(kv...), } } // Close closes the connection to the API service. The user should invoke this when // the client is no longer required. func (c *complianceGRPCClient) Close() error { return c.connPool.Close() } // Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls. type complianceRESTClient struct { // The http endpoint to connect to. endpoint string // The http client. httpClient *http.Client // The x-goog-* headers to be sent with each request. xGoogHeaders []string // Points back to the CallOptions field of the containing ComplianceClient CallOptions **ComplianceCallOptions logger *slog.Logger } // NewComplianceRESTClient creates a new compliance rest client. // // This service is used to test that GAPICs implement various REST-related features correctly. This mostly means transcoding proto3 requests to REST format // correctly for various types of HTTP annotations, but it also includes verifying that unknown (numeric) enums received by clients can be round-tripped // correctly. func NewComplianceRESTClient(ctx context.Context, opts ...option.ClientOption) (*ComplianceClient, error) { clientOpts := append(defaultComplianceRESTClientOptions(), opts...) httpClient, endpoint, err := httptransport.NewClient(ctx, clientOpts...) if err != nil { return nil, err } callOpts := defaultComplianceRESTCallOptions() c := &complianceRESTClient{ endpoint: endpoint, httpClient: httpClient, CallOptions: &callOpts, logger: internaloption.GetLogger(opts), } c.setGoogleClientInfo() return &ComplianceClient{internalClient: c, CallOptions: callOpts}, nil } func defaultComplianceRESTClientOptions() []option.ClientOption { return []option.ClientOption{ internaloption.WithDefaultEndpoint("https://localhost:7469"), internaloption.WithDefaultEndpointTemplate("https://localhost:7469"), internaloption.WithDefaultMTLSEndpoint("https://localhost:7469"), internaloption.WithDefaultUniverseDomain("googleapis.com"), internaloption.WithDefaultAudience("https://localhost/"), internaloption.WithDefaultScopes(DefaultAuthScopes()...), internaloption.EnableNewAuthLibrary(), } } // setGoogleClientInfo sets the name and version of the application in // the `x-goog-api-client` header passed on each request. Intended for // use by Google-written clients. func (c *complianceRESTClient) setGoogleClientInfo(keyval ...string) { kv := append([]string{"gl-go", gax.GoVersion}, keyval...) kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "rest", "UNKNOWN", "pb", protoVersion) c.xGoogHeaders = []string{ "x-goog-api-client", gax.XGoogHeader(kv...), } } // Close closes the connection to the API service. The user should invoke this when // the client is no longer required. func (c *complianceRESTClient) Close() error { // Replace httpClient with nil to force cleanup. c.httpClient = nil return nil } // Connection returns a connection to the API service. // // Deprecated: This method always returns nil. func (c *complianceRESTClient) Connection() *grpc.ClientConn { return nil } func (c *complianceGRPCClient) RepeatDataBody(ctx context.Context, req *genprotopb.RepeatRequest, opts ...gax.CallOption) (*genprotopb.RepeatResponse, error) { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).RepeatDataBody[0:len((*c.CallOptions).RepeatDataBody):len((*c.CallOptions).RepeatDataBody)], opts...) var resp *genprotopb.RepeatResponse err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.complianceClient.RepeatDataBody, req, settings.GRPC, c.logger, "RepeatDataBody") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *complianceGRPCClient) RepeatDataBodyInfo(ctx context.Context, req *genprotopb.RepeatRequest, opts ...gax.CallOption) (*genprotopb.RepeatResponse, error) { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).RepeatDataBodyInfo[0:len((*c.CallOptions).RepeatDataBodyInfo):len((*c.CallOptions).RepeatDataBodyInfo)], opts...) var resp *genprotopb.RepeatResponse err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.complianceClient.RepeatDataBodyInfo, req, settings.GRPC, c.logger, "RepeatDataBodyInfo") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *complianceGRPCClient) RepeatDataQuery(ctx context.Context, req *genprotopb.RepeatRequest, opts ...gax.CallOption) (*genprotopb.RepeatResponse, error) { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).RepeatDataQuery[0:len((*c.CallOptions).RepeatDataQuery):len((*c.CallOptions).RepeatDataQuery)], opts...) var resp *genprotopb.RepeatResponse err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.complianceClient.RepeatDataQuery, req, settings.GRPC, c.logger, "RepeatDataQuery") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *complianceGRPCClient) RepeatDataSimplePath(ctx context.Context, req *genprotopb.RepeatRequest, opts ...gax.CallOption) (*genprotopb.RepeatResponse, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v&%s=%v&%s=%v&%s=%v&%s=%v", "info.f_string", url.QueryEscape(req.GetInfo().GetFString()), "info.f_int32", req.GetInfo().GetFInt32(), "info.f_double", url.QueryEscape(fmt.Sprintf("%g", req.GetInfo().GetFDouble())), "info.f_bool", req.GetInfo().GetFBool(), "info.f_kingdom", genprotopb.ComplianceData_LifeKingdom_name[int32(req.GetInfo().GetFKingdom())])} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).RepeatDataSimplePath[0:len((*c.CallOptions).RepeatDataSimplePath):len((*c.CallOptions).RepeatDataSimplePath)], opts...) var resp *genprotopb.RepeatResponse err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.complianceClient.RepeatDataSimplePath, req, settings.GRPC, c.logger, "RepeatDataSimplePath") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *complianceGRPCClient) RepeatDataPathResource(ctx context.Context, req *genprotopb.RepeatRequest, opts ...gax.CallOption) (*genprotopb.RepeatResponse, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v&%s=%v&%s=%v", "info.f_string", url.QueryEscape(req.GetInfo().GetFString()), "info.f_child.f_string", url.QueryEscape(req.GetInfo().GetFChild().GetFString()), "info.f_bool", req.GetInfo().GetFBool())} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).RepeatDataPathResource[0:len((*c.CallOptions).RepeatDataPathResource):len((*c.CallOptions).RepeatDataPathResource)], opts...) var resp *genprotopb.RepeatResponse err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.complianceClient.RepeatDataPathResource, req, settings.GRPC, c.logger, "RepeatDataPathResource") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *complianceGRPCClient) RepeatDataPathTrailingResource(ctx context.Context, req *genprotopb.RepeatRequest, opts ...gax.CallOption) (*genprotopb.RepeatResponse, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v&%s=%v", "info.f_string", url.QueryEscape(req.GetInfo().GetFString()), "info.f_child.f_string", url.QueryEscape(req.GetInfo().GetFChild().GetFString()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).RepeatDataPathTrailingResource[0:len((*c.CallOptions).RepeatDataPathTrailingResource):len((*c.CallOptions).RepeatDataPathTrailingResource)], opts...) var resp *genprotopb.RepeatResponse err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.complianceClient.RepeatDataPathTrailingResource, req, settings.GRPC, c.logger, "RepeatDataPathTrailingResource") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *complianceGRPCClient) RepeatDataBodyPut(ctx context.Context, req *genprotopb.RepeatRequest, opts ...gax.CallOption) (*genprotopb.RepeatResponse, error) { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).RepeatDataBodyPut[0:len((*c.CallOptions).RepeatDataBodyPut):len((*c.CallOptions).RepeatDataBodyPut)], opts...) var resp *genprotopb.RepeatResponse err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.complianceClient.RepeatDataBodyPut, req, settings.GRPC, c.logger, "RepeatDataBodyPut") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *complianceGRPCClient) RepeatDataBodyPatch(ctx context.Context, req *genprotopb.RepeatRequest, opts ...gax.CallOption) (*genprotopb.RepeatResponse, error) { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).RepeatDataBodyPatch[0:len((*c.CallOptions).RepeatDataBodyPatch):len((*c.CallOptions).RepeatDataBodyPatch)], opts...) var resp *genprotopb.RepeatResponse err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.complianceClient.RepeatDataBodyPatch, req, settings.GRPC, c.logger, "RepeatDataBodyPatch") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *complianceGRPCClient) GetEnum(ctx context.Context, req *genprotopb.EnumRequest, opts ...gax.CallOption) (*genprotopb.EnumResponse, error) { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).GetEnum[0:len((*c.CallOptions).GetEnum):len((*c.CallOptions).GetEnum)], opts...) var resp *genprotopb.EnumResponse err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.complianceClient.GetEnum, req, settings.GRPC, c.logger, "GetEnum") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *complianceGRPCClient) VerifyEnum(ctx context.Context, req *genprotopb.EnumResponse, opts ...gax.CallOption) (*genprotopb.EnumResponse, error) { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).VerifyEnum[0:len((*c.CallOptions).VerifyEnum):len((*c.CallOptions).VerifyEnum)], opts...) var resp *genprotopb.EnumResponse err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.complianceClient.VerifyEnum, req, settings.GRPC, c.logger, "VerifyEnum") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *complianceGRPCClient) ListLocations(ctx context.Context, req *locationpb.ListLocationsRequest, opts ...gax.CallOption) *LocationIterator { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).ListLocations[0:len((*c.CallOptions).ListLocations):len((*c.CallOptions).ListLocations)], opts...) it := &LocationIterator{} req = proto.Clone(req).(*locationpb.ListLocationsRequest) it.InternalFetch = func(pageSize int, pageToken string) ([]*locationpb.Location, string, error) { resp := &locationpb.ListLocationsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.locationsClient.ListLocations, req, settings.GRPC, c.logger, "ListLocations") return err }, opts...) if err != nil { return nil, "", err } it.Response = resp return resp.GetLocations(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } func (c *complianceGRPCClient) GetLocation(ctx context.Context, req *locationpb.GetLocationRequest, opts ...gax.CallOption) (*locationpb.Location, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).GetLocation[0:len((*c.CallOptions).GetLocation):len((*c.CallOptions).GetLocation)], opts...) var resp *locationpb.Location err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.locationsClient.GetLocation, req, settings.GRPC, c.logger, "GetLocation") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *complianceGRPCClient) SetIamPolicy(ctx context.Context, req *iampb.SetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).SetIamPolicy[0:len((*c.CallOptions).SetIamPolicy):len((*c.CallOptions).SetIamPolicy)], opts...) var resp *iampb.Policy err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.iamPolicyClient.SetIamPolicy, req, settings.GRPC, c.logger, "SetIamPolicy") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *complianceGRPCClient) GetIamPolicy(ctx context.Context, req *iampb.GetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).GetIamPolicy[0:len((*c.CallOptions).GetIamPolicy):len((*c.CallOptions).GetIamPolicy)], opts...) var resp *iampb.Policy err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.iamPolicyClient.GetIamPolicy, req, settings.GRPC, c.logger, "GetIamPolicy") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *complianceGRPCClient) TestIamPermissions(ctx context.Context, req *iampb.TestIamPermissionsRequest, opts ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).TestIamPermissions[0:len((*c.CallOptions).TestIamPermissions):len((*c.CallOptions).TestIamPermissions)], opts...) var resp *iampb.TestIamPermissionsResponse err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.iamPolicyClient.TestIamPermissions, req, settings.GRPC, c.logger, "TestIamPermissions") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *complianceGRPCClient) ListOperations(ctx context.Context, req *longrunningpb.ListOperationsRequest, opts ...gax.CallOption) *OperationIterator { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).ListOperations[0:len((*c.CallOptions).ListOperations):len((*c.CallOptions).ListOperations)], opts...) it := &OperationIterator{} req = proto.Clone(req).(*longrunningpb.ListOperationsRequest) it.InternalFetch = func(pageSize int, pageToken string) ([]*longrunningpb.Operation, string, error) { resp := &longrunningpb.ListOperationsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.operationsClient.ListOperations, req, settings.GRPC, c.logger, "ListOperations") return err }, opts...) if err != nil { return nil, "", err } it.Response = resp return resp.GetOperations(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } func (c *complianceGRPCClient) GetOperation(ctx context.Context, req *longrunningpb.GetOperationRequest, opts ...gax.CallOption) (*longrunningpb.Operation, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).GetOperation[0:len((*c.CallOptions).GetOperation):len((*c.CallOptions).GetOperation)], opts...) var resp *longrunningpb.Operation err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.operationsClient.GetOperation, req, settings.GRPC, c.logger, "GetOperation") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *complianceGRPCClient) DeleteOperation(ctx context.Context, req *longrunningpb.DeleteOperationRequest, opts ...gax.CallOption) error { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).DeleteOperation[0:len((*c.CallOptions).DeleteOperation):len((*c.CallOptions).DeleteOperation)], opts...) err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error _, err = executeRPC(ctx, c.operationsClient.DeleteOperation, req, settings.GRPC, c.logger, "DeleteOperation") return err }, opts...) return err } func (c *complianceGRPCClient) CancelOperation(ctx context.Context, req *longrunningpb.CancelOperationRequest, opts ...gax.CallOption) error { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).CancelOperation[0:len((*c.CallOptions).CancelOperation):len((*c.CallOptions).CancelOperation)], opts...) err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error _, err = executeRPC(ctx, c.operationsClient.CancelOperation, req, settings.GRPC, c.logger, "CancelOperation") return err }, opts...) return err } // RepeatDataBody this method echoes the ComplianceData request. This method exercises // sending the entire request object in the REST body. func (c *complianceRESTClient) RepeatDataBody(ctx context.Context, req *genprotopb.RepeatRequest, opts ...gax.CallOption) (*genprotopb.RepeatResponse, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/repeat:body") // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).RepeatDataBody[0:len((*c.CallOptions).RepeatDataBody):len((*c.CallOptions).RepeatDataBody)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.RepeatResponse{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "RepeatDataBody") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // RepeatDataBodyInfo this method echoes the ComplianceData request. This method exercises // sending the a message-type field in the REST body. Per AIP-127, only // top-level, non-repeated fields can be sent this way. func (c *complianceRESTClient) RepeatDataBodyInfo(ctx context.Context, req *genprotopb.RepeatRequest, opts ...gax.CallOption) (*genprotopb.RepeatResponse, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} body := req.GetInfo() jsonReq, err := m.Marshal(body) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/repeat:bodyinfo") params := url.Values{} if req.GetFDouble() != 0 { params.Add("fDouble", fmt.Sprintf("%v", req.GetFDouble())) } if req.GetFInt32() != 0 { params.Add("fInt32", fmt.Sprintf("%v", req.GetFInt32())) } if req.GetFInt64() != 0 { params.Add("fInt64", fmt.Sprintf("%v", req.GetFInt64())) } if req != nil && req.IntendedBindingUri != nil { params.Add("intendedBindingUri", fmt.Sprintf("%v", req.GetIntendedBindingUri())) } if req.GetName() != "" { params.Add("name", fmt.Sprintf("%v", req.GetName())) } if req != nil && req.PDouble != nil { params.Add("pDouble", fmt.Sprintf("%v", req.GetPDouble())) } if req != nil && req.PInt32 != nil { params.Add("pInt32", fmt.Sprintf("%v", req.GetPInt32())) } if req != nil && req.PInt64 != nil { params.Add("pInt64", fmt.Sprintf("%v", req.GetPInt64())) } if req.GetServerVerify() { params.Add("serverVerify", fmt.Sprintf("%v", req.GetServerVerify())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).RepeatDataBodyInfo[0:len((*c.CallOptions).RepeatDataBodyInfo):len((*c.CallOptions).RepeatDataBodyInfo)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.RepeatResponse{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "RepeatDataBodyInfo") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // RepeatDataQuery this method echoes the ComplianceData request. This method exercises // sending all request fields as query parameters. func (c *complianceRESTClient) RepeatDataQuery(ctx context.Context, req *genprotopb.RepeatRequest, opts ...gax.CallOption) (*genprotopb.RepeatResponse, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/repeat:query") params := url.Values{} if req.GetFDouble() != 0 { params.Add("fDouble", fmt.Sprintf("%v", req.GetFDouble())) } if req.GetFInt32() != 0 { params.Add("fInt32", fmt.Sprintf("%v", req.GetFInt32())) } if req.GetFInt64() != 0 { params.Add("fInt64", fmt.Sprintf("%v", req.GetFInt64())) } if req.GetInfo().GetFBool() { params.Add("info.fBool", fmt.Sprintf("%v", req.GetInfo().GetFBool())) } if req.GetInfo().GetFBytes() != nil { params.Add("info.fBytes", fmt.Sprintf("%v", req.GetInfo().GetFBytes())) } if req.GetInfo().GetFChild().GetFBool() { params.Add("info.fChild.fBool", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFBool())) } if req.GetInfo().GetFChild().GetFChild().GetFBool() { params.Add("info.fChild.fChild.fBool", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFChild().GetFBool())) } if req.GetInfo().GetFChild().GetFChild().GetFDouble() != 0 { params.Add("info.fChild.fChild.fDouble", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFChild().GetFDouble())) } if req.GetInfo().GetFChild().GetFChild().GetFString() != "" { params.Add("info.fChild.fChild.fString", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFChild().GetFString())) } if req.GetInfo().GetFChild().GetFContinent() != 0 { params.Add("info.fChild.fContinent", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFContinent())) } if req.GetInfo().GetFChild().GetFDouble() != 0 { params.Add("info.fChild.fDouble", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFDouble())) } if req.GetInfo().GetFChild().GetFFloat() != 0 { params.Add("info.fChild.fFloat", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFFloat())) } if req.GetInfo().GetFChild().GetFString() != "" { params.Add("info.fChild.fString", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFString())) } if req.GetInfo().GetFChild() != nil && req.GetInfo().GetFChild().PBool != nil { params.Add("info.fChild.pBool", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPBool())) } if req.GetInfo().GetFChild().GetPChild().GetFBool() { params.Add("info.fChild.pChild.fBool", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPChild().GetFBool())) } if req.GetInfo().GetFChild().GetPChild().GetFDouble() != 0 { params.Add("info.fChild.pChild.fDouble", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPChild().GetFDouble())) } if req.GetInfo().GetFChild().GetPChild().GetFString() != "" { params.Add("info.fChild.pChild.fString", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPChild().GetFString())) } if req.GetInfo().GetFChild().GetPContinent() != 0 { params.Add("info.fChild.pContinent", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPContinent())) } if req.GetInfo().GetFChild() != nil && req.GetInfo().GetFChild().PDouble != nil { params.Add("info.fChild.pDouble", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPDouble())) } if req.GetInfo().GetFChild() != nil && req.GetInfo().GetFChild().PFloat != nil { params.Add("info.fChild.pFloat", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPFloat())) } if req.GetInfo().GetFChild() != nil && req.GetInfo().GetFChild().PString != nil { params.Add("info.fChild.pString", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPString())) } if req.GetInfo().GetFDouble() != 0 { params.Add("info.fDouble", fmt.Sprintf("%v", req.GetInfo().GetFDouble())) } if req.GetInfo().GetFFixed32() != 0 { params.Add("info.fFixed32", fmt.Sprintf("%v", req.GetInfo().GetFFixed32())) } if req.GetInfo().GetFFixed64() != 0 { params.Add("info.fFixed64", fmt.Sprintf("%v", req.GetInfo().GetFFixed64())) } if req.GetInfo().GetFFloat() != 0 { params.Add("info.fFloat", fmt.Sprintf("%v", req.GetInfo().GetFFloat())) } if req.GetInfo().GetFInt32() != 0 { params.Add("info.fInt32", fmt.Sprintf("%v", req.GetInfo().GetFInt32())) } if req.GetInfo().GetFInt64() != 0 { params.Add("info.fInt64", fmt.Sprintf("%v", req.GetInfo().GetFInt64())) } if req.GetInfo().GetFKingdom() != 0 { params.Add("info.fKingdom", fmt.Sprintf("%v", req.GetInfo().GetFKingdom())) } if req.GetInfo().GetFSfixed32() != 0 { params.Add("info.fSfixed32", fmt.Sprintf("%v", req.GetInfo().GetFSfixed32())) } if req.GetInfo().GetFSfixed64() != 0 { params.Add("info.fSfixed64", fmt.Sprintf("%v", req.GetInfo().GetFSfixed64())) } if req.GetInfo().GetFSint32() != 0 { params.Add("info.fSint32", fmt.Sprintf("%v", req.GetInfo().GetFSint32())) } if req.GetInfo().GetFSint64() != 0 { params.Add("info.fSint64", fmt.Sprintf("%v", req.GetInfo().GetFSint64())) } if req.GetInfo().GetFString() != "" { params.Add("info.fString", fmt.Sprintf("%v", req.GetInfo().GetFString())) } if req.GetInfo().GetFUint32() != 0 { params.Add("info.fUint32", fmt.Sprintf("%v", req.GetInfo().GetFUint32())) } if req.GetInfo().GetFUint64() != 0 { params.Add("info.fUint64", fmt.Sprintf("%v", req.GetInfo().GetFUint64())) } if req.GetInfo() != nil && req.GetInfo().PBool != nil { params.Add("info.pBool", fmt.Sprintf("%v", req.GetInfo().GetPBool())) } if req.GetInfo().GetPChild().GetFBool() { params.Add("info.pChild.fBool", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFBool())) } if req.GetInfo().GetPChild().GetFChild().GetFBool() { params.Add("info.pChild.fChild.fBool", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFChild().GetFBool())) } if req.GetInfo().GetPChild().GetFChild().GetFDouble() != 0 { params.Add("info.pChild.fChild.fDouble", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFChild().GetFDouble())) } if req.GetInfo().GetPChild().GetFChild().GetFString() != "" { params.Add("info.pChild.fChild.fString", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFChild().GetFString())) } if req.GetInfo().GetPChild().GetFContinent() != 0 { params.Add("info.pChild.fContinent", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFContinent())) } if req.GetInfo().GetPChild().GetFDouble() != 0 { params.Add("info.pChild.fDouble", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFDouble())) } if req.GetInfo().GetPChild().GetFFloat() != 0 { params.Add("info.pChild.fFloat", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFFloat())) } if req.GetInfo().GetPChild().GetFString() != "" { params.Add("info.pChild.fString", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFString())) } if req.GetInfo().GetPChild() != nil && req.GetInfo().GetPChild().PBool != nil { params.Add("info.pChild.pBool", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPBool())) } if req.GetInfo().GetPChild().GetPChild().GetFBool() { params.Add("info.pChild.pChild.fBool", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPChild().GetFBool())) } if req.GetInfo().GetPChild().GetPChild().GetFDouble() != 0 { params.Add("info.pChild.pChild.fDouble", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPChild().GetFDouble())) } if req.GetInfo().GetPChild().GetPChild().GetFString() != "" { params.Add("info.pChild.pChild.fString", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPChild().GetFString())) } if req.GetInfo().GetPChild().GetPContinent() != 0 { params.Add("info.pChild.pContinent", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPContinent())) } if req.GetInfo().GetPChild() != nil && req.GetInfo().GetPChild().PDouble != nil { params.Add("info.pChild.pDouble", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPDouble())) } if req.GetInfo().GetPChild() != nil && req.GetInfo().GetPChild().PFloat != nil { params.Add("info.pChild.pFloat", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPFloat())) } if req.GetInfo().GetPChild() != nil && req.GetInfo().GetPChild().PString != nil { params.Add("info.pChild.pString", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPString())) } if req.GetInfo() != nil && req.GetInfo().PDouble != nil { params.Add("info.pDouble", fmt.Sprintf("%v", req.GetInfo().GetPDouble())) } if req.GetInfo() != nil && req.GetInfo().PFixed32 != nil { params.Add("info.pFixed32", fmt.Sprintf("%v", req.GetInfo().GetPFixed32())) } if req.GetInfo() != nil && req.GetInfo().PFixed64 != nil { params.Add("info.pFixed64", fmt.Sprintf("%v", req.GetInfo().GetPFixed64())) } if req.GetInfo() != nil && req.GetInfo().PFloat != nil { params.Add("info.pFloat", fmt.Sprintf("%v", req.GetInfo().GetPFloat())) } if req.GetInfo() != nil && req.GetInfo().PInt32 != nil { params.Add("info.pInt32", fmt.Sprintf("%v", req.GetInfo().GetPInt32())) } if req.GetInfo() != nil && req.GetInfo().PInt64 != nil { params.Add("info.pInt64", fmt.Sprintf("%v", req.GetInfo().GetPInt64())) } if req.GetInfo() != nil && req.GetInfo().PKingdom != nil { params.Add("info.pKingdom", fmt.Sprintf("%v", req.GetInfo().GetPKingdom())) } if req.GetInfo() != nil && req.GetInfo().PSfixed32 != nil { params.Add("info.pSfixed32", fmt.Sprintf("%v", req.GetInfo().GetPSfixed32())) } if req.GetInfo() != nil && req.GetInfo().PSfixed64 != nil { params.Add("info.pSfixed64", fmt.Sprintf("%v", req.GetInfo().GetPSfixed64())) } if req.GetInfo() != nil && req.GetInfo().PSint32 != nil { params.Add("info.pSint32", fmt.Sprintf("%v", req.GetInfo().GetPSint32())) } if req.GetInfo() != nil && req.GetInfo().PSint64 != nil { params.Add("info.pSint64", fmt.Sprintf("%v", req.GetInfo().GetPSint64())) } if req.GetInfo() != nil && req.GetInfo().PString != nil { params.Add("info.pString", fmt.Sprintf("%v", req.GetInfo().GetPString())) } if req.GetInfo() != nil && req.GetInfo().PUint32 != nil { params.Add("info.pUint32", fmt.Sprintf("%v", req.GetInfo().GetPUint32())) } if req.GetInfo() != nil && req.GetInfo().PUint64 != nil { params.Add("info.pUint64", fmt.Sprintf("%v", req.GetInfo().GetPUint64())) } if req != nil && req.IntendedBindingUri != nil { params.Add("intendedBindingUri", fmt.Sprintf("%v", req.GetIntendedBindingUri())) } if req.GetName() != "" { params.Add("name", fmt.Sprintf("%v", req.GetName())) } if req != nil && req.PDouble != nil { params.Add("pDouble", fmt.Sprintf("%v", req.GetPDouble())) } if req != nil && req.PInt32 != nil { params.Add("pInt32", fmt.Sprintf("%v", req.GetPInt32())) } if req != nil && req.PInt64 != nil { params.Add("pInt64", fmt.Sprintf("%v", req.GetPInt64())) } if req.GetServerVerify() { params.Add("serverVerify", fmt.Sprintf("%v", req.GetServerVerify())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).RepeatDataQuery[0:len((*c.CallOptions).RepeatDataQuery):len((*c.CallOptions).RepeatDataQuery)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.RepeatResponse{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "RepeatDataQuery") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // RepeatDataSimplePath this method echoes the ComplianceData request. This method exercises // sending some parameters as “simple” path variables (i.e., of the form // “/bar/{foo}” rather than “/{foo=bar/*}”), and the rest as query parameters. func (c *complianceRESTClient) RepeatDataSimplePath(ctx context.Context, req *genprotopb.RepeatRequest, opts ...gax.CallOption) (*genprotopb.RepeatResponse, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/repeat/%v/%v/%v/%v/%v:simplepath", req.GetInfo().GetFString(), req.GetInfo().GetFInt32(), req.GetInfo().GetFDouble(), req.GetInfo().GetFBool(), req.GetInfo().GetFKingdom()) params := url.Values{} if req.GetFDouble() != 0 { params.Add("fDouble", fmt.Sprintf("%v", req.GetFDouble())) } if req.GetFInt32() != 0 { params.Add("fInt32", fmt.Sprintf("%v", req.GetFInt32())) } if req.GetFInt64() != 0 { params.Add("fInt64", fmt.Sprintf("%v", req.GetFInt64())) } if req.GetInfo().GetFBytes() != nil { params.Add("info.fBytes", fmt.Sprintf("%v", req.GetInfo().GetFBytes())) } if req.GetInfo().GetFChild().GetFBool() { params.Add("info.fChild.fBool", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFBool())) } if req.GetInfo().GetFChild().GetFChild().GetFBool() { params.Add("info.fChild.fChild.fBool", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFChild().GetFBool())) } if req.GetInfo().GetFChild().GetFChild().GetFDouble() != 0 { params.Add("info.fChild.fChild.fDouble", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFChild().GetFDouble())) } if req.GetInfo().GetFChild().GetFChild().GetFString() != "" { params.Add("info.fChild.fChild.fString", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFChild().GetFString())) } if req.GetInfo().GetFChild().GetFContinent() != 0 { params.Add("info.fChild.fContinent", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFContinent())) } if req.GetInfo().GetFChild().GetFDouble() != 0 { params.Add("info.fChild.fDouble", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFDouble())) } if req.GetInfo().GetFChild().GetFFloat() != 0 { params.Add("info.fChild.fFloat", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFFloat())) } if req.GetInfo().GetFChild().GetFString() != "" { params.Add("info.fChild.fString", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFString())) } if req.GetInfo().GetFChild() != nil && req.GetInfo().GetFChild().PBool != nil { params.Add("info.fChild.pBool", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPBool())) } if req.GetInfo().GetFChild().GetPChild().GetFBool() { params.Add("info.fChild.pChild.fBool", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPChild().GetFBool())) } if req.GetInfo().GetFChild().GetPChild().GetFDouble() != 0 { params.Add("info.fChild.pChild.fDouble", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPChild().GetFDouble())) } if req.GetInfo().GetFChild().GetPChild().GetFString() != "" { params.Add("info.fChild.pChild.fString", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPChild().GetFString())) } if req.GetInfo().GetFChild().GetPContinent() != 0 { params.Add("info.fChild.pContinent", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPContinent())) } if req.GetInfo().GetFChild() != nil && req.GetInfo().GetFChild().PDouble != nil { params.Add("info.fChild.pDouble", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPDouble())) } if req.GetInfo().GetFChild() != nil && req.GetInfo().GetFChild().PFloat != nil { params.Add("info.fChild.pFloat", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPFloat())) } if req.GetInfo().GetFChild() != nil && req.GetInfo().GetFChild().PString != nil { params.Add("info.fChild.pString", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPString())) } if req.GetInfo().GetFFixed32() != 0 { params.Add("info.fFixed32", fmt.Sprintf("%v", req.GetInfo().GetFFixed32())) } if req.GetInfo().GetFFixed64() != 0 { params.Add("info.fFixed64", fmt.Sprintf("%v", req.GetInfo().GetFFixed64())) } if req.GetInfo().GetFFloat() != 0 { params.Add("info.fFloat", fmt.Sprintf("%v", req.GetInfo().GetFFloat())) } if req.GetInfo().GetFInt64() != 0 { params.Add("info.fInt64", fmt.Sprintf("%v", req.GetInfo().GetFInt64())) } if req.GetInfo().GetFSfixed32() != 0 { params.Add("info.fSfixed32", fmt.Sprintf("%v", req.GetInfo().GetFSfixed32())) } if req.GetInfo().GetFSfixed64() != 0 { params.Add("info.fSfixed64", fmt.Sprintf("%v", req.GetInfo().GetFSfixed64())) } if req.GetInfo().GetFSint32() != 0 { params.Add("info.fSint32", fmt.Sprintf("%v", req.GetInfo().GetFSint32())) } if req.GetInfo().GetFSint64() != 0 { params.Add("info.fSint64", fmt.Sprintf("%v", req.GetInfo().GetFSint64())) } if req.GetInfo().GetFUint32() != 0 { params.Add("info.fUint32", fmt.Sprintf("%v", req.GetInfo().GetFUint32())) } if req.GetInfo().GetFUint64() != 0 { params.Add("info.fUint64", fmt.Sprintf("%v", req.GetInfo().GetFUint64())) } if req.GetInfo() != nil && req.GetInfo().PBool != nil { params.Add("info.pBool", fmt.Sprintf("%v", req.GetInfo().GetPBool())) } if req.GetInfo().GetPChild().GetFBool() { params.Add("info.pChild.fBool", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFBool())) } if req.GetInfo().GetPChild().GetFChild().GetFBool() { params.Add("info.pChild.fChild.fBool", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFChild().GetFBool())) } if req.GetInfo().GetPChild().GetFChild().GetFDouble() != 0 { params.Add("info.pChild.fChild.fDouble", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFChild().GetFDouble())) } if req.GetInfo().GetPChild().GetFChild().GetFString() != "" { params.Add("info.pChild.fChild.fString", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFChild().GetFString())) } if req.GetInfo().GetPChild().GetFContinent() != 0 { params.Add("info.pChild.fContinent", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFContinent())) } if req.GetInfo().GetPChild().GetFDouble() != 0 { params.Add("info.pChild.fDouble", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFDouble())) } if req.GetInfo().GetPChild().GetFFloat() != 0 { params.Add("info.pChild.fFloat", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFFloat())) } if req.GetInfo().GetPChild().GetFString() != "" { params.Add("info.pChild.fString", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFString())) } if req.GetInfo().GetPChild() != nil && req.GetInfo().GetPChild().PBool != nil { params.Add("info.pChild.pBool", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPBool())) } if req.GetInfo().GetPChild().GetPChild().GetFBool() { params.Add("info.pChild.pChild.fBool", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPChild().GetFBool())) } if req.GetInfo().GetPChild().GetPChild().GetFDouble() != 0 { params.Add("info.pChild.pChild.fDouble", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPChild().GetFDouble())) } if req.GetInfo().GetPChild().GetPChild().GetFString() != "" { params.Add("info.pChild.pChild.fString", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPChild().GetFString())) } if req.GetInfo().GetPChild().GetPContinent() != 0 { params.Add("info.pChild.pContinent", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPContinent())) } if req.GetInfo().GetPChild() != nil && req.GetInfo().GetPChild().PDouble != nil { params.Add("info.pChild.pDouble", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPDouble())) } if req.GetInfo().GetPChild() != nil && req.GetInfo().GetPChild().PFloat != nil { params.Add("info.pChild.pFloat", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPFloat())) } if req.GetInfo().GetPChild() != nil && req.GetInfo().GetPChild().PString != nil { params.Add("info.pChild.pString", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPString())) } if req.GetInfo() != nil && req.GetInfo().PDouble != nil { params.Add("info.pDouble", fmt.Sprintf("%v", req.GetInfo().GetPDouble())) } if req.GetInfo() != nil && req.GetInfo().PFixed32 != nil { params.Add("info.pFixed32", fmt.Sprintf("%v", req.GetInfo().GetPFixed32())) } if req.GetInfo() != nil && req.GetInfo().PFixed64 != nil { params.Add("info.pFixed64", fmt.Sprintf("%v", req.GetInfo().GetPFixed64())) } if req.GetInfo() != nil && req.GetInfo().PFloat != nil { params.Add("info.pFloat", fmt.Sprintf("%v", req.GetInfo().GetPFloat())) } if req.GetInfo() != nil && req.GetInfo().PInt32 != nil { params.Add("info.pInt32", fmt.Sprintf("%v", req.GetInfo().GetPInt32())) } if req.GetInfo() != nil && req.GetInfo().PInt64 != nil { params.Add("info.pInt64", fmt.Sprintf("%v", req.GetInfo().GetPInt64())) } if req.GetInfo() != nil && req.GetInfo().PKingdom != nil { params.Add("info.pKingdom", fmt.Sprintf("%v", req.GetInfo().GetPKingdom())) } if req.GetInfo() != nil && req.GetInfo().PSfixed32 != nil { params.Add("info.pSfixed32", fmt.Sprintf("%v", req.GetInfo().GetPSfixed32())) } if req.GetInfo() != nil && req.GetInfo().PSfixed64 != nil { params.Add("info.pSfixed64", fmt.Sprintf("%v", req.GetInfo().GetPSfixed64())) } if req.GetInfo() != nil && req.GetInfo().PSint32 != nil { params.Add("info.pSint32", fmt.Sprintf("%v", req.GetInfo().GetPSint32())) } if req.GetInfo() != nil && req.GetInfo().PSint64 != nil { params.Add("info.pSint64", fmt.Sprintf("%v", req.GetInfo().GetPSint64())) } if req.GetInfo() != nil && req.GetInfo().PString != nil { params.Add("info.pString", fmt.Sprintf("%v", req.GetInfo().GetPString())) } if req.GetInfo() != nil && req.GetInfo().PUint32 != nil { params.Add("info.pUint32", fmt.Sprintf("%v", req.GetInfo().GetPUint32())) } if req.GetInfo() != nil && req.GetInfo().PUint64 != nil { params.Add("info.pUint64", fmt.Sprintf("%v", req.GetInfo().GetPUint64())) } if req != nil && req.IntendedBindingUri != nil { params.Add("intendedBindingUri", fmt.Sprintf("%v", req.GetIntendedBindingUri())) } if req.GetName() != "" { params.Add("name", fmt.Sprintf("%v", req.GetName())) } if req != nil && req.PDouble != nil { params.Add("pDouble", fmt.Sprintf("%v", req.GetPDouble())) } if req != nil && req.PInt32 != nil { params.Add("pInt32", fmt.Sprintf("%v", req.GetPInt32())) } if req != nil && req.PInt64 != nil { params.Add("pInt64", fmt.Sprintf("%v", req.GetPInt64())) } if req.GetServerVerify() { params.Add("serverVerify", fmt.Sprintf("%v", req.GetServerVerify())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v&%s=%v&%s=%v&%s=%v&%s=%v", "info.f_string", url.QueryEscape(req.GetInfo().GetFString()), "info.f_int32", req.GetInfo().GetFInt32(), "info.f_double", url.QueryEscape(fmt.Sprintf("%g", req.GetInfo().GetFDouble())), "info.f_bool", req.GetInfo().GetFBool(), "info.f_kingdom", genprotopb.ComplianceData_LifeKingdom_name[int32(req.GetInfo().GetFKingdom())])} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).RepeatDataSimplePath[0:len((*c.CallOptions).RepeatDataSimplePath):len((*c.CallOptions).RepeatDataSimplePath)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.RepeatResponse{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "RepeatDataSimplePath") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // RepeatDataPathResource same as RepeatDataSimplePath, but with a path resource. func (c *complianceRESTClient) RepeatDataPathResource(ctx context.Context, req *genprotopb.RepeatRequest, opts ...gax.CallOption) (*genprotopb.RepeatResponse, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/repeat/%v/%v/bool/%v:pathresource", req.GetInfo().GetFString(), req.GetInfo().GetFChild().GetFString(), req.GetInfo().GetFBool()) params := url.Values{} if req.GetFDouble() != 0 { params.Add("fDouble", fmt.Sprintf("%v", req.GetFDouble())) } if req.GetFInt32() != 0 { params.Add("fInt32", fmt.Sprintf("%v", req.GetFInt32())) } if req.GetFInt64() != 0 { params.Add("fInt64", fmt.Sprintf("%v", req.GetFInt64())) } if req.GetInfo().GetFBytes() != nil { params.Add("info.fBytes", fmt.Sprintf("%v", req.GetInfo().GetFBytes())) } if req.GetInfo().GetFChild().GetFBool() { params.Add("info.fChild.fBool", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFBool())) } if req.GetInfo().GetFChild().GetFChild().GetFBool() { params.Add("info.fChild.fChild.fBool", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFChild().GetFBool())) } if req.GetInfo().GetFChild().GetFChild().GetFDouble() != 0 { params.Add("info.fChild.fChild.fDouble", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFChild().GetFDouble())) } if req.GetInfo().GetFChild().GetFChild().GetFString() != "" { params.Add("info.fChild.fChild.fString", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFChild().GetFString())) } if req.GetInfo().GetFChild().GetFContinent() != 0 { params.Add("info.fChild.fContinent", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFContinent())) } if req.GetInfo().GetFChild().GetFDouble() != 0 { params.Add("info.fChild.fDouble", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFDouble())) } if req.GetInfo().GetFChild().GetFFloat() != 0 { params.Add("info.fChild.fFloat", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFFloat())) } if req.GetInfo().GetFChild() != nil && req.GetInfo().GetFChild().PBool != nil { params.Add("info.fChild.pBool", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPBool())) } if req.GetInfo().GetFChild().GetPChild().GetFBool() { params.Add("info.fChild.pChild.fBool", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPChild().GetFBool())) } if req.GetInfo().GetFChild().GetPChild().GetFDouble() != 0 { params.Add("info.fChild.pChild.fDouble", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPChild().GetFDouble())) } if req.GetInfo().GetFChild().GetPChild().GetFString() != "" { params.Add("info.fChild.pChild.fString", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPChild().GetFString())) } if req.GetInfo().GetFChild().GetPContinent() != 0 { params.Add("info.fChild.pContinent", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPContinent())) } if req.GetInfo().GetFChild() != nil && req.GetInfo().GetFChild().PDouble != nil { params.Add("info.fChild.pDouble", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPDouble())) } if req.GetInfo().GetFChild() != nil && req.GetInfo().GetFChild().PFloat != nil { params.Add("info.fChild.pFloat", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPFloat())) } if req.GetInfo().GetFChild() != nil && req.GetInfo().GetFChild().PString != nil { params.Add("info.fChild.pString", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPString())) } if req.GetInfo().GetFDouble() != 0 { params.Add("info.fDouble", fmt.Sprintf("%v", req.GetInfo().GetFDouble())) } if req.GetInfo().GetFFixed32() != 0 { params.Add("info.fFixed32", fmt.Sprintf("%v", req.GetInfo().GetFFixed32())) } if req.GetInfo().GetFFixed64() != 0 { params.Add("info.fFixed64", fmt.Sprintf("%v", req.GetInfo().GetFFixed64())) } if req.GetInfo().GetFFloat() != 0 { params.Add("info.fFloat", fmt.Sprintf("%v", req.GetInfo().GetFFloat())) } if req.GetInfo().GetFInt32() != 0 { params.Add("info.fInt32", fmt.Sprintf("%v", req.GetInfo().GetFInt32())) } if req.GetInfo().GetFInt64() != 0 { params.Add("info.fInt64", fmt.Sprintf("%v", req.GetInfo().GetFInt64())) } if req.GetInfo().GetFKingdom() != 0 { params.Add("info.fKingdom", fmt.Sprintf("%v", req.GetInfo().GetFKingdom())) } if req.GetInfo().GetFSfixed32() != 0 { params.Add("info.fSfixed32", fmt.Sprintf("%v", req.GetInfo().GetFSfixed32())) } if req.GetInfo().GetFSfixed64() != 0 { params.Add("info.fSfixed64", fmt.Sprintf("%v", req.GetInfo().GetFSfixed64())) } if req.GetInfo().GetFSint32() != 0 { params.Add("info.fSint32", fmt.Sprintf("%v", req.GetInfo().GetFSint32())) } if req.GetInfo().GetFSint64() != 0 { params.Add("info.fSint64", fmt.Sprintf("%v", req.GetInfo().GetFSint64())) } if req.GetInfo().GetFUint32() != 0 { params.Add("info.fUint32", fmt.Sprintf("%v", req.GetInfo().GetFUint32())) } if req.GetInfo().GetFUint64() != 0 { params.Add("info.fUint64", fmt.Sprintf("%v", req.GetInfo().GetFUint64())) } if req.GetInfo() != nil && req.GetInfo().PBool != nil { params.Add("info.pBool", fmt.Sprintf("%v", req.GetInfo().GetPBool())) } if req.GetInfo().GetPChild().GetFBool() { params.Add("info.pChild.fBool", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFBool())) } if req.GetInfo().GetPChild().GetFChild().GetFBool() { params.Add("info.pChild.fChild.fBool", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFChild().GetFBool())) } if req.GetInfo().GetPChild().GetFChild().GetFDouble() != 0 { params.Add("info.pChild.fChild.fDouble", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFChild().GetFDouble())) } if req.GetInfo().GetPChild().GetFChild().GetFString() != "" { params.Add("info.pChild.fChild.fString", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFChild().GetFString())) } if req.GetInfo().GetPChild().GetFContinent() != 0 { params.Add("info.pChild.fContinent", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFContinent())) } if req.GetInfo().GetPChild().GetFDouble() != 0 { params.Add("info.pChild.fDouble", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFDouble())) } if req.GetInfo().GetPChild().GetFFloat() != 0 { params.Add("info.pChild.fFloat", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFFloat())) } if req.GetInfo().GetPChild().GetFString() != "" { params.Add("info.pChild.fString", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFString())) } if req.GetInfo().GetPChild() != nil && req.GetInfo().GetPChild().PBool != nil { params.Add("info.pChild.pBool", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPBool())) } if req.GetInfo().GetPChild().GetPChild().GetFBool() { params.Add("info.pChild.pChild.fBool", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPChild().GetFBool())) } if req.GetInfo().GetPChild().GetPChild().GetFDouble() != 0 { params.Add("info.pChild.pChild.fDouble", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPChild().GetFDouble())) } if req.GetInfo().GetPChild().GetPChild().GetFString() != "" { params.Add("info.pChild.pChild.fString", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPChild().GetFString())) } if req.GetInfo().GetPChild().GetPContinent() != 0 { params.Add("info.pChild.pContinent", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPContinent())) } if req.GetInfo().GetPChild() != nil && req.GetInfo().GetPChild().PDouble != nil { params.Add("info.pChild.pDouble", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPDouble())) } if req.GetInfo().GetPChild() != nil && req.GetInfo().GetPChild().PFloat != nil { params.Add("info.pChild.pFloat", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPFloat())) } if req.GetInfo().GetPChild() != nil && req.GetInfo().GetPChild().PString != nil { params.Add("info.pChild.pString", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPString())) } if req.GetInfo() != nil && req.GetInfo().PDouble != nil { params.Add("info.pDouble", fmt.Sprintf("%v", req.GetInfo().GetPDouble())) } if req.GetInfo() != nil && req.GetInfo().PFixed32 != nil { params.Add("info.pFixed32", fmt.Sprintf("%v", req.GetInfo().GetPFixed32())) } if req.GetInfo() != nil && req.GetInfo().PFixed64 != nil { params.Add("info.pFixed64", fmt.Sprintf("%v", req.GetInfo().GetPFixed64())) } if req.GetInfo() != nil && req.GetInfo().PFloat != nil { params.Add("info.pFloat", fmt.Sprintf("%v", req.GetInfo().GetPFloat())) } if req.GetInfo() != nil && req.GetInfo().PInt32 != nil { params.Add("info.pInt32", fmt.Sprintf("%v", req.GetInfo().GetPInt32())) } if req.GetInfo() != nil && req.GetInfo().PInt64 != nil { params.Add("info.pInt64", fmt.Sprintf("%v", req.GetInfo().GetPInt64())) } if req.GetInfo() != nil && req.GetInfo().PKingdom != nil { params.Add("info.pKingdom", fmt.Sprintf("%v", req.GetInfo().GetPKingdom())) } if req.GetInfo() != nil && req.GetInfo().PSfixed32 != nil { params.Add("info.pSfixed32", fmt.Sprintf("%v", req.GetInfo().GetPSfixed32())) } if req.GetInfo() != nil && req.GetInfo().PSfixed64 != nil { params.Add("info.pSfixed64", fmt.Sprintf("%v", req.GetInfo().GetPSfixed64())) } if req.GetInfo() != nil && req.GetInfo().PSint32 != nil { params.Add("info.pSint32", fmt.Sprintf("%v", req.GetInfo().GetPSint32())) } if req.GetInfo() != nil && req.GetInfo().PSint64 != nil { params.Add("info.pSint64", fmt.Sprintf("%v", req.GetInfo().GetPSint64())) } if req.GetInfo() != nil && req.GetInfo().PString != nil { params.Add("info.pString", fmt.Sprintf("%v", req.GetInfo().GetPString())) } if req.GetInfo() != nil && req.GetInfo().PUint32 != nil { params.Add("info.pUint32", fmt.Sprintf("%v", req.GetInfo().GetPUint32())) } if req.GetInfo() != nil && req.GetInfo().PUint64 != nil { params.Add("info.pUint64", fmt.Sprintf("%v", req.GetInfo().GetPUint64())) } if req != nil && req.IntendedBindingUri != nil { params.Add("intendedBindingUri", fmt.Sprintf("%v", req.GetIntendedBindingUri())) } if req.GetName() != "" { params.Add("name", fmt.Sprintf("%v", req.GetName())) } if req != nil && req.PDouble != nil { params.Add("pDouble", fmt.Sprintf("%v", req.GetPDouble())) } if req != nil && req.PInt32 != nil { params.Add("pInt32", fmt.Sprintf("%v", req.GetPInt32())) } if req != nil && req.PInt64 != nil { params.Add("pInt64", fmt.Sprintf("%v", req.GetPInt64())) } if req.GetServerVerify() { params.Add("serverVerify", fmt.Sprintf("%v", req.GetServerVerify())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v&%s=%v&%s=%v", "info.f_string", url.QueryEscape(req.GetInfo().GetFString()), "info.f_child.f_string", url.QueryEscape(req.GetInfo().GetFChild().GetFString()), "info.f_bool", req.GetInfo().GetFBool())} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).RepeatDataPathResource[0:len((*c.CallOptions).RepeatDataPathResource):len((*c.CallOptions).RepeatDataPathResource)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.RepeatResponse{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "RepeatDataPathResource") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // RepeatDataPathTrailingResource same as RepeatDataSimplePath, but with a trailing resource. func (c *complianceRESTClient) RepeatDataPathTrailingResource(ctx context.Context, req *genprotopb.RepeatRequest, opts ...gax.CallOption) (*genprotopb.RepeatResponse, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/repeat/%v/%v:pathtrailingresource", req.GetInfo().GetFString(), req.GetInfo().GetFChild().GetFString()) params := url.Values{} if req.GetFDouble() != 0 { params.Add("fDouble", fmt.Sprintf("%v", req.GetFDouble())) } if req.GetFInt32() != 0 { params.Add("fInt32", fmt.Sprintf("%v", req.GetFInt32())) } if req.GetFInt64() != 0 { params.Add("fInt64", fmt.Sprintf("%v", req.GetFInt64())) } if req.GetInfo().GetFBool() { params.Add("info.fBool", fmt.Sprintf("%v", req.GetInfo().GetFBool())) } if req.GetInfo().GetFBytes() != nil { params.Add("info.fBytes", fmt.Sprintf("%v", req.GetInfo().GetFBytes())) } if req.GetInfo().GetFChild().GetFBool() { params.Add("info.fChild.fBool", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFBool())) } if req.GetInfo().GetFChild().GetFChild().GetFBool() { params.Add("info.fChild.fChild.fBool", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFChild().GetFBool())) } if req.GetInfo().GetFChild().GetFChild().GetFDouble() != 0 { params.Add("info.fChild.fChild.fDouble", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFChild().GetFDouble())) } if req.GetInfo().GetFChild().GetFChild().GetFString() != "" { params.Add("info.fChild.fChild.fString", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFChild().GetFString())) } if req.GetInfo().GetFChild().GetFContinent() != 0 { params.Add("info.fChild.fContinent", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFContinent())) } if req.GetInfo().GetFChild().GetFDouble() != 0 { params.Add("info.fChild.fDouble", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFDouble())) } if req.GetInfo().GetFChild().GetFFloat() != 0 { params.Add("info.fChild.fFloat", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetFFloat())) } if req.GetInfo().GetFChild() != nil && req.GetInfo().GetFChild().PBool != nil { params.Add("info.fChild.pBool", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPBool())) } if req.GetInfo().GetFChild().GetPChild().GetFBool() { params.Add("info.fChild.pChild.fBool", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPChild().GetFBool())) } if req.GetInfo().GetFChild().GetPChild().GetFDouble() != 0 { params.Add("info.fChild.pChild.fDouble", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPChild().GetFDouble())) } if req.GetInfo().GetFChild().GetPChild().GetFString() != "" { params.Add("info.fChild.pChild.fString", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPChild().GetFString())) } if req.GetInfo().GetFChild().GetPContinent() != 0 { params.Add("info.fChild.pContinent", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPContinent())) } if req.GetInfo().GetFChild() != nil && req.GetInfo().GetFChild().PDouble != nil { params.Add("info.fChild.pDouble", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPDouble())) } if req.GetInfo().GetFChild() != nil && req.GetInfo().GetFChild().PFloat != nil { params.Add("info.fChild.pFloat", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPFloat())) } if req.GetInfo().GetFChild() != nil && req.GetInfo().GetFChild().PString != nil { params.Add("info.fChild.pString", fmt.Sprintf("%v", req.GetInfo().GetFChild().GetPString())) } if req.GetInfo().GetFDouble() != 0 { params.Add("info.fDouble", fmt.Sprintf("%v", req.GetInfo().GetFDouble())) } if req.GetInfo().GetFFixed32() != 0 { params.Add("info.fFixed32", fmt.Sprintf("%v", req.GetInfo().GetFFixed32())) } if req.GetInfo().GetFFixed64() != 0 { params.Add("info.fFixed64", fmt.Sprintf("%v", req.GetInfo().GetFFixed64())) } if req.GetInfo().GetFFloat() != 0 { params.Add("info.fFloat", fmt.Sprintf("%v", req.GetInfo().GetFFloat())) } if req.GetInfo().GetFInt32() != 0 { params.Add("info.fInt32", fmt.Sprintf("%v", req.GetInfo().GetFInt32())) } if req.GetInfo().GetFInt64() != 0 { params.Add("info.fInt64", fmt.Sprintf("%v", req.GetInfo().GetFInt64())) } if req.GetInfo().GetFKingdom() != 0 { params.Add("info.fKingdom", fmt.Sprintf("%v", req.GetInfo().GetFKingdom())) } if req.GetInfo().GetFSfixed32() != 0 { params.Add("info.fSfixed32", fmt.Sprintf("%v", req.GetInfo().GetFSfixed32())) } if req.GetInfo().GetFSfixed64() != 0 { params.Add("info.fSfixed64", fmt.Sprintf("%v", req.GetInfo().GetFSfixed64())) } if req.GetInfo().GetFSint32() != 0 { params.Add("info.fSint32", fmt.Sprintf("%v", req.GetInfo().GetFSint32())) } if req.GetInfo().GetFSint64() != 0 { params.Add("info.fSint64", fmt.Sprintf("%v", req.GetInfo().GetFSint64())) } if req.GetInfo().GetFUint32() != 0 { params.Add("info.fUint32", fmt.Sprintf("%v", req.GetInfo().GetFUint32())) } if req.GetInfo().GetFUint64() != 0 { params.Add("info.fUint64", fmt.Sprintf("%v", req.GetInfo().GetFUint64())) } if req.GetInfo() != nil && req.GetInfo().PBool != nil { params.Add("info.pBool", fmt.Sprintf("%v", req.GetInfo().GetPBool())) } if req.GetInfo().GetPChild().GetFBool() { params.Add("info.pChild.fBool", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFBool())) } if req.GetInfo().GetPChild().GetFChild().GetFBool() { params.Add("info.pChild.fChild.fBool", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFChild().GetFBool())) } if req.GetInfo().GetPChild().GetFChild().GetFDouble() != 0 { params.Add("info.pChild.fChild.fDouble", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFChild().GetFDouble())) } if req.GetInfo().GetPChild().GetFChild().GetFString() != "" { params.Add("info.pChild.fChild.fString", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFChild().GetFString())) } if req.GetInfo().GetPChild().GetFContinent() != 0 { params.Add("info.pChild.fContinent", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFContinent())) } if req.GetInfo().GetPChild().GetFDouble() != 0 { params.Add("info.pChild.fDouble", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFDouble())) } if req.GetInfo().GetPChild().GetFFloat() != 0 { params.Add("info.pChild.fFloat", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFFloat())) } if req.GetInfo().GetPChild().GetFString() != "" { params.Add("info.pChild.fString", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetFString())) } if req.GetInfo().GetPChild() != nil && req.GetInfo().GetPChild().PBool != nil { params.Add("info.pChild.pBool", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPBool())) } if req.GetInfo().GetPChild().GetPChild().GetFBool() { params.Add("info.pChild.pChild.fBool", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPChild().GetFBool())) } if req.GetInfo().GetPChild().GetPChild().GetFDouble() != 0 { params.Add("info.pChild.pChild.fDouble", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPChild().GetFDouble())) } if req.GetInfo().GetPChild().GetPChild().GetFString() != "" { params.Add("info.pChild.pChild.fString", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPChild().GetFString())) } if req.GetInfo().GetPChild().GetPContinent() != 0 { params.Add("info.pChild.pContinent", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPContinent())) } if req.GetInfo().GetPChild() != nil && req.GetInfo().GetPChild().PDouble != nil { params.Add("info.pChild.pDouble", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPDouble())) } if req.GetInfo().GetPChild() != nil && req.GetInfo().GetPChild().PFloat != nil { params.Add("info.pChild.pFloat", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPFloat())) } if req.GetInfo().GetPChild() != nil && req.GetInfo().GetPChild().PString != nil { params.Add("info.pChild.pString", fmt.Sprintf("%v", req.GetInfo().GetPChild().GetPString())) } if req.GetInfo() != nil && req.GetInfo().PDouble != nil { params.Add("info.pDouble", fmt.Sprintf("%v", req.GetInfo().GetPDouble())) } if req.GetInfo() != nil && req.GetInfo().PFixed32 != nil { params.Add("info.pFixed32", fmt.Sprintf("%v", req.GetInfo().GetPFixed32())) } if req.GetInfo() != nil && req.GetInfo().PFixed64 != nil { params.Add("info.pFixed64", fmt.Sprintf("%v", req.GetInfo().GetPFixed64())) } if req.GetInfo() != nil && req.GetInfo().PFloat != nil { params.Add("info.pFloat", fmt.Sprintf("%v", req.GetInfo().GetPFloat())) } if req.GetInfo() != nil && req.GetInfo().PInt32 != nil { params.Add("info.pInt32", fmt.Sprintf("%v", req.GetInfo().GetPInt32())) } if req.GetInfo() != nil && req.GetInfo().PInt64 != nil { params.Add("info.pInt64", fmt.Sprintf("%v", req.GetInfo().GetPInt64())) } if req.GetInfo() != nil && req.GetInfo().PKingdom != nil { params.Add("info.pKingdom", fmt.Sprintf("%v", req.GetInfo().GetPKingdom())) } if req.GetInfo() != nil && req.GetInfo().PSfixed32 != nil { params.Add("info.pSfixed32", fmt.Sprintf("%v", req.GetInfo().GetPSfixed32())) } if req.GetInfo() != nil && req.GetInfo().PSfixed64 != nil { params.Add("info.pSfixed64", fmt.Sprintf("%v", req.GetInfo().GetPSfixed64())) } if req.GetInfo() != nil && req.GetInfo().PSint32 != nil { params.Add("info.pSint32", fmt.Sprintf("%v", req.GetInfo().GetPSint32())) } if req.GetInfo() != nil && req.GetInfo().PSint64 != nil { params.Add("info.pSint64", fmt.Sprintf("%v", req.GetInfo().GetPSint64())) } if req.GetInfo() != nil && req.GetInfo().PString != nil { params.Add("info.pString", fmt.Sprintf("%v", req.GetInfo().GetPString())) } if req.GetInfo() != nil && req.GetInfo().PUint32 != nil { params.Add("info.pUint32", fmt.Sprintf("%v", req.GetInfo().GetPUint32())) } if req.GetInfo() != nil && req.GetInfo().PUint64 != nil { params.Add("info.pUint64", fmt.Sprintf("%v", req.GetInfo().GetPUint64())) } if req != nil && req.IntendedBindingUri != nil { params.Add("intendedBindingUri", fmt.Sprintf("%v", req.GetIntendedBindingUri())) } if req.GetName() != "" { params.Add("name", fmt.Sprintf("%v", req.GetName())) } if req != nil && req.PDouble != nil { params.Add("pDouble", fmt.Sprintf("%v", req.GetPDouble())) } if req != nil && req.PInt32 != nil { params.Add("pInt32", fmt.Sprintf("%v", req.GetPInt32())) } if req != nil && req.PInt64 != nil { params.Add("pInt64", fmt.Sprintf("%v", req.GetPInt64())) } if req.GetServerVerify() { params.Add("serverVerify", fmt.Sprintf("%v", req.GetServerVerify())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v&%s=%v", "info.f_string", url.QueryEscape(req.GetInfo().GetFString()), "info.f_child.f_string", url.QueryEscape(req.GetInfo().GetFChild().GetFString()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).RepeatDataPathTrailingResource[0:len((*c.CallOptions).RepeatDataPathTrailingResource):len((*c.CallOptions).RepeatDataPathTrailingResource)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.RepeatResponse{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "RepeatDataPathTrailingResource") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // RepeatDataBodyPut this method echoes the ComplianceData request, using the HTTP PUT method. func (c *complianceRESTClient) RepeatDataBodyPut(ctx context.Context, req *genprotopb.RepeatRequest, opts ...gax.CallOption) (*genprotopb.RepeatResponse, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/repeat:bodyput") // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).RepeatDataBodyPut[0:len((*c.CallOptions).RepeatDataBodyPut):len((*c.CallOptions).RepeatDataBodyPut)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.RepeatResponse{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("PUT", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "RepeatDataBodyPut") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // RepeatDataBodyPatch this method echoes the ComplianceData request, using the HTTP PATCH method. func (c *complianceRESTClient) RepeatDataBodyPatch(ctx context.Context, req *genprotopb.RepeatRequest, opts ...gax.CallOption) (*genprotopb.RepeatResponse, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/repeat:bodypatch") // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).RepeatDataBodyPatch[0:len((*c.CallOptions).RepeatDataBodyPatch):len((*c.CallOptions).RepeatDataBodyPatch)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.RepeatResponse{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("PATCH", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "RepeatDataBodyPatch") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // GetEnum this method requests an enum value from the server. Depending on the contents of EnumRequest, the enum value returned will be a known enum declared in the // .proto file, or a made-up enum value the is unknown to the client. To verify that clients can round-trip unknown enum values they receive, use the // response from this RPC as the request to VerifyEnum() // // The values of enums sent by the server when a known or unknown value is requested will be the same within a single Showcase server run (this is needed for // VerifyEnum() to work) but are not guaranteed to be the same across separate Showcase server runs. func (c *complianceRESTClient) GetEnum(ctx context.Context, req *genprotopb.EnumRequest, opts ...gax.CallOption) (*genprotopb.EnumResponse, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/compliance/enum") params := url.Values{} if req.GetUnknownEnum() { params.Add("unknownEnum", fmt.Sprintf("%v", req.GetUnknownEnum())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).GetEnum[0:len((*c.CallOptions).GetEnum):len((*c.CallOptions).GetEnum)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.EnumResponse{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "GetEnum") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // VerifyEnum this method is used to verify that clients can round-trip enum values, which is particularly important for unknown enum values over REST. VerifyEnum() // verifies that its request, which is presumably the response that the client previously got to a GetEnum(), contains the correct data. If so, it responds // with the same EnumResponse; otherwise, the RPC errors. // // This works because the values of enums sent by the server when a known or unknown value is requested will be the same within a single Showcase server run, // although they are not guaranteed to be the same across separate Showcase server runs. func (c *complianceRESTClient) VerifyEnum(ctx context.Context, req *genprotopb.EnumResponse, opts ...gax.CallOption) (*genprotopb.EnumResponse, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/compliance/enum") params := url.Values{} if req.GetContinent() != 0 { params.Add("continent", fmt.Sprintf("%v", req.GetContinent())) } if req.GetRequest().GetUnknownEnum() { params.Add("request.unknownEnum", fmt.Sprintf("%v", req.GetRequest().GetUnknownEnum())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).VerifyEnum[0:len((*c.CallOptions).VerifyEnum):len((*c.CallOptions).VerifyEnum)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.EnumResponse{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "VerifyEnum") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // ListLocations is a utility method from google.cloud.location.Locations. func (c *complianceRESTClient) ListLocations(ctx context.Context, req *locationpb.ListLocationsRequest, opts ...gax.CallOption) *LocationIterator { it := &LocationIterator{} req = proto.Clone(req).(*locationpb.ListLocationsRequest) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} it.InternalFetch = func(pageSize int, pageToken string) ([]*locationpb.Location, string, error) { resp := &locationpb.ListLocationsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, "", err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v/locations", req.GetName()) params := url.Values{} if req.GetFilter() != "" { params.Add("filter", fmt.Sprintf("%v", req.GetFilter())) } if req.GetPageSize() != 0 { params.Add("pageSize", fmt.Sprintf("%v", req.GetPageSize())) } if req.GetPageToken() != "" { params.Add("pageToken", fmt.Sprintf("%v", req.GetPageToken())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "ListLocations") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, "", e } it.Response = resp return resp.GetLocations(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } // GetLocation is a utility method from google.cloud.location.Locations. func (c *complianceRESTClient) GetLocation(ctx context.Context, req *locationpb.GetLocationRequest, opts ...gax.CallOption) (*locationpb.Location, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).GetLocation[0:len((*c.CallOptions).GetLocation):len((*c.CallOptions).GetLocation)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &locationpb.Location{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "GetLocation") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // SetIamPolicy is a utility method from google.iam.v1.IAMPolicy. func (c *complianceRESTClient) SetIamPolicy(ctx context.Context, req *iampb.SetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:setIamPolicy", req.GetResource()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).SetIamPolicy[0:len((*c.CallOptions).SetIamPolicy):len((*c.CallOptions).SetIamPolicy)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &iampb.Policy{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "SetIamPolicy") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // GetIamPolicy is a utility method from google.iam.v1.IAMPolicy. func (c *complianceRESTClient) GetIamPolicy(ctx context.Context, req *iampb.GetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:getIamPolicy", req.GetResource()) params := url.Values{} if req.GetOptions().GetRequestedPolicyVersion() != 0 { params.Add("options.requestedPolicyVersion", fmt.Sprintf("%v", req.GetOptions().GetRequestedPolicyVersion())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).GetIamPolicy[0:len((*c.CallOptions).GetIamPolicy):len((*c.CallOptions).GetIamPolicy)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &iampb.Policy{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "GetIamPolicy") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // TestIamPermissions is a utility method from google.iam.v1.IAMPolicy. func (c *complianceRESTClient) TestIamPermissions(ctx context.Context, req *iampb.TestIamPermissionsRequest, opts ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:testIamPermissions", req.GetResource()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).TestIamPermissions[0:len((*c.CallOptions).TestIamPermissions):len((*c.CallOptions).TestIamPermissions)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &iampb.TestIamPermissionsResponse{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "TestIamPermissions") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // ListOperations is a utility method from google.longrunning.Operations. func (c *complianceRESTClient) ListOperations(ctx context.Context, req *longrunningpb.ListOperationsRequest, opts ...gax.CallOption) *OperationIterator { it := &OperationIterator{} req = proto.Clone(req).(*longrunningpb.ListOperationsRequest) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} it.InternalFetch = func(pageSize int, pageToken string) ([]*longrunningpb.Operation, string, error) { resp := &longrunningpb.ListOperationsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, "", err } baseUrl.Path += fmt.Sprintf("/v1beta1/operations") params := url.Values{} if req.GetFilter() != "" { params.Add("filter", fmt.Sprintf("%v", req.GetFilter())) } if req.GetName() != "" { params.Add("name", fmt.Sprintf("%v", req.GetName())) } if req.GetPageSize() != 0 { params.Add("pageSize", fmt.Sprintf("%v", req.GetPageSize())) } if req.GetPageToken() != "" { params.Add("pageToken", fmt.Sprintf("%v", req.GetPageToken())) } if req.GetReturnPartialSuccess() { params.Add("returnPartialSuccess", fmt.Sprintf("%v", req.GetReturnPartialSuccess())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "ListOperations") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, "", e } it.Response = resp return resp.GetOperations(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } // GetOperation is a utility method from google.longrunning.Operations. func (c *complianceRESTClient) GetOperation(ctx context.Context, req *longrunningpb.GetOperationRequest, opts ...gax.CallOption) (*longrunningpb.Operation, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).GetOperation[0:len((*c.CallOptions).GetOperation):len((*c.CallOptions).GetOperation)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &longrunningpb.Operation{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "GetOperation") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // DeleteOperation is a utility method from google.longrunning.Operations. func (c *complianceRESTClient) DeleteOperation(ctx context.Context, req *longrunningpb.DeleteOperationRequest, opts ...gax.CallOption) error { baseUrl, err := url.Parse(c.endpoint) if err != nil { return err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) return gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("DELETE", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers _, err = executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "DeleteOperation") return err }, opts...) } // CancelOperation is a utility method from google.longrunning.Operations. func (c *complianceRESTClient) CancelOperation(ctx context.Context, req *longrunningpb.CancelOperationRequest, opts ...gax.CallOption) error { baseUrl, err := url.Parse(c.endpoint) if err != nil { return err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:cancel", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) return gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers _, err = executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "CancelOperation") return err }, opts...) } ================================================ FILE: client/compliance_client_example_go123_test.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go_gapic. DO NOT EDIT. //go:build go1.23 package client_test import ( "context" longrunningpb "cloud.google.com/go/longrunning/autogen/longrunningpb" client "github.com/googleapis/gapic-showcase/client" locationpb "google.golang.org/genproto/googleapis/cloud/location" ) func ExampleComplianceClient_ListLocations_all() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewComplianceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &locationpb.ListLocationsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/google.golang.org/genproto/googleapis/cloud/location#ListLocationsRequest. } for resp, err := range c.ListLocations(ctx, req).All() { if err != nil { // TODO: Handle error and break/return/continue. Iteration will stop after any error. } // TODO: Use resp. _ = resp } } func ExampleComplianceClient_ListOperations_all() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewComplianceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.ListOperationsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#ListOperationsRequest. } for resp, err := range c.ListOperations(ctx, req).All() { if err != nil { // TODO: Handle error and break/return/continue. Iteration will stop after any error. } // TODO: Use resp. _ = resp } } ================================================ FILE: client/compliance_client_example_test.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go_gapic. DO NOT EDIT. package client_test import ( "context" iampb "cloud.google.com/go/iam/apiv1/iampb" longrunningpb "cloud.google.com/go/longrunning/autogen/longrunningpb" client "github.com/googleapis/gapic-showcase/client" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "google.golang.org/api/iterator" locationpb "google.golang.org/genproto/googleapis/cloud/location" ) func ExampleNewComplianceClient() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewComplianceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() // TODO: Use client. _ = c } func ExampleNewComplianceRESTClient() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewComplianceRESTClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() // TODO: Use client. _ = c } func ExampleComplianceClient_GetEnum() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewComplianceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.EnumRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#EnumRequest. } resp, err := c.GetEnum(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleComplianceClient_RepeatDataBody() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewComplianceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.RepeatRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#RepeatRequest. } resp, err := c.RepeatDataBody(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleComplianceClient_RepeatDataBodyInfo() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewComplianceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.RepeatRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#RepeatRequest. } resp, err := c.RepeatDataBodyInfo(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleComplianceClient_RepeatDataBodyPatch() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewComplianceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.RepeatRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#RepeatRequest. } resp, err := c.RepeatDataBodyPatch(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleComplianceClient_RepeatDataBodyPut() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewComplianceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.RepeatRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#RepeatRequest. } resp, err := c.RepeatDataBodyPut(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleComplianceClient_RepeatDataPathResource() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewComplianceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.RepeatRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#RepeatRequest. } resp, err := c.RepeatDataPathResource(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleComplianceClient_RepeatDataPathTrailingResource() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewComplianceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.RepeatRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#RepeatRequest. } resp, err := c.RepeatDataPathTrailingResource(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleComplianceClient_RepeatDataQuery() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewComplianceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.RepeatRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#RepeatRequest. } resp, err := c.RepeatDataQuery(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleComplianceClient_RepeatDataSimplePath() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewComplianceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.RepeatRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#RepeatRequest. } resp, err := c.RepeatDataSimplePath(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleComplianceClient_VerifyEnum() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewComplianceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.EnumResponse{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#EnumResponse. } resp, err := c.VerifyEnum(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleComplianceClient_ListLocations() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewComplianceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &locationpb.ListLocationsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/google.golang.org/genproto/googleapis/cloud/location#ListLocationsRequest. } it := c.ListLocations(ctx, req) for { resp, err := it.Next() if err == iterator.Done { break } if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp // If you need to access the underlying RPC response, // you can do so by casting the `Response` as below. // Otherwise, remove this line. Only populated after // first call to Next(). Not safe for concurrent access. _ = it.Response.(*locationpb.ListLocationsResponse) } } func ExampleComplianceClient_GetLocation() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewComplianceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &locationpb.GetLocationRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/google.golang.org/genproto/googleapis/cloud/location#GetLocationRequest. } resp, err := c.GetLocation(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleComplianceClient_SetIamPolicy() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewComplianceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &iampb.SetIamPolicyRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/iam/apiv1/iampb#SetIamPolicyRequest. } resp, err := c.SetIamPolicy(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleComplianceClient_GetIamPolicy() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewComplianceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &iampb.GetIamPolicyRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/iam/apiv1/iampb#GetIamPolicyRequest. } resp, err := c.GetIamPolicy(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleComplianceClient_TestIamPermissions() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewComplianceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &iampb.TestIamPermissionsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/iam/apiv1/iampb#TestIamPermissionsRequest. } resp, err := c.TestIamPermissions(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleComplianceClient_ListOperations() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewComplianceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.ListOperationsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#ListOperationsRequest. } it := c.ListOperations(ctx, req) for { resp, err := it.Next() if err == iterator.Done { break } if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp // If you need to access the underlying RPC response, // you can do so by casting the `Response` as below. // Otherwise, remove this line. Only populated after // first call to Next(). Not safe for concurrent access. _ = it.Response.(*longrunningpb.ListOperationsResponse) } } func ExampleComplianceClient_GetOperation() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewComplianceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.GetOperationRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#GetOperationRequest. } resp, err := c.GetOperation(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleComplianceClient_DeleteOperation() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewComplianceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.DeleteOperationRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#DeleteOperationRequest. } err = c.DeleteOperation(ctx, req) if err != nil { // TODO: Handle error. } } func ExampleComplianceClient_CancelOperation() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewComplianceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.CancelOperationRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#CancelOperationRequest. } err = c.CancelOperation(ctx, req) if err != nil { // TODO: Handle error. } } ================================================ FILE: client/doc.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go_gapic. DO NOT EDIT. // Package client is an auto-generated package for the // Client Libraries Showcase API. // // Showcase represents both a model API and an integration testing surface // for client library generator consumption. // // # API Versions // // The versioned iterations of API service interfaces in this API client package. // Each client includes the API version identifier mentioned below in their API calls. // Navigate to the product documentation to learn more about the API versions used in this package. // // All clients in this package use version v1_20240408 of their service interface. // // # General documentation // // For information that is relevant for all client libraries please reference // https://pkg.go.dev/cloud.google.com/go#pkg-overview. Some information on this // page includes: // // - [Authentication and Authorization] // - [Timeouts and Cancellation] // - [Testing against Client Libraries] // - [Debugging Client Libraries] // - [Inspecting errors] // // # Example usage // // To get started with this package, create a client. // // // go get github.com/googleapis/gapic-showcase/client@latest // ctx := context.Background() // // This snippet has been automatically generated and should be regarded as a code template only. // // It will require modifications to work: // // - It may require correct/in-range values for request initialization. // // - It may require specifying regional endpoints when creating the service client as shown in: // // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options // c, err := client.NewComplianceClient(ctx) // if err != nil { // // TODO: Handle error. // } // defer c.Close() // // The client will use your default application credentials. Clients should be reused instead of created as needed. // The methods of Client are safe for concurrent use by multiple goroutines. // The returned client must be Closed when it is done being used. // // # Using the Client // // The following is an example of making an API call with the newly created client, mentioned above. // // req := &genprotopb.EnumRequest{ // // TODO: Fill request struct fields. // // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#EnumRequest. // } // resp, err := c.GetEnum(ctx, req) // if err != nil { // // TODO: Handle error. // } // // TODO: Use resp. // _ = resp // // # Use of Context // // The ctx passed to NewComplianceClient is used for authentication requests and // for creating the underlying connection, but is not used for subsequent calls. // Individual methods on the client use the ctx given to them. // // To close the open connection, use the Close() method. // // [Authentication and Authorization]: https://pkg.go.dev/cloud.google.com/go#hdr-Authentication_and_Authorization // [Timeouts and Cancellation]: https://pkg.go.dev/cloud.google.com/go#hdr-Timeouts_and_Cancellation // [Testing against Client Libraries]: https://pkg.go.dev/cloud.google.com/go#hdr-Testing // [Debugging Client Libraries]: https://pkg.go.dev/cloud.google.com/go#hdr-Debugging // [Inspecting errors]: https://pkg.go.dev/cloud.google.com/go#hdr-Inspecting_errors package client // import "github.com/googleapis/gapic-showcase/client" ================================================ FILE: client/echo_client.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go_gapic. DO NOT EDIT. package client import ( "bytes" "context" "errors" "fmt" "log/slog" "math" "net/http" "net/url" "regexp" "sort" "strings" "time" iampb "cloud.google.com/go/iam/apiv1/iampb" "cloud.google.com/go/longrunning" lroauto "cloud.google.com/go/longrunning/autogen" longrunningpb "cloud.google.com/go/longrunning/autogen/longrunningpb" "github.com/google/uuid" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" gax "github.com/googleapis/gax-go/v2" "google.golang.org/api/iterator" "google.golang.org/api/option" "google.golang.org/api/option/internaloption" gtransport "google.golang.org/api/transport/grpc" httptransport "google.golang.org/api/transport/http" locationpb "google.golang.org/genproto/googleapis/cloud/location" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" ) var newEchoClientHook clientHook // EchoCallOptions contains the retry settings for each method of EchoClient. type EchoCallOptions struct { Echo []gax.CallOption EchoErrorDetails []gax.CallOption FailEchoWithDetails []gax.CallOption Expand []gax.CallOption Collect []gax.CallOption Chat []gax.CallOption PagedExpand []gax.CallOption PagedExpandLegacy []gax.CallOption PagedExpandLegacyMapped []gax.CallOption Wait []gax.CallOption Block []gax.CallOption ListLocations []gax.CallOption GetLocation []gax.CallOption SetIamPolicy []gax.CallOption GetIamPolicy []gax.CallOption TestIamPermissions []gax.CallOption ListOperations []gax.CallOption GetOperation []gax.CallOption DeleteOperation []gax.CallOption CancelOperation []gax.CallOption } func defaultEchoGRPCClientOptions() []option.ClientOption { return []option.ClientOption{ internaloption.WithDefaultEndpoint("localhost:7469"), internaloption.WithDefaultEndpointTemplate("localhost:7469"), internaloption.WithDefaultMTLSEndpoint("localhost:7469"), internaloption.WithDefaultUniverseDomain("googleapis.com"), internaloption.WithDefaultAudience("https://localhost/"), internaloption.WithDefaultScopes(DefaultAuthScopes()...), internaloption.EnableJwtWithScope(), internaloption.EnableNewAuthLibrary(), option.WithGRPCDialOption(grpc.WithDefaultCallOptions( grpc.MaxCallRecvMsgSize(math.MaxInt32))), } } func defaultEchoCallOptions() *EchoCallOptions { return &EchoCallOptions{ Echo: []gax.CallOption{ gax.WithTimeout(10000 * time.Millisecond), gax.WithRetry(func() gax.Retryer { return gax.OnCodes([]codes.Code{ codes.Unavailable, codes.Unknown, }, gax.Backoff{ Initial: 100 * time.Millisecond, Max: 3000 * time.Millisecond, Multiplier: 2.00, }) }), }, EchoErrorDetails: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, FailEchoWithDetails: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, Expand: []gax.CallOption{ gax.WithRetry(func() gax.Retryer { return gax.OnCodes([]codes.Code{ codes.Unavailable, codes.Unknown, }, gax.Backoff{ Initial: 100 * time.Millisecond, Max: 3000 * time.Millisecond, Multiplier: 2.00, }) }), }, Collect: []gax.CallOption{}, Chat: []gax.CallOption{}, PagedExpand: []gax.CallOption{ gax.WithTimeout(10000 * time.Millisecond), gax.WithRetry(func() gax.Retryer { return gax.OnCodes([]codes.Code{ codes.Unavailable, codes.Unknown, }, gax.Backoff{ Initial: 100 * time.Millisecond, Max: 3000 * time.Millisecond, Multiplier: 2.00, }) }), }, PagedExpandLegacy: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, PagedExpandLegacyMapped: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, Wait: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, Block: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, ListLocations: []gax.CallOption{}, GetLocation: []gax.CallOption{}, SetIamPolicy: []gax.CallOption{}, GetIamPolicy: []gax.CallOption{}, TestIamPermissions: []gax.CallOption{}, ListOperations: []gax.CallOption{}, GetOperation: []gax.CallOption{}, DeleteOperation: []gax.CallOption{}, CancelOperation: []gax.CallOption{}, } } func defaultEchoRESTCallOptions() *EchoCallOptions { return &EchoCallOptions{ Echo: []gax.CallOption{ gax.WithTimeout(10000 * time.Millisecond), gax.WithRetry(func() gax.Retryer { return gax.OnHTTPCodes(gax.Backoff{ Initial: 100 * time.Millisecond, Max: 3000 * time.Millisecond, Multiplier: 2.00, }, http.StatusServiceUnavailable, http.StatusInternalServerError) }), }, EchoErrorDetails: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, FailEchoWithDetails: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, Expand: []gax.CallOption{ gax.WithTimeout(10000 * time.Millisecond), gax.WithRetry(func() gax.Retryer { return gax.OnHTTPCodes(gax.Backoff{ Initial: 100 * time.Millisecond, Max: 3000 * time.Millisecond, Multiplier: 2.00, }, http.StatusServiceUnavailable, http.StatusInternalServerError) }), }, Collect: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, Chat: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, PagedExpand: []gax.CallOption{ gax.WithTimeout(10000 * time.Millisecond), gax.WithRetry(func() gax.Retryer { return gax.OnHTTPCodes(gax.Backoff{ Initial: 100 * time.Millisecond, Max: 3000 * time.Millisecond, Multiplier: 2.00, }, http.StatusServiceUnavailable, http.StatusInternalServerError) }), }, PagedExpandLegacy: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, PagedExpandLegacyMapped: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, Wait: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, Block: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, ListLocations: []gax.CallOption{}, GetLocation: []gax.CallOption{}, SetIamPolicy: []gax.CallOption{}, GetIamPolicy: []gax.CallOption{}, TestIamPermissions: []gax.CallOption{}, ListOperations: []gax.CallOption{}, GetOperation: []gax.CallOption{}, DeleteOperation: []gax.CallOption{}, CancelOperation: []gax.CallOption{}, } } // internalEchoClient is an interface that defines the methods available from Client Libraries Showcase API. type internalEchoClient interface { Close() error setGoogleClientInfo(...string) Connection() *grpc.ClientConn Echo(context.Context, *genprotopb.EchoRequest, ...gax.CallOption) (*genprotopb.EchoResponse, error) EchoErrorDetails(context.Context, *genprotopb.EchoErrorDetailsRequest, ...gax.CallOption) (*genprotopb.EchoErrorDetailsResponse, error) FailEchoWithDetails(context.Context, *genprotopb.FailEchoWithDetailsRequest, ...gax.CallOption) (*genprotopb.FailEchoWithDetailsResponse, error) Expand(context.Context, *genprotopb.ExpandRequest, ...gax.CallOption) (genprotopb.Echo_ExpandClient, error) Collect(context.Context, ...gax.CallOption) (genprotopb.Echo_CollectClient, error) Chat(context.Context, ...gax.CallOption) (genprotopb.Echo_ChatClient, error) PagedExpand(context.Context, *genprotopb.PagedExpandRequest, ...gax.CallOption) *EchoResponseIterator PagedExpandLegacy(context.Context, *genprotopb.PagedExpandLegacyRequest, ...gax.CallOption) *EchoResponseIterator PagedExpandLegacyMapped(context.Context, *genprotopb.PagedExpandRequest, ...gax.CallOption) *PagedExpandResponseListPairIterator Wait(context.Context, *genprotopb.WaitRequest, ...gax.CallOption) (*WaitOperation, error) WaitOperation(name string) *WaitOperation Block(context.Context, *genprotopb.BlockRequest, ...gax.CallOption) (*genprotopb.BlockResponse, error) ListLocations(context.Context, *locationpb.ListLocationsRequest, ...gax.CallOption) *LocationIterator GetLocation(context.Context, *locationpb.GetLocationRequest, ...gax.CallOption) (*locationpb.Location, error) SetIamPolicy(context.Context, *iampb.SetIamPolicyRequest, ...gax.CallOption) (*iampb.Policy, error) GetIamPolicy(context.Context, *iampb.GetIamPolicyRequest, ...gax.CallOption) (*iampb.Policy, error) TestIamPermissions(context.Context, *iampb.TestIamPermissionsRequest, ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error) ListOperations(context.Context, *longrunningpb.ListOperationsRequest, ...gax.CallOption) *OperationIterator GetOperation(context.Context, *longrunningpb.GetOperationRequest, ...gax.CallOption) (*longrunningpb.Operation, error) DeleteOperation(context.Context, *longrunningpb.DeleteOperationRequest, ...gax.CallOption) error CancelOperation(context.Context, *longrunningpb.CancelOperationRequest, ...gax.CallOption) error } // EchoClient is a client for interacting with Client Libraries Showcase API. // Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls. // // This service is used showcase the four main types of rpcs - unary, server // side streaming, client side streaming, and bidirectional streaming. This // service also exposes methods that explicitly implement server delay, and // paginated calls. Set the ‘showcase-trailer’ metadata key on any method // to have the values echoed in the response trailers. Set the // ‘x-goog-request-params’ metadata key on any method to have the values // echoed in the response headers. // // This client uses Echo version v1_20240408. type EchoClient struct { // The internal transport-dependent client. internalClient internalEchoClient // The call options for this service. CallOptions *EchoCallOptions // LROClient is used internally to handle long-running operations. // It is exposed so that its CallOptions can be modified if required. // Users should not Close this client. LROClient *lroauto.OperationsClient } // Wrapper methods routed to the internal client. // Close closes the connection to the API service. The user should invoke this when // the client is no longer required. func (c *EchoClient) Close() error { return c.internalClient.Close() } // setGoogleClientInfo sets the name and version of the application in // the `x-goog-api-client` header passed on each request. Intended for // use by Google-written clients. func (c *EchoClient) setGoogleClientInfo(keyval ...string) { c.internalClient.setGoogleClientInfo(keyval...) } // Connection returns a connection to the API service. // // Deprecated: Connections are now pooled so this method does not always // return the same resource. func (c *EchoClient) Connection() *grpc.ClientConn { return c.internalClient.Connection() } // Echo this method simply echoes the request. This method showcases unary RPCs. func (c *EchoClient) Echo(ctx context.Context, req *genprotopb.EchoRequest, opts ...gax.CallOption) (*genprotopb.EchoResponse, error) { return c.internalClient.Echo(ctx, req, opts...) } // EchoErrorDetails this method returns error details in a repeated “google.protobuf.Any” // field. This method showcases handling errors thus encoded, particularly // over REST transport. Note that GAPICs only allow the type // “google.protobuf.Any” for field paths ending in “error.details”, and, at // run-time, the actual types for these fields must be one of the types in // google/rpc/error_details.proto. func (c *EchoClient) EchoErrorDetails(ctx context.Context, req *genprotopb.EchoErrorDetailsRequest, opts ...gax.CallOption) (*genprotopb.EchoErrorDetailsResponse, error) { return c.internalClient.EchoErrorDetails(ctx, req, opts...) } // FailEchoWithDetails this method always fails with a gRPC “Aborted” error status that contains // multiple error details. These include one instance of each of the standard // ones in error_details.proto // (https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto (at https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto)) // plus a custom, Showcase-defined PoetryError. The intent of this RPC is to // verify that GAPICs can process these various error details and surface them // to the user in an idiomatic form. func (c *EchoClient) FailEchoWithDetails(ctx context.Context, req *genprotopb.FailEchoWithDetailsRequest, opts ...gax.CallOption) (*genprotopb.FailEchoWithDetailsResponse, error) { return c.internalClient.FailEchoWithDetails(ctx, req, opts...) } // Expand this method splits the given content into words and will pass each word back // through the stream. This method showcases server-side streaming RPCs. func (c *EchoClient) Expand(ctx context.Context, req *genprotopb.ExpandRequest, opts ...gax.CallOption) (genprotopb.Echo_ExpandClient, error) { return c.internalClient.Expand(ctx, req, opts...) } // Collect this method will collect the words given to it. When the stream is closed // by the client, this method will return the a concatenation of the strings // passed to it. This method showcases client-side streaming RPCs. // // This method is not supported for the REST transport. func (c *EchoClient) Collect(ctx context.Context, opts ...gax.CallOption) (genprotopb.Echo_CollectClient, error) { return c.internalClient.Collect(ctx, opts...) } // Chat this method, upon receiving a request on the stream, will pass the same // content back on the stream. This method showcases bidirectional // streaming RPCs. // // This method is not supported for the REST transport. func (c *EchoClient) Chat(ctx context.Context, opts ...gax.CallOption) (genprotopb.Echo_ChatClient, error) { return c.internalClient.Chat(ctx, opts...) } // PagedExpand this is similar to the Expand method but instead of returning a stream of // expanded words, this method returns a paged list of expanded words. func (c *EchoClient) PagedExpand(ctx context.Context, req *genprotopb.PagedExpandRequest, opts ...gax.CallOption) *EchoResponseIterator { return c.internalClient.PagedExpand(ctx, req, opts...) } // PagedExpandLegacy this is similar to the PagedExpand except that it uses // max_results instead of page_size, as some legacy APIs still // do. New APIs should NOT use this pattern. func (c *EchoClient) PagedExpandLegacy(ctx context.Context, req *genprotopb.PagedExpandLegacyRequest, opts ...gax.CallOption) *EchoResponseIterator { return c.internalClient.PagedExpandLegacy(ctx, req, opts...) } // PagedExpandLegacyMapped this method returns a map containing lists of words that appear in the input, keyed by their // initial character. The only words returned are the ones included in the current page, // as determined by page_token and page_size, which both refer to the word indices in the // input. This paging result consisting of a map of lists is a pattern used by some legacy // APIs. New APIs should NOT use this pattern. func (c *EchoClient) PagedExpandLegacyMapped(ctx context.Context, req *genprotopb.PagedExpandRequest, opts ...gax.CallOption) *PagedExpandResponseListPairIterator { return c.internalClient.PagedExpandLegacyMapped(ctx, req, opts...) } // Wait this method will wait for the requested amount of time and then return. // This method showcases how a client handles a request timeout. func (c *EchoClient) Wait(ctx context.Context, req *genprotopb.WaitRequest, opts ...gax.CallOption) (*WaitOperation, error) { return c.internalClient.Wait(ctx, req, opts...) } // WaitOperation returns a new WaitOperation from a given name. // The name must be that of a previously created WaitOperation, possibly from a different process. func (c *EchoClient) WaitOperation(name string) *WaitOperation { return c.internalClient.WaitOperation(name) } // Block this method will block (wait) for the requested amount of time // and then return the response or error. // This method showcases how a client handles delays or retries. func (c *EchoClient) Block(ctx context.Context, req *genprotopb.BlockRequest, opts ...gax.CallOption) (*genprotopb.BlockResponse, error) { return c.internalClient.Block(ctx, req, opts...) } // ListLocations is a utility method from google.cloud.location.Locations. func (c *EchoClient) ListLocations(ctx context.Context, req *locationpb.ListLocationsRequest, opts ...gax.CallOption) *LocationIterator { return c.internalClient.ListLocations(ctx, req, opts...) } // GetLocation is a utility method from google.cloud.location.Locations. func (c *EchoClient) GetLocation(ctx context.Context, req *locationpb.GetLocationRequest, opts ...gax.CallOption) (*locationpb.Location, error) { return c.internalClient.GetLocation(ctx, req, opts...) } // SetIamPolicy is a utility method from google.iam.v1.IAMPolicy. func (c *EchoClient) SetIamPolicy(ctx context.Context, req *iampb.SetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { return c.internalClient.SetIamPolicy(ctx, req, opts...) } // GetIamPolicy is a utility method from google.iam.v1.IAMPolicy. func (c *EchoClient) GetIamPolicy(ctx context.Context, req *iampb.GetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { return c.internalClient.GetIamPolicy(ctx, req, opts...) } // TestIamPermissions is a utility method from google.iam.v1.IAMPolicy. func (c *EchoClient) TestIamPermissions(ctx context.Context, req *iampb.TestIamPermissionsRequest, opts ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error) { return c.internalClient.TestIamPermissions(ctx, req, opts...) } // ListOperations is a utility method from google.longrunning.Operations. func (c *EchoClient) ListOperations(ctx context.Context, req *longrunningpb.ListOperationsRequest, opts ...gax.CallOption) *OperationIterator { return c.internalClient.ListOperations(ctx, req, opts...) } // GetOperation is a utility method from google.longrunning.Operations. func (c *EchoClient) GetOperation(ctx context.Context, req *longrunningpb.GetOperationRequest, opts ...gax.CallOption) (*longrunningpb.Operation, error) { return c.internalClient.GetOperation(ctx, req, opts...) } // DeleteOperation is a utility method from google.longrunning.Operations. func (c *EchoClient) DeleteOperation(ctx context.Context, req *longrunningpb.DeleteOperationRequest, opts ...gax.CallOption) error { return c.internalClient.DeleteOperation(ctx, req, opts...) } // CancelOperation is a utility method from google.longrunning.Operations. func (c *EchoClient) CancelOperation(ctx context.Context, req *longrunningpb.CancelOperationRequest, opts ...gax.CallOption) error { return c.internalClient.CancelOperation(ctx, req, opts...) } // echoGRPCClient is a client for interacting with Client Libraries Showcase API over gRPC transport. // // Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls. type echoGRPCClient struct { // Connection pool of gRPC connections to the service. connPool gtransport.ConnPool // Points back to the CallOptions field of the containing EchoClient CallOptions **EchoCallOptions // The gRPC API client. echoClient genprotopb.EchoClient // LROClient is used internally to handle long-running operations. // It is exposed so that its CallOptions can be modified if required. // Users should not Close this client. LROClient **lroauto.OperationsClient operationsClient longrunningpb.OperationsClient iamPolicyClient iampb.IAMPolicyClient locationsClient locationpb.LocationsClient // The x-goog-* metadata to be sent with each request. xGoogHeaders []string logger *slog.Logger } // NewEchoClient creates a new echo client based on gRPC. // The returned client must be Closed when it is done being used to clean up its underlying connections. // // This service is used showcase the four main types of rpcs - unary, server // side streaming, client side streaming, and bidirectional streaming. This // service also exposes methods that explicitly implement server delay, and // paginated calls. Set the ‘showcase-trailer’ metadata key on any method // to have the values echoed in the response trailers. Set the // ‘x-goog-request-params’ metadata key on any method to have the values // echoed in the response headers. func NewEchoClient(ctx context.Context, opts ...option.ClientOption) (*EchoClient, error) { clientOpts := defaultEchoGRPCClientOptions() if newEchoClientHook != nil { hookOpts, err := newEchoClientHook(ctx, clientHookParams{}) if err != nil { return nil, err } clientOpts = append(clientOpts, hookOpts...) } connPool, err := gtransport.DialPool(ctx, append(clientOpts, opts...)...) if err != nil { return nil, err } client := EchoClient{CallOptions: defaultEchoCallOptions()} c := &echoGRPCClient{ connPool: connPool, echoClient: genprotopb.NewEchoClient(connPool), CallOptions: &client.CallOptions, logger: internaloption.GetLogger(opts), operationsClient: longrunningpb.NewOperationsClient(connPool), iamPolicyClient: iampb.NewIAMPolicyClient(connPool), locationsClient: locationpb.NewLocationsClient(connPool), } c.setGoogleClientInfo() client.internalClient = c client.LROClient, err = lroauto.NewOperationsClient(ctx, gtransport.WithConnPool(connPool)) if err != nil { // This error "should not happen", since we are just reusing old connection pool // and never actually need to dial. // If this does happen, we could leak connp. However, we cannot close conn: // If the user invoked the constructor with option.WithGRPCConn, // we would close a connection that's still in use. // TODO: investigate error conditions. return nil, err } c.LROClient = &client.LROClient return &client, nil } // Connection returns a connection to the API service. // // Deprecated: Connections are now pooled so this method does not always // return the same resource. func (c *echoGRPCClient) Connection() *grpc.ClientConn { return c.connPool.Conn() } // setGoogleClientInfo sets the name and version of the application in // the `x-goog-api-client` header passed on each request. Intended for // use by Google-written clients. func (c *echoGRPCClient) setGoogleClientInfo(keyval ...string) { kv := append([]string{"gl-go", gax.GoVersion}, keyval...) kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "grpc", grpc.Version, "pb", protoVersion) c.xGoogHeaders = []string{ "x-goog-api-client", gax.XGoogHeader(kv...), "x-goog-api-version", "v1_20240408", } } // Close closes the connection to the API service. The user should invoke this when // the client is no longer required. func (c *echoGRPCClient) Close() error { return c.connPool.Close() } // Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls. type echoRESTClient struct { // The http endpoint to connect to. endpoint string // The http client. httpClient *http.Client // LROClient is used internally to handle long-running operations. // It is exposed so that its CallOptions can be modified if required. // Users should not Close this client. LROClient **lroauto.OperationsClient // The x-goog-* headers to be sent with each request. xGoogHeaders []string // Points back to the CallOptions field of the containing EchoClient CallOptions **EchoCallOptions logger *slog.Logger } // NewEchoRESTClient creates a new echo rest client. // // This service is used showcase the four main types of rpcs - unary, server // side streaming, client side streaming, and bidirectional streaming. This // service also exposes methods that explicitly implement server delay, and // paginated calls. Set the ‘showcase-trailer’ metadata key on any method // to have the values echoed in the response trailers. Set the // ‘x-goog-request-params’ metadata key on any method to have the values // echoed in the response headers. func NewEchoRESTClient(ctx context.Context, opts ...option.ClientOption) (*EchoClient, error) { clientOpts := append(defaultEchoRESTClientOptions(), opts...) httpClient, endpoint, err := httptransport.NewClient(ctx, clientOpts...) if err != nil { return nil, err } callOpts := defaultEchoRESTCallOptions() c := &echoRESTClient{ endpoint: endpoint, httpClient: httpClient, CallOptions: &callOpts, logger: internaloption.GetLogger(opts), } c.setGoogleClientInfo() lroOpts := []option.ClientOption{ option.WithHTTPClient(httpClient), option.WithEndpoint(endpoint), } opClient, err := lroauto.NewOperationsRESTClient(ctx, lroOpts...) if err != nil { return nil, err } c.LROClient = &opClient return &EchoClient{internalClient: c, CallOptions: callOpts}, nil } func defaultEchoRESTClientOptions() []option.ClientOption { return []option.ClientOption{ internaloption.WithDefaultEndpoint("https://localhost:7469"), internaloption.WithDefaultEndpointTemplate("https://localhost:7469"), internaloption.WithDefaultMTLSEndpoint("https://localhost:7469"), internaloption.WithDefaultUniverseDomain("googleapis.com"), internaloption.WithDefaultAudience("https://localhost/"), internaloption.WithDefaultScopes(DefaultAuthScopes()...), internaloption.EnableNewAuthLibrary(), } } // setGoogleClientInfo sets the name and version of the application in // the `x-goog-api-client` header passed on each request. Intended for // use by Google-written clients. func (c *echoRESTClient) setGoogleClientInfo(keyval ...string) { kv := append([]string{"gl-go", gax.GoVersion}, keyval...) kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "rest", "UNKNOWN", "pb", protoVersion) c.xGoogHeaders = []string{ "x-goog-api-client", gax.XGoogHeader(kv...), "x-goog-api-version", "v1_20240408", } } // Close closes the connection to the API service. The user should invoke this when // the client is no longer required. func (c *echoRESTClient) Close() error { // Replace httpClient with nil to force cleanup. c.httpClient = nil return nil } // Connection returns a connection to the API service. // // Deprecated: This method always returns nil. func (c *echoRESTClient) Connection() *grpc.ClientConn { return nil } func (c *echoGRPCClient) Echo(ctx context.Context, req *genprotopb.EchoRequest, opts ...gax.CallOption) (*genprotopb.EchoResponse, error) { routingHeaders := "" routingHeadersMap := make(map[string]string) if reg := regexp.MustCompile("(.*)"); reg.MatchString(req.GetHeader()) && len(url.QueryEscape(reg.FindStringSubmatch(req.GetHeader())[1])) > 0 { routingHeadersMap["header"] = url.QueryEscape(reg.FindStringSubmatch(req.GetHeader())[1]) } if reg := regexp.MustCompile("(?P.*)"); reg.MatchString(req.GetHeader()) && len(url.QueryEscape(reg.FindStringSubmatch(req.GetHeader())[1])) > 0 { routingHeadersMap["routing_id"] = url.QueryEscape(reg.FindStringSubmatch(req.GetHeader())[1]) } if reg := regexp.MustCompile("(?Pregions/[^/]+/zones/[^/]+(?:/.*)?)"); reg.MatchString(req.GetHeader()) && len(url.QueryEscape(reg.FindStringSubmatch(req.GetHeader())[1])) > 0 { routingHeadersMap["table_name"] = url.QueryEscape(reg.FindStringSubmatch(req.GetHeader())[1]) } if reg := regexp.MustCompile("(?Pprojects/[^/]+)(?:/.*)?"); reg.MatchString(req.GetHeader()) && len(url.QueryEscape(reg.FindStringSubmatch(req.GetHeader())[1])) > 0 { routingHeadersMap["super_id"] = url.QueryEscape(reg.FindStringSubmatch(req.GetHeader())[1]) } if reg := regexp.MustCompile("(?Pprojects/[^/]+/instances/[^/]+(?:/.*)?)"); reg.MatchString(req.GetHeader()) && len(url.QueryEscape(reg.FindStringSubmatch(req.GetHeader())[1])) > 0 { routingHeadersMap["table_name"] = url.QueryEscape(reg.FindStringSubmatch(req.GetHeader())[1]) } if reg := regexp.MustCompile("projects/[^/]+/(?Pinstances/[^/]+)(?:/.*)?"); reg.MatchString(req.GetHeader()) && len(url.QueryEscape(reg.FindStringSubmatch(req.GetHeader())[1])) > 0 { routingHeadersMap["instance_id"] = url.QueryEscape(reg.FindStringSubmatch(req.GetHeader())[1]) } if reg := regexp.MustCompile("(?P.*)"); reg.MatchString(req.GetOtherHeader()) && len(url.QueryEscape(reg.FindStringSubmatch(req.GetOtherHeader())[1])) > 0 { routingHeadersMap["baz"] = url.QueryEscape(reg.FindStringSubmatch(req.GetOtherHeader())[1]) } if reg := regexp.MustCompile("(?Pprojects/[^/]+)(?:/.*)?"); reg.MatchString(req.GetOtherHeader()) && len(url.QueryEscape(reg.FindStringSubmatch(req.GetOtherHeader())[1])) > 0 { routingHeadersMap["qux"] = url.QueryEscape(reg.FindStringSubmatch(req.GetOtherHeader())[1]) } for headerName, headerValue := range routingHeadersMap { routingHeaders = fmt.Sprintf("%s%s=%s&", routingHeaders, headerName, headerValue) } routingHeaders = strings.TrimSuffix(routingHeaders, "&") hds := []string{"x-goog-request-params", routingHeaders} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) if req != nil && req.GetRequestId() == "" { req.RequestId = uuid.NewString() } if req != nil && req.OtherRequestId == nil { req.OtherRequestId = proto.String(uuid.NewString()) } opts = append((*c.CallOptions).Echo[0:len((*c.CallOptions).Echo):len((*c.CallOptions).Echo)], opts...) var resp *genprotopb.EchoResponse err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.echoClient.Echo, req, settings.GRPC, c.logger, "Echo") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *echoGRPCClient) EchoErrorDetails(ctx context.Context, req *genprotopb.EchoErrorDetailsRequest, opts ...gax.CallOption) (*genprotopb.EchoErrorDetailsResponse, error) { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).EchoErrorDetails[0:len((*c.CallOptions).EchoErrorDetails):len((*c.CallOptions).EchoErrorDetails)], opts...) var resp *genprotopb.EchoErrorDetailsResponse err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.echoClient.EchoErrorDetails, req, settings.GRPC, c.logger, "EchoErrorDetails") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *echoGRPCClient) FailEchoWithDetails(ctx context.Context, req *genprotopb.FailEchoWithDetailsRequest, opts ...gax.CallOption) (*genprotopb.FailEchoWithDetailsResponse, error) { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).FailEchoWithDetails[0:len((*c.CallOptions).FailEchoWithDetails):len((*c.CallOptions).FailEchoWithDetails)], opts...) var resp *genprotopb.FailEchoWithDetailsResponse err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.echoClient.FailEchoWithDetails, req, settings.GRPC, c.logger, "FailEchoWithDetails") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *echoGRPCClient) Expand(ctx context.Context, req *genprotopb.ExpandRequest, opts ...gax.CallOption) (genprotopb.Echo_ExpandClient, error) { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).Expand[0:len((*c.CallOptions).Expand):len((*c.CallOptions).Expand)], opts...) var resp genprotopb.Echo_ExpandClient err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error c.logger.DebugContext(ctx, "api streaming client request", "serviceName", serviceName, "rpcName", "Expand") resp, err = c.echoClient.Expand(ctx, req, settings.GRPC...) c.logger.DebugContext(ctx, "api streaming client response", "serviceName", serviceName, "rpcName", "Expand") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *echoGRPCClient) Collect(ctx context.Context, opts ...gax.CallOption) (genprotopb.Echo_CollectClient, error) { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) var resp genprotopb.Echo_CollectClient opts = append((*c.CallOptions).Collect[0:len((*c.CallOptions).Collect):len((*c.CallOptions).Collect)], opts...) err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error c.logger.DebugContext(ctx, "api streaming client request", "serviceName", serviceName, "rpcName", "Collect") resp, err = c.echoClient.Collect(ctx, settings.GRPC...) c.logger.DebugContext(ctx, "api streaming client response", "serviceName", serviceName, "rpcName", "Collect") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *echoGRPCClient) Chat(ctx context.Context, opts ...gax.CallOption) (genprotopb.Echo_ChatClient, error) { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) var resp genprotopb.Echo_ChatClient opts = append((*c.CallOptions).Chat[0:len((*c.CallOptions).Chat):len((*c.CallOptions).Chat)], opts...) err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error c.logger.DebugContext(ctx, "api streaming client request", "serviceName", serviceName, "rpcName", "Chat") resp, err = c.echoClient.Chat(ctx, settings.GRPC...) c.logger.DebugContext(ctx, "api streaming client response", "serviceName", serviceName, "rpcName", "Chat") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *echoGRPCClient) PagedExpand(ctx context.Context, req *genprotopb.PagedExpandRequest, opts ...gax.CallOption) *EchoResponseIterator { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).PagedExpand[0:len((*c.CallOptions).PagedExpand):len((*c.CallOptions).PagedExpand)], opts...) it := &EchoResponseIterator{} req = proto.Clone(req).(*genprotopb.PagedExpandRequest) it.InternalFetch = func(pageSize int, pageToken string) ([]*genprotopb.EchoResponse, string, error) { resp := &genprotopb.PagedExpandResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.echoClient.PagedExpand, req, settings.GRPC, c.logger, "PagedExpand") return err }, opts...) if err != nil { return nil, "", err } it.Response = resp return resp.GetResponses(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } func (c *echoGRPCClient) PagedExpandLegacy(ctx context.Context, req *genprotopb.PagedExpandLegacyRequest, opts ...gax.CallOption) *EchoResponseIterator { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).PagedExpandLegacy[0:len((*c.CallOptions).PagedExpandLegacy):len((*c.CallOptions).PagedExpandLegacy)], opts...) it := &EchoResponseIterator{} req = proto.Clone(req).(*genprotopb.PagedExpandLegacyRequest) it.InternalFetch = func(pageSize int, pageToken string) ([]*genprotopb.EchoResponse, string, error) { resp := &genprotopb.PagedExpandResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.MaxResults = math.MaxInt32 } else if pageSize != 0 { req.MaxResults = int32(pageSize) } err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.echoClient.PagedExpandLegacy, req, settings.GRPC, c.logger, "PagedExpandLegacy") return err }, opts...) if err != nil { return nil, "", err } it.Response = resp return resp.GetResponses(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetMaxResults()) it.pageInfo.Token = req.GetPageToken() return it } func (c *echoGRPCClient) PagedExpandLegacyMapped(ctx context.Context, req *genprotopb.PagedExpandRequest, opts ...gax.CallOption) *PagedExpandResponseListPairIterator { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).PagedExpandLegacyMapped[0:len((*c.CallOptions).PagedExpandLegacyMapped):len((*c.CallOptions).PagedExpandLegacyMapped)], opts...) it := &PagedExpandResponseListPairIterator{} req = proto.Clone(req).(*genprotopb.PagedExpandRequest) it.InternalFetch = func(pageSize int, pageToken string) ([]PagedExpandResponseListPair, string, error) { resp := &genprotopb.PagedExpandLegacyMappedResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.echoClient.PagedExpandLegacyMapped, req, settings.GRPC, c.logger, "PagedExpandLegacyMapped") return err }, opts...) if err != nil { return nil, "", err } it.Response = resp elems := make([]PagedExpandResponseListPair, 0, len(resp.GetAlphabetized())) for k, v := range resp.GetAlphabetized() { elems = append(elems, PagedExpandResponseListPair{k, v}) } sort.Slice(elems, func(i, j int) bool { return elems[i].Key < elems[j].Key }) return elems, resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } func (c *echoGRPCClient) Wait(ctx context.Context, req *genprotopb.WaitRequest, opts ...gax.CallOption) (*WaitOperation, error) { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).Wait[0:len((*c.CallOptions).Wait):len((*c.CallOptions).Wait)], opts...) var resp *longrunningpb.Operation err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.echoClient.Wait, req, settings.GRPC, c.logger, "Wait") return err }, opts...) if err != nil { return nil, err } return &WaitOperation{ lro: longrunning.InternalNewOperation(*c.LROClient, resp), }, nil } func (c *echoGRPCClient) Block(ctx context.Context, req *genprotopb.BlockRequest, opts ...gax.CallOption) (*genprotopb.BlockResponse, error) { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).Block[0:len((*c.CallOptions).Block):len((*c.CallOptions).Block)], opts...) var resp *genprotopb.BlockResponse err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.echoClient.Block, req, settings.GRPC, c.logger, "Block") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *echoGRPCClient) ListLocations(ctx context.Context, req *locationpb.ListLocationsRequest, opts ...gax.CallOption) *LocationIterator { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).ListLocations[0:len((*c.CallOptions).ListLocations):len((*c.CallOptions).ListLocations)], opts...) it := &LocationIterator{} req = proto.Clone(req).(*locationpb.ListLocationsRequest) it.InternalFetch = func(pageSize int, pageToken string) ([]*locationpb.Location, string, error) { resp := &locationpb.ListLocationsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.locationsClient.ListLocations, req, settings.GRPC, c.logger, "ListLocations") return err }, opts...) if err != nil { return nil, "", err } it.Response = resp return resp.GetLocations(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } func (c *echoGRPCClient) GetLocation(ctx context.Context, req *locationpb.GetLocationRequest, opts ...gax.CallOption) (*locationpb.Location, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).GetLocation[0:len((*c.CallOptions).GetLocation):len((*c.CallOptions).GetLocation)], opts...) var resp *locationpb.Location err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.locationsClient.GetLocation, req, settings.GRPC, c.logger, "GetLocation") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *echoGRPCClient) SetIamPolicy(ctx context.Context, req *iampb.SetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).SetIamPolicy[0:len((*c.CallOptions).SetIamPolicy):len((*c.CallOptions).SetIamPolicy)], opts...) var resp *iampb.Policy err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.iamPolicyClient.SetIamPolicy, req, settings.GRPC, c.logger, "SetIamPolicy") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *echoGRPCClient) GetIamPolicy(ctx context.Context, req *iampb.GetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).GetIamPolicy[0:len((*c.CallOptions).GetIamPolicy):len((*c.CallOptions).GetIamPolicy)], opts...) var resp *iampb.Policy err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.iamPolicyClient.GetIamPolicy, req, settings.GRPC, c.logger, "GetIamPolicy") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *echoGRPCClient) TestIamPermissions(ctx context.Context, req *iampb.TestIamPermissionsRequest, opts ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).TestIamPermissions[0:len((*c.CallOptions).TestIamPermissions):len((*c.CallOptions).TestIamPermissions)], opts...) var resp *iampb.TestIamPermissionsResponse err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.iamPolicyClient.TestIamPermissions, req, settings.GRPC, c.logger, "TestIamPermissions") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *echoGRPCClient) ListOperations(ctx context.Context, req *longrunningpb.ListOperationsRequest, opts ...gax.CallOption) *OperationIterator { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).ListOperations[0:len((*c.CallOptions).ListOperations):len((*c.CallOptions).ListOperations)], opts...) it := &OperationIterator{} req = proto.Clone(req).(*longrunningpb.ListOperationsRequest) it.InternalFetch = func(pageSize int, pageToken string) ([]*longrunningpb.Operation, string, error) { resp := &longrunningpb.ListOperationsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.operationsClient.ListOperations, req, settings.GRPC, c.logger, "ListOperations") return err }, opts...) if err != nil { return nil, "", err } it.Response = resp return resp.GetOperations(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } func (c *echoGRPCClient) GetOperation(ctx context.Context, req *longrunningpb.GetOperationRequest, opts ...gax.CallOption) (*longrunningpb.Operation, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).GetOperation[0:len((*c.CallOptions).GetOperation):len((*c.CallOptions).GetOperation)], opts...) var resp *longrunningpb.Operation err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.operationsClient.GetOperation, req, settings.GRPC, c.logger, "GetOperation") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *echoGRPCClient) DeleteOperation(ctx context.Context, req *longrunningpb.DeleteOperationRequest, opts ...gax.CallOption) error { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).DeleteOperation[0:len((*c.CallOptions).DeleteOperation):len((*c.CallOptions).DeleteOperation)], opts...) err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error _, err = executeRPC(ctx, c.operationsClient.DeleteOperation, req, settings.GRPC, c.logger, "DeleteOperation") return err }, opts...) return err } func (c *echoGRPCClient) CancelOperation(ctx context.Context, req *longrunningpb.CancelOperationRequest, opts ...gax.CallOption) error { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).CancelOperation[0:len((*c.CallOptions).CancelOperation):len((*c.CallOptions).CancelOperation)], opts...) err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error _, err = executeRPC(ctx, c.operationsClient.CancelOperation, req, settings.GRPC, c.logger, "CancelOperation") return err }, opts...) return err } // Echo this method simply echoes the request. This method showcases unary RPCs. func (c *echoRESTClient) Echo(ctx context.Context, req *genprotopb.EchoRequest, opts ...gax.CallOption) (*genprotopb.EchoResponse, error) { if req != nil && req.GetRequestId() == "" { req.RequestId = uuid.NewString() } if req != nil && req.OtherRequestId == nil { req.OtherRequestId = proto.String(uuid.NewString()) } m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/echo:echo") // Build HTTP headers from client and context metadata. routingHeaders := "" routingHeadersMap := make(map[string]string) if reg := regexp.MustCompile("(.*)"); reg.MatchString(req.GetHeader()) && len(url.QueryEscape(reg.FindStringSubmatch(req.GetHeader())[1])) > 0 { routingHeadersMap["header"] = url.QueryEscape(reg.FindStringSubmatch(req.GetHeader())[1]) } if reg := regexp.MustCompile("(?P.*)"); reg.MatchString(req.GetHeader()) && len(url.QueryEscape(reg.FindStringSubmatch(req.GetHeader())[1])) > 0 { routingHeadersMap["routing_id"] = url.QueryEscape(reg.FindStringSubmatch(req.GetHeader())[1]) } if reg := regexp.MustCompile("(?Pregions/[^/]+/zones/[^/]+(?:/.*)?)"); reg.MatchString(req.GetHeader()) && len(url.QueryEscape(reg.FindStringSubmatch(req.GetHeader())[1])) > 0 { routingHeadersMap["table_name"] = url.QueryEscape(reg.FindStringSubmatch(req.GetHeader())[1]) } if reg := regexp.MustCompile("(?Pprojects/[^/]+)(?:/.*)?"); reg.MatchString(req.GetHeader()) && len(url.QueryEscape(reg.FindStringSubmatch(req.GetHeader())[1])) > 0 { routingHeadersMap["super_id"] = url.QueryEscape(reg.FindStringSubmatch(req.GetHeader())[1]) } if reg := regexp.MustCompile("(?Pprojects/[^/]+/instances/[^/]+(?:/.*)?)"); reg.MatchString(req.GetHeader()) && len(url.QueryEscape(reg.FindStringSubmatch(req.GetHeader())[1])) > 0 { routingHeadersMap["table_name"] = url.QueryEscape(reg.FindStringSubmatch(req.GetHeader())[1]) } if reg := regexp.MustCompile("projects/[^/]+/(?Pinstances/[^/]+)(?:/.*)?"); reg.MatchString(req.GetHeader()) && len(url.QueryEscape(reg.FindStringSubmatch(req.GetHeader())[1])) > 0 { routingHeadersMap["instance_id"] = url.QueryEscape(reg.FindStringSubmatch(req.GetHeader())[1]) } if reg := regexp.MustCompile("(?P.*)"); reg.MatchString(req.GetOtherHeader()) && len(url.QueryEscape(reg.FindStringSubmatch(req.GetOtherHeader())[1])) > 0 { routingHeadersMap["baz"] = url.QueryEscape(reg.FindStringSubmatch(req.GetOtherHeader())[1]) } if reg := regexp.MustCompile("(?Pprojects/[^/]+)(?:/.*)?"); reg.MatchString(req.GetOtherHeader()) && len(url.QueryEscape(reg.FindStringSubmatch(req.GetOtherHeader())[1])) > 0 { routingHeadersMap["qux"] = url.QueryEscape(reg.FindStringSubmatch(req.GetOtherHeader())[1]) } for headerName, headerValue := range routingHeadersMap { routingHeaders = fmt.Sprintf("%s%s=%s&", routingHeaders, headerName, headerValue) } routingHeaders = strings.TrimSuffix(routingHeaders, "&") hds := []string{"x-goog-request-params", routingHeaders} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).Echo[0:len((*c.CallOptions).Echo):len((*c.CallOptions).Echo)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.EchoResponse{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "Echo") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // EchoErrorDetails this method returns error details in a repeated “google.protobuf.Any” // field. This method showcases handling errors thus encoded, particularly // over REST transport. Note that GAPICs only allow the type // “google.protobuf.Any” for field paths ending in “error.details”, and, at // run-time, the actual types for these fields must be one of the types in // google/rpc/error_details.proto. func (c *echoRESTClient) EchoErrorDetails(ctx context.Context, req *genprotopb.EchoErrorDetailsRequest, opts ...gax.CallOption) (*genprotopb.EchoErrorDetailsResponse, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/echo:error-details") // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).EchoErrorDetails[0:len((*c.CallOptions).EchoErrorDetails):len((*c.CallOptions).EchoErrorDetails)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.EchoErrorDetailsResponse{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "EchoErrorDetails") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // FailEchoWithDetails this method always fails with a gRPC “Aborted” error status that contains // multiple error details. These include one instance of each of the standard // ones in error_details.proto // (https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto (at https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto)) // plus a custom, Showcase-defined PoetryError. The intent of this RPC is to // verify that GAPICs can process these various error details and surface them // to the user in an idiomatic form. func (c *echoRESTClient) FailEchoWithDetails(ctx context.Context, req *genprotopb.FailEchoWithDetailsRequest, opts ...gax.CallOption) (*genprotopb.FailEchoWithDetailsResponse, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/echo:failWithDetails") // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).FailEchoWithDetails[0:len((*c.CallOptions).FailEchoWithDetails):len((*c.CallOptions).FailEchoWithDetails)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.FailEchoWithDetailsResponse{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "FailEchoWithDetails") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // Expand this method splits the given content into words and will pass each word back // through the stream. This method showcases server-side streaming RPCs. func (c *echoRESTClient) Expand(ctx context.Context, req *genprotopb.ExpandRequest, opts ...gax.CallOption) (genprotopb.Echo_ExpandClient, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/echo:expand") // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) var streamClient *expandRESTStreamClient e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers httpRsp, err := executeStreamingHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "Expand") if err != nil { return err } streamClient = &expandRESTStreamClient{ ctx: ctx, md: metadata.MD(httpRsp.Header), stream: gax.NewProtoJSONStreamReader(httpRsp.Body, (&genprotopb.EchoResponse{}).ProtoReflect().Type()), } return nil }, opts...) return streamClient, e } // expandRESTStreamClient is the stream client used to consume the server stream created by // the REST implementation of Expand. type expandRESTStreamClient struct { ctx context.Context md metadata.MD stream *gax.ProtoJSONStream } func (c *expandRESTStreamClient) Recv() (*genprotopb.EchoResponse, error) { if err := c.ctx.Err(); err != nil { defer c.stream.Close() return nil, err } msg, err := c.stream.Recv() if err != nil { defer c.stream.Close() return nil, err } res := msg.(*genprotopb.EchoResponse) return res, nil } func (c *expandRESTStreamClient) Header() (metadata.MD, error) { return c.md, nil } func (c *expandRESTStreamClient) Trailer() metadata.MD { return c.md } func (c *expandRESTStreamClient) CloseSend() error { // This is a no-op to fulfill the interface. return errors.New("this method is not implemented for a server-stream") } func (c *expandRESTStreamClient) Context() context.Context { return c.ctx } func (c *expandRESTStreamClient) SendMsg(m interface{}) error { // This is a no-op to fulfill the interface. return errors.New("this method is not implemented for a server-stream") } func (c *expandRESTStreamClient) RecvMsg(m interface{}) error { // This is a no-op to fulfill the interface. return errors.New("this method is not implemented, use Recv") } // Collect this method will collect the words given to it. When the stream is closed // by the client, this method will return the a concatenation of the strings // passed to it. This method showcases client-side streaming RPCs. // // This method is not supported for the REST transport. func (c *echoRESTClient) Collect(ctx context.Context, opts ...gax.CallOption) (genprotopb.Echo_CollectClient, error) { return nil, errors.New("Collect not yet supported for REST clients") } // Chat this method, upon receiving a request on the stream, will pass the same // content back on the stream. This method showcases bidirectional // streaming RPCs. // // This method is not supported for the REST transport. func (c *echoRESTClient) Chat(ctx context.Context, opts ...gax.CallOption) (genprotopb.Echo_ChatClient, error) { return nil, errors.New("Chat not yet supported for REST clients") } // PagedExpand this is similar to the Expand method but instead of returning a stream of // expanded words, this method returns a paged list of expanded words. func (c *echoRESTClient) PagedExpand(ctx context.Context, req *genprotopb.PagedExpandRequest, opts ...gax.CallOption) *EchoResponseIterator { it := &EchoResponseIterator{} req = proto.Clone(req).(*genprotopb.PagedExpandRequest) m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} it.InternalFetch = func(pageSize int, pageToken string) ([]*genprotopb.EchoResponse, string, error) { resp := &genprotopb.PagedExpandResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } jsonReq, err := m.Marshal(req) if err != nil { return nil, "", err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, "", err } baseUrl.Path += fmt.Sprintf("/v1beta1/echo:pagedExpand") // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "PagedExpand") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, "", e } it.Response = resp return resp.GetResponses(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } // PagedExpandLegacy this is similar to the PagedExpand except that it uses // max_results instead of page_size, as some legacy APIs still // do. New APIs should NOT use this pattern. func (c *echoRESTClient) PagedExpandLegacy(ctx context.Context, req *genprotopb.PagedExpandLegacyRequest, opts ...gax.CallOption) *EchoResponseIterator { it := &EchoResponseIterator{} req = proto.Clone(req).(*genprotopb.PagedExpandLegacyRequest) m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} it.InternalFetch = func(pageSize int, pageToken string) ([]*genprotopb.EchoResponse, string, error) { resp := &genprotopb.PagedExpandResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.MaxResults = math.MaxInt32 } else if pageSize != 0 { req.MaxResults = int32(pageSize) } jsonReq, err := m.Marshal(req) if err != nil { return nil, "", err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, "", err } baseUrl.Path += fmt.Sprintf("/v1beta1/echo:pagedExpandLegacy") // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "PagedExpandLegacy") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, "", e } it.Response = resp return resp.GetResponses(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetMaxResults()) it.pageInfo.Token = req.GetPageToken() return it } // PagedExpandLegacyMapped this method returns a map containing lists of words that appear in the input, keyed by their // initial character. The only words returned are the ones included in the current page, // as determined by page_token and page_size, which both refer to the word indices in the // input. This paging result consisting of a map of lists is a pattern used by some legacy // APIs. New APIs should NOT use this pattern. func (c *echoRESTClient) PagedExpandLegacyMapped(ctx context.Context, req *genprotopb.PagedExpandRequest, opts ...gax.CallOption) *PagedExpandResponseListPairIterator { it := &PagedExpandResponseListPairIterator{} req = proto.Clone(req).(*genprotopb.PagedExpandRequest) m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} it.InternalFetch = func(pageSize int, pageToken string) ([]PagedExpandResponseListPair, string, error) { resp := &genprotopb.PagedExpandLegacyMappedResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } jsonReq, err := m.Marshal(req) if err != nil { return nil, "", err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, "", err } baseUrl.Path += fmt.Sprintf("/v1beta1/echo:pagedExpandLegacyMapped") // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "PagedExpandLegacyMapped") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, "", e } it.Response = resp elems := make([]PagedExpandResponseListPair, 0, len(resp.GetAlphabetized())) for k, v := range resp.GetAlphabetized() { elems = append(elems, PagedExpandResponseListPair{k, v}) } sort.Slice(elems, func(i, j int) bool { return elems[i].Key < elems[j].Key }) return elems, resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } // Wait this method will wait for the requested amount of time and then return. // This method showcases how a client handles a request timeout. func (c *echoRESTClient) Wait(ctx context.Context, req *genprotopb.WaitRequest, opts ...gax.CallOption) (*WaitOperation, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/echo:wait") // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &longrunningpb.Operation{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "Wait") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } override := fmt.Sprintf("/v1beta1/%s", resp.GetName()) return &WaitOperation{ lro: longrunning.InternalNewOperation(*c.LROClient, resp), pollPath: override, }, nil } // Block this method will block (wait) for the requested amount of time // and then return the response or error. // This method showcases how a client handles delays or retries. func (c *echoRESTClient) Block(ctx context.Context, req *genprotopb.BlockRequest, opts ...gax.CallOption) (*genprotopb.BlockResponse, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/echo:block") // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).Block[0:len((*c.CallOptions).Block):len((*c.CallOptions).Block)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.BlockResponse{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "Block") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // ListLocations is a utility method from google.cloud.location.Locations. func (c *echoRESTClient) ListLocations(ctx context.Context, req *locationpb.ListLocationsRequest, opts ...gax.CallOption) *LocationIterator { it := &LocationIterator{} req = proto.Clone(req).(*locationpb.ListLocationsRequest) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} it.InternalFetch = func(pageSize int, pageToken string) ([]*locationpb.Location, string, error) { resp := &locationpb.ListLocationsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, "", err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v/locations", req.GetName()) params := url.Values{} if req.GetFilter() != "" { params.Add("filter", fmt.Sprintf("%v", req.GetFilter())) } if req.GetPageSize() != 0 { params.Add("pageSize", fmt.Sprintf("%v", req.GetPageSize())) } if req.GetPageToken() != "" { params.Add("pageToken", fmt.Sprintf("%v", req.GetPageToken())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "ListLocations") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, "", e } it.Response = resp return resp.GetLocations(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } // GetLocation is a utility method from google.cloud.location.Locations. func (c *echoRESTClient) GetLocation(ctx context.Context, req *locationpb.GetLocationRequest, opts ...gax.CallOption) (*locationpb.Location, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).GetLocation[0:len((*c.CallOptions).GetLocation):len((*c.CallOptions).GetLocation)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &locationpb.Location{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "GetLocation") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // SetIamPolicy is a utility method from google.iam.v1.IAMPolicy. func (c *echoRESTClient) SetIamPolicy(ctx context.Context, req *iampb.SetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:setIamPolicy", req.GetResource()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).SetIamPolicy[0:len((*c.CallOptions).SetIamPolicy):len((*c.CallOptions).SetIamPolicy)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &iampb.Policy{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "SetIamPolicy") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // GetIamPolicy is a utility method from google.iam.v1.IAMPolicy. func (c *echoRESTClient) GetIamPolicy(ctx context.Context, req *iampb.GetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:getIamPolicy", req.GetResource()) params := url.Values{} if req.GetOptions().GetRequestedPolicyVersion() != 0 { params.Add("options.requestedPolicyVersion", fmt.Sprintf("%v", req.GetOptions().GetRequestedPolicyVersion())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).GetIamPolicy[0:len((*c.CallOptions).GetIamPolicy):len((*c.CallOptions).GetIamPolicy)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &iampb.Policy{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "GetIamPolicy") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // TestIamPermissions is a utility method from google.iam.v1.IAMPolicy. func (c *echoRESTClient) TestIamPermissions(ctx context.Context, req *iampb.TestIamPermissionsRequest, opts ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:testIamPermissions", req.GetResource()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).TestIamPermissions[0:len((*c.CallOptions).TestIamPermissions):len((*c.CallOptions).TestIamPermissions)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &iampb.TestIamPermissionsResponse{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "TestIamPermissions") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // ListOperations is a utility method from google.longrunning.Operations. func (c *echoRESTClient) ListOperations(ctx context.Context, req *longrunningpb.ListOperationsRequest, opts ...gax.CallOption) *OperationIterator { it := &OperationIterator{} req = proto.Clone(req).(*longrunningpb.ListOperationsRequest) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} it.InternalFetch = func(pageSize int, pageToken string) ([]*longrunningpb.Operation, string, error) { resp := &longrunningpb.ListOperationsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, "", err } baseUrl.Path += fmt.Sprintf("/v1beta1/operations") params := url.Values{} if req.GetFilter() != "" { params.Add("filter", fmt.Sprintf("%v", req.GetFilter())) } if req.GetName() != "" { params.Add("name", fmt.Sprintf("%v", req.GetName())) } if req.GetPageSize() != 0 { params.Add("pageSize", fmt.Sprintf("%v", req.GetPageSize())) } if req.GetPageToken() != "" { params.Add("pageToken", fmt.Sprintf("%v", req.GetPageToken())) } if req.GetReturnPartialSuccess() { params.Add("returnPartialSuccess", fmt.Sprintf("%v", req.GetReturnPartialSuccess())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "ListOperations") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, "", e } it.Response = resp return resp.GetOperations(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } // GetOperation is a utility method from google.longrunning.Operations. func (c *echoRESTClient) GetOperation(ctx context.Context, req *longrunningpb.GetOperationRequest, opts ...gax.CallOption) (*longrunningpb.Operation, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).GetOperation[0:len((*c.CallOptions).GetOperation):len((*c.CallOptions).GetOperation)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &longrunningpb.Operation{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "GetOperation") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // DeleteOperation is a utility method from google.longrunning.Operations. func (c *echoRESTClient) DeleteOperation(ctx context.Context, req *longrunningpb.DeleteOperationRequest, opts ...gax.CallOption) error { baseUrl, err := url.Parse(c.endpoint) if err != nil { return err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) return gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("DELETE", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers _, err = executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "DeleteOperation") return err }, opts...) } // CancelOperation is a utility method from google.longrunning.Operations. func (c *echoRESTClient) CancelOperation(ctx context.Context, req *longrunningpb.CancelOperationRequest, opts ...gax.CallOption) error { baseUrl, err := url.Parse(c.endpoint) if err != nil { return err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:cancel", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) return gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers _, err = executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "CancelOperation") return err }, opts...) } // WaitOperation returns a new WaitOperation from a given name. // The name must be that of a previously created WaitOperation, possibly from a different process. func (c *echoGRPCClient) WaitOperation(name string) *WaitOperation { return &WaitOperation{ lro: longrunning.InternalNewOperation(*c.LROClient, &longrunningpb.Operation{Name: name}), } } // WaitOperation returns a new WaitOperation from a given name. // The name must be that of a previously created WaitOperation, possibly from a different process. func (c *echoRESTClient) WaitOperation(name string) *WaitOperation { override := fmt.Sprintf("/v1beta1/%s", name) return &WaitOperation{ lro: longrunning.InternalNewOperation(*c.LROClient, &longrunningpb.Operation{Name: name}), pollPath: override, } } ================================================ FILE: client/echo_client_example_go123_test.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go_gapic. DO NOT EDIT. //go:build go1.23 package client_test import ( "context" longrunningpb "cloud.google.com/go/longrunning/autogen/longrunningpb" client "github.com/googleapis/gapic-showcase/client" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" locationpb "google.golang.org/genproto/googleapis/cloud/location" ) func ExampleEchoClient_PagedExpand_all() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewEchoClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.PagedExpandRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#PagedExpandRequest. } for resp, err := range c.PagedExpand(ctx, req).All() { if err != nil { // TODO: Handle error and break/return/continue. Iteration will stop after any error. } // TODO: Use resp. _ = resp } } func ExampleEchoClient_PagedExpandLegacy_all() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewEchoClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.PagedExpandLegacyRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#PagedExpandLegacyRequest. } for resp, err := range c.PagedExpandLegacy(ctx, req).All() { if err != nil { // TODO: Handle error and break/return/continue. Iteration will stop after any error. } // TODO: Use resp. _ = resp } } func ExampleEchoClient_PagedExpandLegacyMapped_all() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewEchoClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.PagedExpandRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#PagedExpandRequest. } for resp, err := range c.PagedExpandLegacyMapped(ctx, req).All() { if err != nil { // TODO: Handle error and break/return/continue. Iteration will stop after any error. } // TODO: Use resp. _ = resp } } func ExampleEchoClient_ListLocations_all() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewEchoClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &locationpb.ListLocationsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/google.golang.org/genproto/googleapis/cloud/location#ListLocationsRequest. } for resp, err := range c.ListLocations(ctx, req).All() { if err != nil { // TODO: Handle error and break/return/continue. Iteration will stop after any error. } // TODO: Use resp. _ = resp } } func ExampleEchoClient_ListOperations_all() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewEchoClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.ListOperationsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#ListOperationsRequest. } for resp, err := range c.ListOperations(ctx, req).All() { if err != nil { // TODO: Handle error and break/return/continue. Iteration will stop after any error. } // TODO: Use resp. _ = resp } } ================================================ FILE: client/echo_client_example_test.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go_gapic. DO NOT EDIT. package client_test import ( "context" "io" iampb "cloud.google.com/go/iam/apiv1/iampb" longrunningpb "cloud.google.com/go/longrunning/autogen/longrunningpb" client "github.com/googleapis/gapic-showcase/client" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "google.golang.org/api/iterator" locationpb "google.golang.org/genproto/googleapis/cloud/location" ) func ExampleNewEchoClient() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewEchoClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() // TODO: Use client. _ = c } func ExampleNewEchoRESTClient() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewEchoRESTClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() // TODO: Use client. _ = c } func ExampleEchoClient_Block() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewEchoClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.BlockRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#BlockRequest. } resp, err := c.Block(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleEchoClient_Chat() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewEchoClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() stream, err := c.Chat(ctx) if err != nil { // TODO: Handle error. } go func() { reqs := []*genprotopb.EchoRequest{ // TODO: Create requests. } for _, req := range reqs { if err := stream.Send(req); err != nil { // TODO: Handle error. } } stream.CloseSend() }() for { resp, err := stream.Recv() if err == io.EOF { break } if err != nil { // TODO: handle error. } // TODO: Use resp. _ = resp } } func ExampleEchoClient_Echo() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewEchoClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.EchoRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#EchoRequest. } resp, err := c.Echo(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleEchoClient_EchoErrorDetails() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewEchoClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.EchoErrorDetailsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#EchoErrorDetailsRequest. } resp, err := c.EchoErrorDetails(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleEchoClient_FailEchoWithDetails() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewEchoClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.FailEchoWithDetailsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#FailEchoWithDetailsRequest. } resp, err := c.FailEchoWithDetails(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleEchoClient_PagedExpand() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewEchoClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.PagedExpandRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#PagedExpandRequest. } it := c.PagedExpand(ctx, req) for { resp, err := it.Next() if err == iterator.Done { break } if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp // If you need to access the underlying RPC response, // you can do so by casting the `Response` as below. // Otherwise, remove this line. Only populated after // first call to Next(). Not safe for concurrent access. _ = it.Response.(*genprotopb.PagedExpandResponse) } } func ExampleEchoClient_PagedExpandLegacy() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewEchoClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.PagedExpandLegacyRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#PagedExpandLegacyRequest. } it := c.PagedExpandLegacy(ctx, req) for { resp, err := it.Next() if err == iterator.Done { break } if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp // If you need to access the underlying RPC response, // you can do so by casting the `Response` as below. // Otherwise, remove this line. Only populated after // first call to Next(). Not safe for concurrent access. _ = it.Response.(*genprotopb.PagedExpandResponse) } } func ExampleEchoClient_PagedExpandLegacyMapped() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewEchoClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.PagedExpandRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#PagedExpandRequest. } it := c.PagedExpandLegacyMapped(ctx, req) for { resp, err := it.Next() if err == iterator.Done { break } if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp // If you need to access the underlying RPC response, // you can do so by casting the `Response` as below. // Otherwise, remove this line. Only populated after // first call to Next(). Not safe for concurrent access. _ = it.Response.(*genprotopb.PagedExpandLegacyMappedResponse) } } func ExampleEchoClient_Wait() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewEchoClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.WaitRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#WaitRequest. } op, err := c.Wait(ctx, req) if err != nil { // TODO: Handle error. } resp, err := op.Wait(ctx) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleEchoClient_ListLocations() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewEchoClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &locationpb.ListLocationsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/google.golang.org/genproto/googleapis/cloud/location#ListLocationsRequest. } it := c.ListLocations(ctx, req) for { resp, err := it.Next() if err == iterator.Done { break } if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp // If you need to access the underlying RPC response, // you can do so by casting the `Response` as below. // Otherwise, remove this line. Only populated after // first call to Next(). Not safe for concurrent access. _ = it.Response.(*locationpb.ListLocationsResponse) } } func ExampleEchoClient_GetLocation() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewEchoClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &locationpb.GetLocationRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/google.golang.org/genproto/googleapis/cloud/location#GetLocationRequest. } resp, err := c.GetLocation(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleEchoClient_SetIamPolicy() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewEchoClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &iampb.SetIamPolicyRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/iam/apiv1/iampb#SetIamPolicyRequest. } resp, err := c.SetIamPolicy(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleEchoClient_GetIamPolicy() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewEchoClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &iampb.GetIamPolicyRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/iam/apiv1/iampb#GetIamPolicyRequest. } resp, err := c.GetIamPolicy(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleEchoClient_TestIamPermissions() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewEchoClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &iampb.TestIamPermissionsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/iam/apiv1/iampb#TestIamPermissionsRequest. } resp, err := c.TestIamPermissions(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleEchoClient_ListOperations() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewEchoClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.ListOperationsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#ListOperationsRequest. } it := c.ListOperations(ctx, req) for { resp, err := it.Next() if err == iterator.Done { break } if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp // If you need to access the underlying RPC response, // you can do so by casting the `Response` as below. // Otherwise, remove this line. Only populated after // first call to Next(). Not safe for concurrent access. _ = it.Response.(*longrunningpb.ListOperationsResponse) } } func ExampleEchoClient_GetOperation() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewEchoClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.GetOperationRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#GetOperationRequest. } resp, err := c.GetOperation(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleEchoClient_DeleteOperation() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewEchoClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.DeleteOperationRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#DeleteOperationRequest. } err = c.DeleteOperation(ctx, req) if err != nil { // TODO: Handle error. } } func ExampleEchoClient_CancelOperation() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewEchoClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.CancelOperationRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#CancelOperationRequest. } err = c.CancelOperation(ctx, req) if err != nil { // TODO: Handle error. } } ================================================ FILE: client/gapic_metadata.json ================================================ { "schema": "1.0", "comment": "This file maps proto services/RPCs to the corresponding library clients/methods.", "language": "go", "protoPackage": "google.showcase.v1beta1", "libraryPackage": "github.com/googleapis/gapic-showcase/client", "services": { "Compliance": { "clients": { "grpc": { "libraryClient": "ComplianceClient", "rpcs": { "CancelOperation": { "methods": [ "CancelOperation" ] }, "DeleteOperation": { "methods": [ "DeleteOperation" ] }, "GetEnum": { "methods": [ "GetEnum" ] }, "GetIamPolicy": { "methods": [ "GetIamPolicy" ] }, "GetLocation": { "methods": [ "GetLocation" ] }, "GetOperation": { "methods": [ "GetOperation" ] }, "ListLocations": { "methods": [ "ListLocations" ] }, "ListOperations": { "methods": [ "ListOperations" ] }, "RepeatDataBody": { "methods": [ "RepeatDataBody" ] }, "RepeatDataBodyInfo": { "methods": [ "RepeatDataBodyInfo" ] }, "RepeatDataBodyPatch": { "methods": [ "RepeatDataBodyPatch" ] }, "RepeatDataBodyPut": { "methods": [ "RepeatDataBodyPut" ] }, "RepeatDataPathResource": { "methods": [ "RepeatDataPathResource" ] }, "RepeatDataPathTrailingResource": { "methods": [ "RepeatDataPathTrailingResource" ] }, "RepeatDataQuery": { "methods": [ "RepeatDataQuery" ] }, "RepeatDataSimplePath": { "methods": [ "RepeatDataSimplePath" ] }, "SetIamPolicy": { "methods": [ "SetIamPolicy" ] }, "TestIamPermissions": { "methods": [ "TestIamPermissions" ] }, "VerifyEnum": { "methods": [ "VerifyEnum" ] } } }, "rest": { "libraryClient": "ComplianceClient", "rpcs": { "CancelOperation": { "methods": [ "CancelOperation" ] }, "DeleteOperation": { "methods": [ "DeleteOperation" ] }, "GetEnum": { "methods": [ "GetEnum" ] }, "GetIamPolicy": { "methods": [ "GetIamPolicy" ] }, "GetLocation": { "methods": [ "GetLocation" ] }, "GetOperation": { "methods": [ "GetOperation" ] }, "ListLocations": { "methods": [ "ListLocations" ] }, "ListOperations": { "methods": [ "ListOperations" ] }, "RepeatDataBody": { "methods": [ "RepeatDataBody" ] }, "RepeatDataBodyInfo": { "methods": [ "RepeatDataBodyInfo" ] }, "RepeatDataBodyPatch": { "methods": [ "RepeatDataBodyPatch" ] }, "RepeatDataBodyPut": { "methods": [ "RepeatDataBodyPut" ] }, "RepeatDataPathResource": { "methods": [ "RepeatDataPathResource" ] }, "RepeatDataPathTrailingResource": { "methods": [ "RepeatDataPathTrailingResource" ] }, "RepeatDataQuery": { "methods": [ "RepeatDataQuery" ] }, "RepeatDataSimplePath": { "methods": [ "RepeatDataSimplePath" ] }, "SetIamPolicy": { "methods": [ "SetIamPolicy" ] }, "TestIamPermissions": { "methods": [ "TestIamPermissions" ] }, "VerifyEnum": { "methods": [ "VerifyEnum" ] } } } } }, "Echo": { "clients": { "grpc": { "libraryClient": "EchoClient", "rpcs": { "Block": { "methods": [ "Block" ] }, "CancelOperation": { "methods": [ "CancelOperation" ] }, "Chat": { "methods": [ "Chat" ] }, "Collect": { "methods": [ "Collect" ] }, "DeleteOperation": { "methods": [ "DeleteOperation" ] }, "Echo": { "methods": [ "Echo" ] }, "EchoErrorDetails": { "methods": [ "EchoErrorDetails" ] }, "Expand": { "methods": [ "Expand" ] }, "FailEchoWithDetails": { "methods": [ "FailEchoWithDetails" ] }, "GetIamPolicy": { "methods": [ "GetIamPolicy" ] }, "GetLocation": { "methods": [ "GetLocation" ] }, "GetOperation": { "methods": [ "GetOperation" ] }, "ListLocations": { "methods": [ "ListLocations" ] }, "ListOperations": { "methods": [ "ListOperations" ] }, "PagedExpand": { "methods": [ "PagedExpand" ] }, "PagedExpandLegacy": { "methods": [ "PagedExpandLegacy" ] }, "PagedExpandLegacyMapped": { "methods": [ "PagedExpandLegacyMapped" ] }, "SetIamPolicy": { "methods": [ "SetIamPolicy" ] }, "TestIamPermissions": { "methods": [ "TestIamPermissions" ] }, "Wait": { "methods": [ "Wait" ] } } }, "rest": { "libraryClient": "EchoClient", "rpcs": { "Block": { "methods": [ "Block" ] }, "CancelOperation": { "methods": [ "CancelOperation" ] }, "Chat": { "methods": [ "Chat" ] }, "Collect": { "methods": [ "Collect" ] }, "DeleteOperation": { "methods": [ "DeleteOperation" ] }, "Echo": { "methods": [ "Echo" ] }, "EchoErrorDetails": { "methods": [ "EchoErrorDetails" ] }, "Expand": { "methods": [ "Expand" ] }, "FailEchoWithDetails": { "methods": [ "FailEchoWithDetails" ] }, "GetIamPolicy": { "methods": [ "GetIamPolicy" ] }, "GetLocation": { "methods": [ "GetLocation" ] }, "GetOperation": { "methods": [ "GetOperation" ] }, "ListLocations": { "methods": [ "ListLocations" ] }, "ListOperations": { "methods": [ "ListOperations" ] }, "PagedExpand": { "methods": [ "PagedExpand" ] }, "PagedExpandLegacy": { "methods": [ "PagedExpandLegacy" ] }, "PagedExpandLegacyMapped": { "methods": [ "PagedExpandLegacyMapped" ] }, "SetIamPolicy": { "methods": [ "SetIamPolicy" ] }, "TestIamPermissions": { "methods": [ "TestIamPermissions" ] }, "Wait": { "methods": [ "Wait" ] } } } }, "apiVersion": "v1_20240408" }, "Identity": { "clients": { "grpc": { "libraryClient": "IdentityClient", "rpcs": { "CancelOperation": { "methods": [ "CancelOperation" ] }, "CreateUser": { "methods": [ "CreateUser" ] }, "DeleteOperation": { "methods": [ "DeleteOperation" ] }, "DeleteUser": { "methods": [ "DeleteUser" ] }, "GetIamPolicy": { "methods": [ "GetIamPolicy" ] }, "GetLocation": { "methods": [ "GetLocation" ] }, "GetOperation": { "methods": [ "GetOperation" ] }, "GetUser": { "methods": [ "GetUser" ] }, "ListLocations": { "methods": [ "ListLocations" ] }, "ListOperations": { "methods": [ "ListOperations" ] }, "ListUsers": { "methods": [ "ListUsers" ] }, "SetIamPolicy": { "methods": [ "SetIamPolicy" ] }, "TestIamPermissions": { "methods": [ "TestIamPermissions" ] }, "UpdateUser": { "methods": [ "UpdateUser" ] } } }, "rest": { "libraryClient": "IdentityClient", "rpcs": { "CancelOperation": { "methods": [ "CancelOperation" ] }, "CreateUser": { "methods": [ "CreateUser" ] }, "DeleteOperation": { "methods": [ "DeleteOperation" ] }, "DeleteUser": { "methods": [ "DeleteUser" ] }, "GetIamPolicy": { "methods": [ "GetIamPolicy" ] }, "GetLocation": { "methods": [ "GetLocation" ] }, "GetOperation": { "methods": [ "GetOperation" ] }, "GetUser": { "methods": [ "GetUser" ] }, "ListLocations": { "methods": [ "ListLocations" ] }, "ListOperations": { "methods": [ "ListOperations" ] }, "ListUsers": { "methods": [ "ListUsers" ] }, "SetIamPolicy": { "methods": [ "SetIamPolicy" ] }, "TestIamPermissions": { "methods": [ "TestIamPermissions" ] }, "UpdateUser": { "methods": [ "UpdateUser" ] } } } } }, "Messaging": { "clients": { "grpc": { "libraryClient": "MessagingClient", "rpcs": { "CancelOperation": { "methods": [ "CancelOperation" ] }, "Connect": { "methods": [ "Connect" ] }, "CreateBlurb": { "methods": [ "CreateBlurb" ] }, "CreateRoom": { "methods": [ "CreateRoom" ] }, "DeleteBlurb": { "methods": [ "DeleteBlurb" ] }, "DeleteOperation": { "methods": [ "DeleteOperation" ] }, "DeleteRoom": { "methods": [ "DeleteRoom" ] }, "GetBlurb": { "methods": [ "GetBlurb" ] }, "GetIamPolicy": { "methods": [ "GetIamPolicy" ] }, "GetLocation": { "methods": [ "GetLocation" ] }, "GetOperation": { "methods": [ "GetOperation" ] }, "GetRoom": { "methods": [ "GetRoom" ] }, "ListBlurbs": { "methods": [ "ListBlurbs" ] }, "ListLocations": { "methods": [ "ListLocations" ] }, "ListOperations": { "methods": [ "ListOperations" ] }, "ListRooms": { "methods": [ "ListRooms" ] }, "SearchBlurbs": { "methods": [ "SearchBlurbs" ] }, "SendBlurbs": { "methods": [ "SendBlurbs" ] }, "SetIamPolicy": { "methods": [ "SetIamPolicy" ] }, "StreamBlurbs": { "methods": [ "StreamBlurbs" ] }, "TestIamPermissions": { "methods": [ "TestIamPermissions" ] }, "UpdateBlurb": { "methods": [ "UpdateBlurb" ] }, "UpdateRoom": { "methods": [ "UpdateRoom" ] } } }, "rest": { "libraryClient": "MessagingClient", "rpcs": { "CancelOperation": { "methods": [ "CancelOperation" ] }, "Connect": { "methods": [ "Connect" ] }, "CreateBlurb": { "methods": [ "CreateBlurb" ] }, "CreateRoom": { "methods": [ "CreateRoom" ] }, "DeleteBlurb": { "methods": [ "DeleteBlurb" ] }, "DeleteOperation": { "methods": [ "DeleteOperation" ] }, "DeleteRoom": { "methods": [ "DeleteRoom" ] }, "GetBlurb": { "methods": [ "GetBlurb" ] }, "GetIamPolicy": { "methods": [ "GetIamPolicy" ] }, "GetLocation": { "methods": [ "GetLocation" ] }, "GetOperation": { "methods": [ "GetOperation" ] }, "GetRoom": { "methods": [ "GetRoom" ] }, "ListBlurbs": { "methods": [ "ListBlurbs" ] }, "ListLocations": { "methods": [ "ListLocations" ] }, "ListOperations": { "methods": [ "ListOperations" ] }, "ListRooms": { "methods": [ "ListRooms" ] }, "SearchBlurbs": { "methods": [ "SearchBlurbs" ] }, "SendBlurbs": { "methods": [ "SendBlurbs" ] }, "SetIamPolicy": { "methods": [ "SetIamPolicy" ] }, "StreamBlurbs": { "methods": [ "StreamBlurbs" ] }, "TestIamPermissions": { "methods": [ "TestIamPermissions" ] }, "UpdateBlurb": { "methods": [ "UpdateBlurb" ] }, "UpdateRoom": { "methods": [ "UpdateRoom" ] } } } } }, "SequenceService": { "clients": { "grpc": { "libraryClient": "SequenceClient", "rpcs": { "AttemptSequence": { "methods": [ "AttemptSequence" ] }, "AttemptStreamingSequence": { "methods": [ "AttemptStreamingSequence" ] }, "CancelOperation": { "methods": [ "CancelOperation" ] }, "CreateSequence": { "methods": [ "CreateSequence" ] }, "CreateStreamingSequence": { "methods": [ "CreateStreamingSequence" ] }, "DeleteOperation": { "methods": [ "DeleteOperation" ] }, "GetIamPolicy": { "methods": [ "GetIamPolicy" ] }, "GetLocation": { "methods": [ "GetLocation" ] }, "GetOperation": { "methods": [ "GetOperation" ] }, "GetSequenceReport": { "methods": [ "GetSequenceReport" ] }, "GetStreamingSequenceReport": { "methods": [ "GetStreamingSequenceReport" ] }, "ListLocations": { "methods": [ "ListLocations" ] }, "ListOperations": { "methods": [ "ListOperations" ] }, "SetIamPolicy": { "methods": [ "SetIamPolicy" ] }, "TestIamPermissions": { "methods": [ "TestIamPermissions" ] } } }, "rest": { "libraryClient": "SequenceClient", "rpcs": { "AttemptSequence": { "methods": [ "AttemptSequence" ] }, "AttemptStreamingSequence": { "methods": [ "AttemptStreamingSequence" ] }, "CancelOperation": { "methods": [ "CancelOperation" ] }, "CreateSequence": { "methods": [ "CreateSequence" ] }, "CreateStreamingSequence": { "methods": [ "CreateStreamingSequence" ] }, "DeleteOperation": { "methods": [ "DeleteOperation" ] }, "GetIamPolicy": { "methods": [ "GetIamPolicy" ] }, "GetLocation": { "methods": [ "GetLocation" ] }, "GetOperation": { "methods": [ "GetOperation" ] }, "GetSequenceReport": { "methods": [ "GetSequenceReport" ] }, "GetStreamingSequenceReport": { "methods": [ "GetStreamingSequenceReport" ] }, "ListLocations": { "methods": [ "ListLocations" ] }, "ListOperations": { "methods": [ "ListOperations" ] }, "SetIamPolicy": { "methods": [ "SetIamPolicy" ] }, "TestIamPermissions": { "methods": [ "TestIamPermissions" ] } } } } }, "Testing": { "clients": { "grpc": { "libraryClient": "TestingClient", "rpcs": { "CancelOperation": { "methods": [ "CancelOperation" ] }, "CreateSession": { "methods": [ "CreateSession" ] }, "DeleteOperation": { "methods": [ "DeleteOperation" ] }, "DeleteSession": { "methods": [ "DeleteSession" ] }, "DeleteTest": { "methods": [ "DeleteTest" ] }, "GetIamPolicy": { "methods": [ "GetIamPolicy" ] }, "GetLocation": { "methods": [ "GetLocation" ] }, "GetOperation": { "methods": [ "GetOperation" ] }, "GetSession": { "methods": [ "GetSession" ] }, "ListLocations": { "methods": [ "ListLocations" ] }, "ListOperations": { "methods": [ "ListOperations" ] }, "ListSessions": { "methods": [ "ListSessions" ] }, "ListTests": { "methods": [ "ListTests" ] }, "ReportSession": { "methods": [ "ReportSession" ] }, "SetIamPolicy": { "methods": [ "SetIamPolicy" ] }, "TestIamPermissions": { "methods": [ "TestIamPermissions" ] }, "VerifyTest": { "methods": [ "VerifyTest" ] } } }, "rest": { "libraryClient": "TestingClient", "rpcs": { "CancelOperation": { "methods": [ "CancelOperation" ] }, "CreateSession": { "methods": [ "CreateSession" ] }, "DeleteOperation": { "methods": [ "DeleteOperation" ] }, "DeleteSession": { "methods": [ "DeleteSession" ] }, "DeleteTest": { "methods": [ "DeleteTest" ] }, "GetIamPolicy": { "methods": [ "GetIamPolicy" ] }, "GetLocation": { "methods": [ "GetLocation" ] }, "GetOperation": { "methods": [ "GetOperation" ] }, "GetSession": { "methods": [ "GetSession" ] }, "ListLocations": { "methods": [ "ListLocations" ] }, "ListOperations": { "methods": [ "ListOperations" ] }, "ListSessions": { "methods": [ "ListSessions" ] }, "ListTests": { "methods": [ "ListTests" ] }, "ReportSession": { "methods": [ "ReportSession" ] }, "SetIamPolicy": { "methods": [ "SetIamPolicy" ] }, "TestIamPermissions": { "methods": [ "TestIamPermissions" ] }, "VerifyTest": { "methods": [ "VerifyTest" ] } } } } } } } ================================================ FILE: client/helpers.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go_gapic. DO NOT EDIT. package client import ( "context" "fmt" "io" "log/slog" "net/http" "github.com/googleapis/gax-go/v2/internallog" "github.com/googleapis/gax-go/v2/internallog/grpclog" "google.golang.org/api/googleapi" "google.golang.org/api/option" "google.golang.org/grpc" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/runtime/protoimpl" ) const serviceName = "showcase.googleapis.com" var protoVersion = fmt.Sprintf("1.%d", protoimpl.MaxVersion) // For more information on implementing a client constructor hook, see // https://github.com/googleapis/google-cloud-go/wiki/Customizing-constructors. type clientHookParams struct{} type clientHook func(context.Context, clientHookParams) ([]option.ClientOption, error) var versionClient string func getVersionClient() string { if versionClient == "" { return "UNKNOWN" } return versionClient } // DefaultAuthScopes reports the default set of authentication scopes to use with this package. func DefaultAuthScopes() []string { return []string{} } func executeHTTPRequestWithResponse(ctx context.Context, client *http.Client, req *http.Request, logger *slog.Logger, body []byte, rpc string) ([]byte, *http.Response, error) { logger.DebugContext(ctx, "api request", "serviceName", serviceName, "rpcName", rpc, "request", internallog.HTTPRequest(req, body)) resp, err := client.Do(req) if err != nil { return nil, nil, err } defer resp.Body.Close() buf, err := io.ReadAll(resp.Body) if err != nil { return nil, nil, err } logger.DebugContext(ctx, "api response", "serviceName", serviceName, "rpcName", rpc, "response", internallog.HTTPResponse(resp, buf)) if err = googleapi.CheckResponseWithBody(resp, buf); err != nil { return nil, nil, err } return buf, resp, nil } func executeHTTPRequest(ctx context.Context, client *http.Client, req *http.Request, logger *slog.Logger, body []byte, rpc string) ([]byte, error) { buf, _, err := executeHTTPRequestWithResponse(ctx, client, req, logger, body, rpc) return buf, err } func executeStreamingHTTPRequest(ctx context.Context, client *http.Client, req *http.Request, logger *slog.Logger, body []byte, rpc string) (*http.Response, error) { logger.DebugContext(ctx, "api request", "serviceName", serviceName, "rpcName", rpc, "request", internallog.HTTPRequest(req, body)) resp, err := client.Do(req) if err != nil { return nil, err } logger.DebugContext(ctx, "api response", "serviceName", serviceName, "rpcName", rpc, "response", internallog.HTTPResponse(resp, nil)) if err = googleapi.CheckResponse(resp); err != nil { return nil, err } return resp, nil } func executeRPC[I proto.Message, O proto.Message](ctx context.Context, fn func(context.Context, I, ...grpc.CallOption) (O, error), req I, opts []grpc.CallOption, logger *slog.Logger, rpc string) (O, error) { var zero O logger.DebugContext(ctx, "api request", "serviceName", serviceName, "rpcName", rpc, "request", grpclog.ProtoMessageRequest(ctx, req)) resp, err := fn(ctx, req, opts...) if err != nil { return zero, err } logger.DebugContext(ctx, "api response", "serviceName", serviceName, "rpcName", rpc, "response", grpclog.ProtoMessageResponse(resp)) return resp, err } ================================================ FILE: client/identity_client.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go_gapic. DO NOT EDIT. package client import ( "bytes" "context" "fmt" "log/slog" "math" "net/http" "net/url" "time" iampb "cloud.google.com/go/iam/apiv1/iampb" longrunningpb "cloud.google.com/go/longrunning/autogen/longrunningpb" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" gax "github.com/googleapis/gax-go/v2" "google.golang.org/api/iterator" "google.golang.org/api/option" "google.golang.org/api/option/internaloption" gtransport "google.golang.org/api/transport/grpc" httptransport "google.golang.org/api/transport/http" locationpb "google.golang.org/genproto/googleapis/cloud/location" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" ) var newIdentityClientHook clientHook // IdentityCallOptions contains the retry settings for each method of IdentityClient. type IdentityCallOptions struct { CreateUser []gax.CallOption GetUser []gax.CallOption UpdateUser []gax.CallOption DeleteUser []gax.CallOption ListUsers []gax.CallOption ListLocations []gax.CallOption GetLocation []gax.CallOption SetIamPolicy []gax.CallOption GetIamPolicy []gax.CallOption TestIamPermissions []gax.CallOption ListOperations []gax.CallOption GetOperation []gax.CallOption DeleteOperation []gax.CallOption CancelOperation []gax.CallOption } func defaultIdentityGRPCClientOptions() []option.ClientOption { return []option.ClientOption{ internaloption.WithDefaultEndpoint("localhost:7469"), internaloption.WithDefaultEndpointTemplate("localhost:7469"), internaloption.WithDefaultMTLSEndpoint("localhost:7469"), internaloption.WithDefaultUniverseDomain("googleapis.com"), internaloption.WithDefaultAudience("https://localhost/"), internaloption.WithDefaultScopes(DefaultAuthScopes()...), internaloption.EnableJwtWithScope(), internaloption.EnableNewAuthLibrary(), option.WithGRPCDialOption(grpc.WithDefaultCallOptions( grpc.MaxCallRecvMsgSize(math.MaxInt32))), } } func defaultIdentityCallOptions() *IdentityCallOptions { return &IdentityCallOptions{ CreateUser: []gax.CallOption{}, GetUser: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), gax.WithRetry(func() gax.Retryer { return gax.OnCodes([]codes.Code{ codes.Unavailable, codes.Unknown, }, gax.Backoff{ Initial: 200 * time.Millisecond, Max: 3000 * time.Millisecond, Multiplier: 2.00, }) }), }, UpdateUser: []gax.CallOption{}, DeleteUser: []gax.CallOption{}, ListUsers: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), gax.WithRetry(func() gax.Retryer { return gax.OnCodes([]codes.Code{ codes.Unavailable, codes.Unknown, }, gax.Backoff{ Initial: 200 * time.Millisecond, Max: 3000 * time.Millisecond, Multiplier: 2.00, }) }), }, ListLocations: []gax.CallOption{}, GetLocation: []gax.CallOption{}, SetIamPolicy: []gax.CallOption{}, GetIamPolicy: []gax.CallOption{}, TestIamPermissions: []gax.CallOption{}, ListOperations: []gax.CallOption{}, GetOperation: []gax.CallOption{}, DeleteOperation: []gax.CallOption{}, CancelOperation: []gax.CallOption{}, } } func defaultIdentityRESTCallOptions() *IdentityCallOptions { return &IdentityCallOptions{ CreateUser: []gax.CallOption{}, GetUser: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), gax.WithRetry(func() gax.Retryer { return gax.OnHTTPCodes(gax.Backoff{ Initial: 200 * time.Millisecond, Max: 3000 * time.Millisecond, Multiplier: 2.00, }, http.StatusServiceUnavailable, http.StatusInternalServerError) }), }, UpdateUser: []gax.CallOption{}, DeleteUser: []gax.CallOption{}, ListUsers: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), gax.WithRetry(func() gax.Retryer { return gax.OnHTTPCodes(gax.Backoff{ Initial: 200 * time.Millisecond, Max: 3000 * time.Millisecond, Multiplier: 2.00, }, http.StatusServiceUnavailable, http.StatusInternalServerError) }), }, ListLocations: []gax.CallOption{}, GetLocation: []gax.CallOption{}, SetIamPolicy: []gax.CallOption{}, GetIamPolicy: []gax.CallOption{}, TestIamPermissions: []gax.CallOption{}, ListOperations: []gax.CallOption{}, GetOperation: []gax.CallOption{}, DeleteOperation: []gax.CallOption{}, CancelOperation: []gax.CallOption{}, } } // internalIdentityClient is an interface that defines the methods available from Client Libraries Showcase API. type internalIdentityClient interface { Close() error setGoogleClientInfo(...string) Connection() *grpc.ClientConn CreateUser(context.Context, *genprotopb.CreateUserRequest, ...gax.CallOption) (*genprotopb.User, error) GetUser(context.Context, *genprotopb.GetUserRequest, ...gax.CallOption) (*genprotopb.User, error) UpdateUser(context.Context, *genprotopb.UpdateUserRequest, ...gax.CallOption) (*genprotopb.User, error) DeleteUser(context.Context, *genprotopb.DeleteUserRequest, ...gax.CallOption) error ListUsers(context.Context, *genprotopb.ListUsersRequest, ...gax.CallOption) *UserIterator ListLocations(context.Context, *locationpb.ListLocationsRequest, ...gax.CallOption) *LocationIterator GetLocation(context.Context, *locationpb.GetLocationRequest, ...gax.CallOption) (*locationpb.Location, error) SetIamPolicy(context.Context, *iampb.SetIamPolicyRequest, ...gax.CallOption) (*iampb.Policy, error) GetIamPolicy(context.Context, *iampb.GetIamPolicyRequest, ...gax.CallOption) (*iampb.Policy, error) TestIamPermissions(context.Context, *iampb.TestIamPermissionsRequest, ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error) ListOperations(context.Context, *longrunningpb.ListOperationsRequest, ...gax.CallOption) *OperationIterator GetOperation(context.Context, *longrunningpb.GetOperationRequest, ...gax.CallOption) (*longrunningpb.Operation, error) DeleteOperation(context.Context, *longrunningpb.DeleteOperationRequest, ...gax.CallOption) error CancelOperation(context.Context, *longrunningpb.CancelOperationRequest, ...gax.CallOption) error } // IdentityClient is a client for interacting with Client Libraries Showcase API. // Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls. // // A simple identity service. type IdentityClient struct { // The internal transport-dependent client. internalClient internalIdentityClient // The call options for this service. CallOptions *IdentityCallOptions } // Wrapper methods routed to the internal client. // Close closes the connection to the API service. The user should invoke this when // the client is no longer required. func (c *IdentityClient) Close() error { return c.internalClient.Close() } // setGoogleClientInfo sets the name and version of the application in // the `x-goog-api-client` header passed on each request. Intended for // use by Google-written clients. func (c *IdentityClient) setGoogleClientInfo(keyval ...string) { c.internalClient.setGoogleClientInfo(keyval...) } // Connection returns a connection to the API service. // // Deprecated: Connections are now pooled so this method does not always // return the same resource. func (c *IdentityClient) Connection() *grpc.ClientConn { return c.internalClient.Connection() } // CreateUser creates a user. func (c *IdentityClient) CreateUser(ctx context.Context, req *genprotopb.CreateUserRequest, opts ...gax.CallOption) (*genprotopb.User, error) { return c.internalClient.CreateUser(ctx, req, opts...) } // GetUser retrieves the User with the given uri. func (c *IdentityClient) GetUser(ctx context.Context, req *genprotopb.GetUserRequest, opts ...gax.CallOption) (*genprotopb.User, error) { return c.internalClient.GetUser(ctx, req, opts...) } // UpdateUser updates a user. func (c *IdentityClient) UpdateUser(ctx context.Context, req *genprotopb.UpdateUserRequest, opts ...gax.CallOption) (*genprotopb.User, error) { return c.internalClient.UpdateUser(ctx, req, opts...) } // DeleteUser deletes a user, their profile, and all of their authored messages. func (c *IdentityClient) DeleteUser(ctx context.Context, req *genprotopb.DeleteUserRequest, opts ...gax.CallOption) error { return c.internalClient.DeleteUser(ctx, req, opts...) } // ListUsers lists all users. func (c *IdentityClient) ListUsers(ctx context.Context, req *genprotopb.ListUsersRequest, opts ...gax.CallOption) *UserIterator { return c.internalClient.ListUsers(ctx, req, opts...) } // ListLocations is a utility method from google.cloud.location.Locations. func (c *IdentityClient) ListLocations(ctx context.Context, req *locationpb.ListLocationsRequest, opts ...gax.CallOption) *LocationIterator { return c.internalClient.ListLocations(ctx, req, opts...) } // GetLocation is a utility method from google.cloud.location.Locations. func (c *IdentityClient) GetLocation(ctx context.Context, req *locationpb.GetLocationRequest, opts ...gax.CallOption) (*locationpb.Location, error) { return c.internalClient.GetLocation(ctx, req, opts...) } // SetIamPolicy is a utility method from google.iam.v1.IAMPolicy. func (c *IdentityClient) SetIamPolicy(ctx context.Context, req *iampb.SetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { return c.internalClient.SetIamPolicy(ctx, req, opts...) } // GetIamPolicy is a utility method from google.iam.v1.IAMPolicy. func (c *IdentityClient) GetIamPolicy(ctx context.Context, req *iampb.GetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { return c.internalClient.GetIamPolicy(ctx, req, opts...) } // TestIamPermissions is a utility method from google.iam.v1.IAMPolicy. func (c *IdentityClient) TestIamPermissions(ctx context.Context, req *iampb.TestIamPermissionsRequest, opts ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error) { return c.internalClient.TestIamPermissions(ctx, req, opts...) } // ListOperations is a utility method from google.longrunning.Operations. func (c *IdentityClient) ListOperations(ctx context.Context, req *longrunningpb.ListOperationsRequest, opts ...gax.CallOption) *OperationIterator { return c.internalClient.ListOperations(ctx, req, opts...) } // GetOperation is a utility method from google.longrunning.Operations. func (c *IdentityClient) GetOperation(ctx context.Context, req *longrunningpb.GetOperationRequest, opts ...gax.CallOption) (*longrunningpb.Operation, error) { return c.internalClient.GetOperation(ctx, req, opts...) } // DeleteOperation is a utility method from google.longrunning.Operations. func (c *IdentityClient) DeleteOperation(ctx context.Context, req *longrunningpb.DeleteOperationRequest, opts ...gax.CallOption) error { return c.internalClient.DeleteOperation(ctx, req, opts...) } // CancelOperation is a utility method from google.longrunning.Operations. func (c *IdentityClient) CancelOperation(ctx context.Context, req *longrunningpb.CancelOperationRequest, opts ...gax.CallOption) error { return c.internalClient.CancelOperation(ctx, req, opts...) } // identityGRPCClient is a client for interacting with Client Libraries Showcase API over gRPC transport. // // Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls. type identityGRPCClient struct { // Connection pool of gRPC connections to the service. connPool gtransport.ConnPool // Points back to the CallOptions field of the containing IdentityClient CallOptions **IdentityCallOptions // The gRPC API client. identityClient genprotopb.IdentityClient operationsClient longrunningpb.OperationsClient iamPolicyClient iampb.IAMPolicyClient locationsClient locationpb.LocationsClient // The x-goog-* metadata to be sent with each request. xGoogHeaders []string logger *slog.Logger } // NewIdentityClient creates a new identity client based on gRPC. // The returned client must be Closed when it is done being used to clean up its underlying connections. // // A simple identity service. func NewIdentityClient(ctx context.Context, opts ...option.ClientOption) (*IdentityClient, error) { clientOpts := defaultIdentityGRPCClientOptions() if newIdentityClientHook != nil { hookOpts, err := newIdentityClientHook(ctx, clientHookParams{}) if err != nil { return nil, err } clientOpts = append(clientOpts, hookOpts...) } connPool, err := gtransport.DialPool(ctx, append(clientOpts, opts...)...) if err != nil { return nil, err } client := IdentityClient{CallOptions: defaultIdentityCallOptions()} c := &identityGRPCClient{ connPool: connPool, identityClient: genprotopb.NewIdentityClient(connPool), CallOptions: &client.CallOptions, logger: internaloption.GetLogger(opts), operationsClient: longrunningpb.NewOperationsClient(connPool), iamPolicyClient: iampb.NewIAMPolicyClient(connPool), locationsClient: locationpb.NewLocationsClient(connPool), } c.setGoogleClientInfo() client.internalClient = c return &client, nil } // Connection returns a connection to the API service. // // Deprecated: Connections are now pooled so this method does not always // return the same resource. func (c *identityGRPCClient) Connection() *grpc.ClientConn { return c.connPool.Conn() } // setGoogleClientInfo sets the name and version of the application in // the `x-goog-api-client` header passed on each request. Intended for // use by Google-written clients. func (c *identityGRPCClient) setGoogleClientInfo(keyval ...string) { kv := append([]string{"gl-go", gax.GoVersion}, keyval...) kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "grpc", grpc.Version, "pb", protoVersion) c.xGoogHeaders = []string{ "x-goog-api-client", gax.XGoogHeader(kv...), } } // Close closes the connection to the API service. The user should invoke this when // the client is no longer required. func (c *identityGRPCClient) Close() error { return c.connPool.Close() } // Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls. type identityRESTClient struct { // The http endpoint to connect to. endpoint string // The http client. httpClient *http.Client // The x-goog-* headers to be sent with each request. xGoogHeaders []string // Points back to the CallOptions field of the containing IdentityClient CallOptions **IdentityCallOptions logger *slog.Logger } // NewIdentityRESTClient creates a new identity rest client. // // A simple identity service. func NewIdentityRESTClient(ctx context.Context, opts ...option.ClientOption) (*IdentityClient, error) { clientOpts := append(defaultIdentityRESTClientOptions(), opts...) httpClient, endpoint, err := httptransport.NewClient(ctx, clientOpts...) if err != nil { return nil, err } callOpts := defaultIdentityRESTCallOptions() c := &identityRESTClient{ endpoint: endpoint, httpClient: httpClient, CallOptions: &callOpts, logger: internaloption.GetLogger(opts), } c.setGoogleClientInfo() return &IdentityClient{internalClient: c, CallOptions: callOpts}, nil } func defaultIdentityRESTClientOptions() []option.ClientOption { return []option.ClientOption{ internaloption.WithDefaultEndpoint("https://localhost:7469"), internaloption.WithDefaultEndpointTemplate("https://localhost:7469"), internaloption.WithDefaultMTLSEndpoint("https://localhost:7469"), internaloption.WithDefaultUniverseDomain("googleapis.com"), internaloption.WithDefaultAudience("https://localhost/"), internaloption.WithDefaultScopes(DefaultAuthScopes()...), internaloption.EnableNewAuthLibrary(), } } // setGoogleClientInfo sets the name and version of the application in // the `x-goog-api-client` header passed on each request. Intended for // use by Google-written clients. func (c *identityRESTClient) setGoogleClientInfo(keyval ...string) { kv := append([]string{"gl-go", gax.GoVersion}, keyval...) kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "rest", "UNKNOWN", "pb", protoVersion) c.xGoogHeaders = []string{ "x-goog-api-client", gax.XGoogHeader(kv...), } } // Close closes the connection to the API service. The user should invoke this when // the client is no longer required. func (c *identityRESTClient) Close() error { // Replace httpClient with nil to force cleanup. c.httpClient = nil return nil } // Connection returns a connection to the API service. // // Deprecated: This method always returns nil. func (c *identityRESTClient) Connection() *grpc.ClientConn { return nil } func (c *identityGRPCClient) CreateUser(ctx context.Context, req *genprotopb.CreateUserRequest, opts ...gax.CallOption) (*genprotopb.User, error) { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).CreateUser[0:len((*c.CallOptions).CreateUser):len((*c.CallOptions).CreateUser)], opts...) var resp *genprotopb.User err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.identityClient.CreateUser, req, settings.GRPC, c.logger, "CreateUser") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *identityGRPCClient) GetUser(ctx context.Context, req *genprotopb.GetUserRequest, opts ...gax.CallOption) (*genprotopb.User, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).GetUser[0:len((*c.CallOptions).GetUser):len((*c.CallOptions).GetUser)], opts...) var resp *genprotopb.User err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.identityClient.GetUser, req, settings.GRPC, c.logger, "GetUser") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *identityGRPCClient) UpdateUser(ctx context.Context, req *genprotopb.UpdateUserRequest, opts ...gax.CallOption) (*genprotopb.User, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "user.name", url.QueryEscape(req.GetUser().GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).UpdateUser[0:len((*c.CallOptions).UpdateUser):len((*c.CallOptions).UpdateUser)], opts...) var resp *genprotopb.User err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.identityClient.UpdateUser, req, settings.GRPC, c.logger, "UpdateUser") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *identityGRPCClient) DeleteUser(ctx context.Context, req *genprotopb.DeleteUserRequest, opts ...gax.CallOption) error { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).DeleteUser[0:len((*c.CallOptions).DeleteUser):len((*c.CallOptions).DeleteUser)], opts...) err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error _, err = executeRPC(ctx, c.identityClient.DeleteUser, req, settings.GRPC, c.logger, "DeleteUser") return err }, opts...) return err } func (c *identityGRPCClient) ListUsers(ctx context.Context, req *genprotopb.ListUsersRequest, opts ...gax.CallOption) *UserIterator { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).ListUsers[0:len((*c.CallOptions).ListUsers):len((*c.CallOptions).ListUsers)], opts...) it := &UserIterator{} req = proto.Clone(req).(*genprotopb.ListUsersRequest) it.InternalFetch = func(pageSize int, pageToken string) ([]*genprotopb.User, string, error) { resp := &genprotopb.ListUsersResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.identityClient.ListUsers, req, settings.GRPC, c.logger, "ListUsers") return err }, opts...) if err != nil { return nil, "", err } it.Response = resp return resp.GetUsers(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } func (c *identityGRPCClient) ListLocations(ctx context.Context, req *locationpb.ListLocationsRequest, opts ...gax.CallOption) *LocationIterator { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).ListLocations[0:len((*c.CallOptions).ListLocations):len((*c.CallOptions).ListLocations)], opts...) it := &LocationIterator{} req = proto.Clone(req).(*locationpb.ListLocationsRequest) it.InternalFetch = func(pageSize int, pageToken string) ([]*locationpb.Location, string, error) { resp := &locationpb.ListLocationsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.locationsClient.ListLocations, req, settings.GRPC, c.logger, "ListLocations") return err }, opts...) if err != nil { return nil, "", err } it.Response = resp return resp.GetLocations(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } func (c *identityGRPCClient) GetLocation(ctx context.Context, req *locationpb.GetLocationRequest, opts ...gax.CallOption) (*locationpb.Location, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).GetLocation[0:len((*c.CallOptions).GetLocation):len((*c.CallOptions).GetLocation)], opts...) var resp *locationpb.Location err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.locationsClient.GetLocation, req, settings.GRPC, c.logger, "GetLocation") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *identityGRPCClient) SetIamPolicy(ctx context.Context, req *iampb.SetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).SetIamPolicy[0:len((*c.CallOptions).SetIamPolicy):len((*c.CallOptions).SetIamPolicy)], opts...) var resp *iampb.Policy err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.iamPolicyClient.SetIamPolicy, req, settings.GRPC, c.logger, "SetIamPolicy") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *identityGRPCClient) GetIamPolicy(ctx context.Context, req *iampb.GetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).GetIamPolicy[0:len((*c.CallOptions).GetIamPolicy):len((*c.CallOptions).GetIamPolicy)], opts...) var resp *iampb.Policy err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.iamPolicyClient.GetIamPolicy, req, settings.GRPC, c.logger, "GetIamPolicy") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *identityGRPCClient) TestIamPermissions(ctx context.Context, req *iampb.TestIamPermissionsRequest, opts ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).TestIamPermissions[0:len((*c.CallOptions).TestIamPermissions):len((*c.CallOptions).TestIamPermissions)], opts...) var resp *iampb.TestIamPermissionsResponse err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.iamPolicyClient.TestIamPermissions, req, settings.GRPC, c.logger, "TestIamPermissions") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *identityGRPCClient) ListOperations(ctx context.Context, req *longrunningpb.ListOperationsRequest, opts ...gax.CallOption) *OperationIterator { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).ListOperations[0:len((*c.CallOptions).ListOperations):len((*c.CallOptions).ListOperations)], opts...) it := &OperationIterator{} req = proto.Clone(req).(*longrunningpb.ListOperationsRequest) it.InternalFetch = func(pageSize int, pageToken string) ([]*longrunningpb.Operation, string, error) { resp := &longrunningpb.ListOperationsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.operationsClient.ListOperations, req, settings.GRPC, c.logger, "ListOperations") return err }, opts...) if err != nil { return nil, "", err } it.Response = resp return resp.GetOperations(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } func (c *identityGRPCClient) GetOperation(ctx context.Context, req *longrunningpb.GetOperationRequest, opts ...gax.CallOption) (*longrunningpb.Operation, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).GetOperation[0:len((*c.CallOptions).GetOperation):len((*c.CallOptions).GetOperation)], opts...) var resp *longrunningpb.Operation err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.operationsClient.GetOperation, req, settings.GRPC, c.logger, "GetOperation") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *identityGRPCClient) DeleteOperation(ctx context.Context, req *longrunningpb.DeleteOperationRequest, opts ...gax.CallOption) error { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).DeleteOperation[0:len((*c.CallOptions).DeleteOperation):len((*c.CallOptions).DeleteOperation)], opts...) err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error _, err = executeRPC(ctx, c.operationsClient.DeleteOperation, req, settings.GRPC, c.logger, "DeleteOperation") return err }, opts...) return err } func (c *identityGRPCClient) CancelOperation(ctx context.Context, req *longrunningpb.CancelOperationRequest, opts ...gax.CallOption) error { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).CancelOperation[0:len((*c.CallOptions).CancelOperation):len((*c.CallOptions).CancelOperation)], opts...) err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error _, err = executeRPC(ctx, c.operationsClient.CancelOperation, req, settings.GRPC, c.logger, "CancelOperation") return err }, opts...) return err } // CreateUser creates a user. func (c *identityRESTClient) CreateUser(ctx context.Context, req *genprotopb.CreateUserRequest, opts ...gax.CallOption) (*genprotopb.User, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/users") // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).CreateUser[0:len((*c.CallOptions).CreateUser):len((*c.CallOptions).CreateUser)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.User{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "CreateUser") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // GetUser retrieves the User with the given uri. func (c *identityRESTClient) GetUser(ctx context.Context, req *genprotopb.GetUserRequest, opts ...gax.CallOption) (*genprotopb.User, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).GetUser[0:len((*c.CallOptions).GetUser):len((*c.CallOptions).GetUser)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.User{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "GetUser") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // UpdateUser updates a user. func (c *identityRESTClient) UpdateUser(ctx context.Context, req *genprotopb.UpdateUserRequest, opts ...gax.CallOption) (*genprotopb.User, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} body := req.GetUser() jsonReq, err := m.Marshal(body) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetUser().GetName()) params := url.Values{} if req.GetUpdateMask() != nil { field, err := protojson.Marshal(req.GetUpdateMask()) if err != nil { return nil, err } params.Add("updateMask", string(field[1:len(field)-1])) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "user.name", url.QueryEscape(req.GetUser().GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).UpdateUser[0:len((*c.CallOptions).UpdateUser):len((*c.CallOptions).UpdateUser)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.User{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("PATCH", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "UpdateUser") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // DeleteUser deletes a user, their profile, and all of their authored messages. func (c *identityRESTClient) DeleteUser(ctx context.Context, req *genprotopb.DeleteUserRequest, opts ...gax.CallOption) error { baseUrl, err := url.Parse(c.endpoint) if err != nil { return err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) return gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("DELETE", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers _, err = executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "DeleteUser") return err }, opts...) } // ListUsers lists all users. func (c *identityRESTClient) ListUsers(ctx context.Context, req *genprotopb.ListUsersRequest, opts ...gax.CallOption) *UserIterator { it := &UserIterator{} req = proto.Clone(req).(*genprotopb.ListUsersRequest) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} it.InternalFetch = func(pageSize int, pageToken string) ([]*genprotopb.User, string, error) { resp := &genprotopb.ListUsersResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, "", err } baseUrl.Path += fmt.Sprintf("/v1beta1/users") params := url.Values{} if req.GetPageSize() != 0 { params.Add("pageSize", fmt.Sprintf("%v", req.GetPageSize())) } if req.GetPageToken() != "" { params.Add("pageToken", fmt.Sprintf("%v", req.GetPageToken())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "ListUsers") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, "", e } it.Response = resp return resp.GetUsers(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } // ListLocations is a utility method from google.cloud.location.Locations. func (c *identityRESTClient) ListLocations(ctx context.Context, req *locationpb.ListLocationsRequest, opts ...gax.CallOption) *LocationIterator { it := &LocationIterator{} req = proto.Clone(req).(*locationpb.ListLocationsRequest) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} it.InternalFetch = func(pageSize int, pageToken string) ([]*locationpb.Location, string, error) { resp := &locationpb.ListLocationsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, "", err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v/locations", req.GetName()) params := url.Values{} if req.GetFilter() != "" { params.Add("filter", fmt.Sprintf("%v", req.GetFilter())) } if req.GetPageSize() != 0 { params.Add("pageSize", fmt.Sprintf("%v", req.GetPageSize())) } if req.GetPageToken() != "" { params.Add("pageToken", fmt.Sprintf("%v", req.GetPageToken())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "ListLocations") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, "", e } it.Response = resp return resp.GetLocations(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } // GetLocation is a utility method from google.cloud.location.Locations. func (c *identityRESTClient) GetLocation(ctx context.Context, req *locationpb.GetLocationRequest, opts ...gax.CallOption) (*locationpb.Location, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).GetLocation[0:len((*c.CallOptions).GetLocation):len((*c.CallOptions).GetLocation)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &locationpb.Location{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "GetLocation") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // SetIamPolicy is a utility method from google.iam.v1.IAMPolicy. func (c *identityRESTClient) SetIamPolicy(ctx context.Context, req *iampb.SetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:setIamPolicy", req.GetResource()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).SetIamPolicy[0:len((*c.CallOptions).SetIamPolicy):len((*c.CallOptions).SetIamPolicy)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &iampb.Policy{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "SetIamPolicy") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // GetIamPolicy is a utility method from google.iam.v1.IAMPolicy. func (c *identityRESTClient) GetIamPolicy(ctx context.Context, req *iampb.GetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:getIamPolicy", req.GetResource()) params := url.Values{} if req.GetOptions().GetRequestedPolicyVersion() != 0 { params.Add("options.requestedPolicyVersion", fmt.Sprintf("%v", req.GetOptions().GetRequestedPolicyVersion())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).GetIamPolicy[0:len((*c.CallOptions).GetIamPolicy):len((*c.CallOptions).GetIamPolicy)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &iampb.Policy{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "GetIamPolicy") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // TestIamPermissions is a utility method from google.iam.v1.IAMPolicy. func (c *identityRESTClient) TestIamPermissions(ctx context.Context, req *iampb.TestIamPermissionsRequest, opts ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:testIamPermissions", req.GetResource()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).TestIamPermissions[0:len((*c.CallOptions).TestIamPermissions):len((*c.CallOptions).TestIamPermissions)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &iampb.TestIamPermissionsResponse{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "TestIamPermissions") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // ListOperations is a utility method from google.longrunning.Operations. func (c *identityRESTClient) ListOperations(ctx context.Context, req *longrunningpb.ListOperationsRequest, opts ...gax.CallOption) *OperationIterator { it := &OperationIterator{} req = proto.Clone(req).(*longrunningpb.ListOperationsRequest) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} it.InternalFetch = func(pageSize int, pageToken string) ([]*longrunningpb.Operation, string, error) { resp := &longrunningpb.ListOperationsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, "", err } baseUrl.Path += fmt.Sprintf("/v1beta1/operations") params := url.Values{} if req.GetFilter() != "" { params.Add("filter", fmt.Sprintf("%v", req.GetFilter())) } if req.GetName() != "" { params.Add("name", fmt.Sprintf("%v", req.GetName())) } if req.GetPageSize() != 0 { params.Add("pageSize", fmt.Sprintf("%v", req.GetPageSize())) } if req.GetPageToken() != "" { params.Add("pageToken", fmt.Sprintf("%v", req.GetPageToken())) } if req.GetReturnPartialSuccess() { params.Add("returnPartialSuccess", fmt.Sprintf("%v", req.GetReturnPartialSuccess())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "ListOperations") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, "", e } it.Response = resp return resp.GetOperations(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } // GetOperation is a utility method from google.longrunning.Operations. func (c *identityRESTClient) GetOperation(ctx context.Context, req *longrunningpb.GetOperationRequest, opts ...gax.CallOption) (*longrunningpb.Operation, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).GetOperation[0:len((*c.CallOptions).GetOperation):len((*c.CallOptions).GetOperation)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &longrunningpb.Operation{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "GetOperation") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // DeleteOperation is a utility method from google.longrunning.Operations. func (c *identityRESTClient) DeleteOperation(ctx context.Context, req *longrunningpb.DeleteOperationRequest, opts ...gax.CallOption) error { baseUrl, err := url.Parse(c.endpoint) if err != nil { return err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) return gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("DELETE", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers _, err = executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "DeleteOperation") return err }, opts...) } // CancelOperation is a utility method from google.longrunning.Operations. func (c *identityRESTClient) CancelOperation(ctx context.Context, req *longrunningpb.CancelOperationRequest, opts ...gax.CallOption) error { baseUrl, err := url.Parse(c.endpoint) if err != nil { return err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:cancel", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) return gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers _, err = executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "CancelOperation") return err }, opts...) } ================================================ FILE: client/identity_client_example_go123_test.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go_gapic. DO NOT EDIT. //go:build go1.23 package client_test import ( "context" longrunningpb "cloud.google.com/go/longrunning/autogen/longrunningpb" client "github.com/googleapis/gapic-showcase/client" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" locationpb "google.golang.org/genproto/googleapis/cloud/location" ) func ExampleIdentityClient_ListUsers_all() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewIdentityClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.ListUsersRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#ListUsersRequest. } for resp, err := range c.ListUsers(ctx, req).All() { if err != nil { // TODO: Handle error and break/return/continue. Iteration will stop after any error. } // TODO: Use resp. _ = resp } } func ExampleIdentityClient_ListLocations_all() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewIdentityClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &locationpb.ListLocationsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/google.golang.org/genproto/googleapis/cloud/location#ListLocationsRequest. } for resp, err := range c.ListLocations(ctx, req).All() { if err != nil { // TODO: Handle error and break/return/continue. Iteration will stop after any error. } // TODO: Use resp. _ = resp } } func ExampleIdentityClient_ListOperations_all() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewIdentityClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.ListOperationsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#ListOperationsRequest. } for resp, err := range c.ListOperations(ctx, req).All() { if err != nil { // TODO: Handle error and break/return/continue. Iteration will stop after any error. } // TODO: Use resp. _ = resp } } ================================================ FILE: client/identity_client_example_test.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go_gapic. DO NOT EDIT. package client_test import ( "context" iampb "cloud.google.com/go/iam/apiv1/iampb" longrunningpb "cloud.google.com/go/longrunning/autogen/longrunningpb" client "github.com/googleapis/gapic-showcase/client" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "google.golang.org/api/iterator" locationpb "google.golang.org/genproto/googleapis/cloud/location" ) func ExampleNewIdentityClient() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewIdentityClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() // TODO: Use client. _ = c } func ExampleNewIdentityRESTClient() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewIdentityRESTClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() // TODO: Use client. _ = c } func ExampleIdentityClient_CreateUser() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewIdentityClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.CreateUserRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#CreateUserRequest. } resp, err := c.CreateUser(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleIdentityClient_DeleteUser() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewIdentityClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.DeleteUserRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#DeleteUserRequest. } err = c.DeleteUser(ctx, req) if err != nil { // TODO: Handle error. } } func ExampleIdentityClient_GetUser() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewIdentityClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.GetUserRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#GetUserRequest. } resp, err := c.GetUser(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleIdentityClient_ListUsers() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewIdentityClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.ListUsersRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#ListUsersRequest. } it := c.ListUsers(ctx, req) for { resp, err := it.Next() if err == iterator.Done { break } if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp // If you need to access the underlying RPC response, // you can do so by casting the `Response` as below. // Otherwise, remove this line. Only populated after // first call to Next(). Not safe for concurrent access. _ = it.Response.(*genprotopb.ListUsersResponse) } } func ExampleIdentityClient_UpdateUser() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewIdentityClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.UpdateUserRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#UpdateUserRequest. } resp, err := c.UpdateUser(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleIdentityClient_ListLocations() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewIdentityClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &locationpb.ListLocationsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/google.golang.org/genproto/googleapis/cloud/location#ListLocationsRequest. } it := c.ListLocations(ctx, req) for { resp, err := it.Next() if err == iterator.Done { break } if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp // If you need to access the underlying RPC response, // you can do so by casting the `Response` as below. // Otherwise, remove this line. Only populated after // first call to Next(). Not safe for concurrent access. _ = it.Response.(*locationpb.ListLocationsResponse) } } func ExampleIdentityClient_GetLocation() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewIdentityClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &locationpb.GetLocationRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/google.golang.org/genproto/googleapis/cloud/location#GetLocationRequest. } resp, err := c.GetLocation(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleIdentityClient_SetIamPolicy() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewIdentityClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &iampb.SetIamPolicyRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/iam/apiv1/iampb#SetIamPolicyRequest. } resp, err := c.SetIamPolicy(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleIdentityClient_GetIamPolicy() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewIdentityClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &iampb.GetIamPolicyRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/iam/apiv1/iampb#GetIamPolicyRequest. } resp, err := c.GetIamPolicy(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleIdentityClient_TestIamPermissions() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewIdentityClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &iampb.TestIamPermissionsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/iam/apiv1/iampb#TestIamPermissionsRequest. } resp, err := c.TestIamPermissions(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleIdentityClient_ListOperations() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewIdentityClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.ListOperationsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#ListOperationsRequest. } it := c.ListOperations(ctx, req) for { resp, err := it.Next() if err == iterator.Done { break } if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp // If you need to access the underlying RPC response, // you can do so by casting the `Response` as below. // Otherwise, remove this line. Only populated after // first call to Next(). Not safe for concurrent access. _ = it.Response.(*longrunningpb.ListOperationsResponse) } } func ExampleIdentityClient_GetOperation() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewIdentityClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.GetOperationRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#GetOperationRequest. } resp, err := c.GetOperation(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleIdentityClient_DeleteOperation() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewIdentityClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.DeleteOperationRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#DeleteOperationRequest. } err = c.DeleteOperation(ctx, req) if err != nil { // TODO: Handle error. } } func ExampleIdentityClient_CancelOperation() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewIdentityClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.CancelOperationRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#CancelOperationRequest. } err = c.CancelOperation(ctx, req) if err != nil { // TODO: Handle error. } } ================================================ FILE: client/messaging_client.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go_gapic. DO NOT EDIT. package client import ( "bytes" "context" "errors" "fmt" "log/slog" "math" "net/http" "net/url" "time" iampb "cloud.google.com/go/iam/apiv1/iampb" "cloud.google.com/go/longrunning" lroauto "cloud.google.com/go/longrunning/autogen" longrunningpb "cloud.google.com/go/longrunning/autogen/longrunningpb" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" gax "github.com/googleapis/gax-go/v2" "google.golang.org/api/iterator" "google.golang.org/api/option" "google.golang.org/api/option/internaloption" gtransport "google.golang.org/api/transport/grpc" httptransport "google.golang.org/api/transport/http" locationpb "google.golang.org/genproto/googleapis/cloud/location" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" ) var newMessagingClientHook clientHook // MessagingCallOptions contains the retry settings for each method of MessagingClient. type MessagingCallOptions struct { CreateRoom []gax.CallOption GetRoom []gax.CallOption UpdateRoom []gax.CallOption DeleteRoom []gax.CallOption ListRooms []gax.CallOption CreateBlurb []gax.CallOption GetBlurb []gax.CallOption UpdateBlurb []gax.CallOption DeleteBlurb []gax.CallOption ListBlurbs []gax.CallOption SearchBlurbs []gax.CallOption StreamBlurbs []gax.CallOption SendBlurbs []gax.CallOption Connect []gax.CallOption ListLocations []gax.CallOption GetLocation []gax.CallOption SetIamPolicy []gax.CallOption GetIamPolicy []gax.CallOption TestIamPermissions []gax.CallOption ListOperations []gax.CallOption GetOperation []gax.CallOption DeleteOperation []gax.CallOption CancelOperation []gax.CallOption } func defaultMessagingGRPCClientOptions() []option.ClientOption { return []option.ClientOption{ internaloption.WithDefaultEndpoint("localhost:7469"), internaloption.WithDefaultEndpointTemplate("localhost:7469"), internaloption.WithDefaultMTLSEndpoint("localhost:7469"), internaloption.WithDefaultUniverseDomain("googleapis.com"), internaloption.WithDefaultAudience("https://localhost/"), internaloption.WithDefaultScopes(DefaultAuthScopes()...), internaloption.EnableJwtWithScope(), internaloption.EnableNewAuthLibrary(), option.WithGRPCDialOption(grpc.WithDefaultCallOptions( grpc.MaxCallRecvMsgSize(math.MaxInt32))), } } func defaultMessagingCallOptions() *MessagingCallOptions { return &MessagingCallOptions{ CreateRoom: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, GetRoom: []gax.CallOption{ gax.WithTimeout(10000 * time.Millisecond), gax.WithRetry(func() gax.Retryer { return gax.OnCodes([]codes.Code{ codes.Unavailable, codes.Unknown, }, gax.Backoff{ Initial: 100 * time.Millisecond, Max: 3000 * time.Millisecond, Multiplier: 2.00, }) }), }, UpdateRoom: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, DeleteRoom: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, ListRooms: []gax.CallOption{ gax.WithTimeout(10000 * time.Millisecond), gax.WithRetry(func() gax.Retryer { return gax.OnCodes([]codes.Code{ codes.Unavailable, codes.Unknown, }, gax.Backoff{ Initial: 100 * time.Millisecond, Max: 3000 * time.Millisecond, Multiplier: 2.00, }) }), }, CreateBlurb: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, GetBlurb: []gax.CallOption{ gax.WithTimeout(10000 * time.Millisecond), gax.WithRetry(func() gax.Retryer { return gax.OnCodes([]codes.Code{ codes.Unavailable, codes.Unknown, }, gax.Backoff{ Initial: 100 * time.Millisecond, Max: 3000 * time.Millisecond, Multiplier: 2.00, }) }), }, UpdateBlurb: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, DeleteBlurb: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, ListBlurbs: []gax.CallOption{ gax.WithTimeout(10000 * time.Millisecond), gax.WithRetry(func() gax.Retryer { return gax.OnCodes([]codes.Code{ codes.Unavailable, codes.Unknown, }, gax.Backoff{ Initial: 100 * time.Millisecond, Max: 3000 * time.Millisecond, Multiplier: 2.00, }) }), }, SearchBlurbs: []gax.CallOption{ gax.WithTimeout(10000 * time.Millisecond), gax.WithRetry(func() gax.Retryer { return gax.OnCodes([]codes.Code{ codes.Unavailable, codes.Unknown, }, gax.Backoff{ Initial: 100 * time.Millisecond, Max: 3000 * time.Millisecond, Multiplier: 2.00, }) }), }, StreamBlurbs: []gax.CallOption{}, SendBlurbs: []gax.CallOption{}, Connect: []gax.CallOption{ gax.WithRetry(func() gax.Retryer { return gax.OnCodes([]codes.Code{ codes.Unavailable, codes.Unknown, }, gax.Backoff{ Initial: 100 * time.Millisecond, Max: 3000 * time.Millisecond, Multiplier: 2.00, }) }), }, ListLocations: []gax.CallOption{}, GetLocation: []gax.CallOption{}, SetIamPolicy: []gax.CallOption{}, GetIamPolicy: []gax.CallOption{}, TestIamPermissions: []gax.CallOption{}, ListOperations: []gax.CallOption{}, GetOperation: []gax.CallOption{}, DeleteOperation: []gax.CallOption{}, CancelOperation: []gax.CallOption{}, } } func defaultMessagingRESTCallOptions() *MessagingCallOptions { return &MessagingCallOptions{ CreateRoom: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, GetRoom: []gax.CallOption{ gax.WithTimeout(10000 * time.Millisecond), gax.WithRetry(func() gax.Retryer { return gax.OnHTTPCodes(gax.Backoff{ Initial: 100 * time.Millisecond, Max: 3000 * time.Millisecond, Multiplier: 2.00, }, http.StatusServiceUnavailable, http.StatusInternalServerError) }), }, UpdateRoom: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, DeleteRoom: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, ListRooms: []gax.CallOption{ gax.WithTimeout(10000 * time.Millisecond), gax.WithRetry(func() gax.Retryer { return gax.OnHTTPCodes(gax.Backoff{ Initial: 100 * time.Millisecond, Max: 3000 * time.Millisecond, Multiplier: 2.00, }, http.StatusServiceUnavailable, http.StatusInternalServerError) }), }, CreateBlurb: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, GetBlurb: []gax.CallOption{ gax.WithTimeout(10000 * time.Millisecond), gax.WithRetry(func() gax.Retryer { return gax.OnHTTPCodes(gax.Backoff{ Initial: 100 * time.Millisecond, Max: 3000 * time.Millisecond, Multiplier: 2.00, }, http.StatusServiceUnavailable, http.StatusInternalServerError) }), }, UpdateBlurb: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, DeleteBlurb: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, ListBlurbs: []gax.CallOption{ gax.WithTimeout(10000 * time.Millisecond), gax.WithRetry(func() gax.Retryer { return gax.OnHTTPCodes(gax.Backoff{ Initial: 100 * time.Millisecond, Max: 3000 * time.Millisecond, Multiplier: 2.00, }, http.StatusServiceUnavailable, http.StatusInternalServerError) }), }, SearchBlurbs: []gax.CallOption{ gax.WithTimeout(10000 * time.Millisecond), gax.WithRetry(func() gax.Retryer { return gax.OnHTTPCodes(gax.Backoff{ Initial: 100 * time.Millisecond, Max: 3000 * time.Millisecond, Multiplier: 2.00, }, http.StatusServiceUnavailable, http.StatusInternalServerError) }), }, StreamBlurbs: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, SendBlurbs: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, Connect: []gax.CallOption{ gax.WithTimeout(10000 * time.Millisecond), gax.WithRetry(func() gax.Retryer { return gax.OnHTTPCodes(gax.Backoff{ Initial: 100 * time.Millisecond, Max: 3000 * time.Millisecond, Multiplier: 2.00, }, http.StatusServiceUnavailable, http.StatusInternalServerError) }), }, ListLocations: []gax.CallOption{}, GetLocation: []gax.CallOption{}, SetIamPolicy: []gax.CallOption{}, GetIamPolicy: []gax.CallOption{}, TestIamPermissions: []gax.CallOption{}, ListOperations: []gax.CallOption{}, GetOperation: []gax.CallOption{}, DeleteOperation: []gax.CallOption{}, CancelOperation: []gax.CallOption{}, } } // internalMessagingClient is an interface that defines the methods available from Client Libraries Showcase API. type internalMessagingClient interface { Close() error setGoogleClientInfo(...string) Connection() *grpc.ClientConn CreateRoom(context.Context, *genprotopb.CreateRoomRequest, ...gax.CallOption) (*genprotopb.Room, error) GetRoom(context.Context, *genprotopb.GetRoomRequest, ...gax.CallOption) (*genprotopb.Room, error) UpdateRoom(context.Context, *genprotopb.UpdateRoomRequest, ...gax.CallOption) (*genprotopb.Room, error) DeleteRoom(context.Context, *genprotopb.DeleteRoomRequest, ...gax.CallOption) error ListRooms(context.Context, *genprotopb.ListRoomsRequest, ...gax.CallOption) *RoomIterator CreateBlurb(context.Context, *genprotopb.CreateBlurbRequest, ...gax.CallOption) (*genprotopb.Blurb, error) GetBlurb(context.Context, *genprotopb.GetBlurbRequest, ...gax.CallOption) (*genprotopb.Blurb, error) UpdateBlurb(context.Context, *genprotopb.UpdateBlurbRequest, ...gax.CallOption) (*genprotopb.Blurb, error) DeleteBlurb(context.Context, *genprotopb.DeleteBlurbRequest, ...gax.CallOption) error ListBlurbs(context.Context, *genprotopb.ListBlurbsRequest, ...gax.CallOption) *BlurbIterator SearchBlurbs(context.Context, *genprotopb.SearchBlurbsRequest, ...gax.CallOption) (*SearchBlurbsOperation, error) SearchBlurbsOperation(name string) *SearchBlurbsOperation StreamBlurbs(context.Context, *genprotopb.StreamBlurbsRequest, ...gax.CallOption) (genprotopb.Messaging_StreamBlurbsClient, error) SendBlurbs(context.Context, ...gax.CallOption) (genprotopb.Messaging_SendBlurbsClient, error) Connect(context.Context, ...gax.CallOption) (genprotopb.Messaging_ConnectClient, error) ListLocations(context.Context, *locationpb.ListLocationsRequest, ...gax.CallOption) *LocationIterator GetLocation(context.Context, *locationpb.GetLocationRequest, ...gax.CallOption) (*locationpb.Location, error) SetIamPolicy(context.Context, *iampb.SetIamPolicyRequest, ...gax.CallOption) (*iampb.Policy, error) GetIamPolicy(context.Context, *iampb.GetIamPolicyRequest, ...gax.CallOption) (*iampb.Policy, error) TestIamPermissions(context.Context, *iampb.TestIamPermissionsRequest, ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error) ListOperations(context.Context, *longrunningpb.ListOperationsRequest, ...gax.CallOption) *OperationIterator GetOperation(context.Context, *longrunningpb.GetOperationRequest, ...gax.CallOption) (*longrunningpb.Operation, error) DeleteOperation(context.Context, *longrunningpb.DeleteOperationRequest, ...gax.CallOption) error CancelOperation(context.Context, *longrunningpb.CancelOperationRequest, ...gax.CallOption) error } // MessagingClient is a client for interacting with Client Libraries Showcase API. // Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls. // // A simple messaging service that implements chat rooms and profile posts. // // This messaging service showcases the features that API clients // generated by gapic-generators implement. type MessagingClient struct { // The internal transport-dependent client. internalClient internalMessagingClient // The call options for this service. CallOptions *MessagingCallOptions // LROClient is used internally to handle long-running operations. // It is exposed so that its CallOptions can be modified if required. // Users should not Close this client. LROClient *lroauto.OperationsClient } // Wrapper methods routed to the internal client. // Close closes the connection to the API service. The user should invoke this when // the client is no longer required. func (c *MessagingClient) Close() error { return c.internalClient.Close() } // setGoogleClientInfo sets the name and version of the application in // the `x-goog-api-client` header passed on each request. Intended for // use by Google-written clients. func (c *MessagingClient) setGoogleClientInfo(keyval ...string) { c.internalClient.setGoogleClientInfo(keyval...) } // Connection returns a connection to the API service. // // Deprecated: Connections are now pooled so this method does not always // return the same resource. func (c *MessagingClient) Connection() *grpc.ClientConn { return c.internalClient.Connection() } // CreateRoom creates a room. func (c *MessagingClient) CreateRoom(ctx context.Context, req *genprotopb.CreateRoomRequest, opts ...gax.CallOption) (*genprotopb.Room, error) { return c.internalClient.CreateRoom(ctx, req, opts...) } // GetRoom retrieves the Room with the given resource name. func (c *MessagingClient) GetRoom(ctx context.Context, req *genprotopb.GetRoomRequest, opts ...gax.CallOption) (*genprotopb.Room, error) { return c.internalClient.GetRoom(ctx, req, opts...) } // UpdateRoom updates a room. func (c *MessagingClient) UpdateRoom(ctx context.Context, req *genprotopb.UpdateRoomRequest, opts ...gax.CallOption) (*genprotopb.Room, error) { return c.internalClient.UpdateRoom(ctx, req, opts...) } // DeleteRoom deletes a room and all of its blurbs. func (c *MessagingClient) DeleteRoom(ctx context.Context, req *genprotopb.DeleteRoomRequest, opts ...gax.CallOption) error { return c.internalClient.DeleteRoom(ctx, req, opts...) } // ListRooms lists all chat rooms. func (c *MessagingClient) ListRooms(ctx context.Context, req *genprotopb.ListRoomsRequest, opts ...gax.CallOption) *RoomIterator { return c.internalClient.ListRooms(ctx, req, opts...) } // CreateBlurb creates a blurb. If the parent is a room, the blurb is understood to be a // message in that room. If the parent is a profile, the blurb is understood // to be a post on the profile. func (c *MessagingClient) CreateBlurb(ctx context.Context, req *genprotopb.CreateBlurbRequest, opts ...gax.CallOption) (*genprotopb.Blurb, error) { return c.internalClient.CreateBlurb(ctx, req, opts...) } // GetBlurb retrieves the Blurb with the given resource name. func (c *MessagingClient) GetBlurb(ctx context.Context, req *genprotopb.GetBlurbRequest, opts ...gax.CallOption) (*genprotopb.Blurb, error) { return c.internalClient.GetBlurb(ctx, req, opts...) } // UpdateBlurb updates a blurb. func (c *MessagingClient) UpdateBlurb(ctx context.Context, req *genprotopb.UpdateBlurbRequest, opts ...gax.CallOption) (*genprotopb.Blurb, error) { return c.internalClient.UpdateBlurb(ctx, req, opts...) } // DeleteBlurb deletes a blurb. func (c *MessagingClient) DeleteBlurb(ctx context.Context, req *genprotopb.DeleteBlurbRequest, opts ...gax.CallOption) error { return c.internalClient.DeleteBlurb(ctx, req, opts...) } // ListBlurbs lists blurbs for a specific chat room or user profile depending on the // parent resource name. func (c *MessagingClient) ListBlurbs(ctx context.Context, req *genprotopb.ListBlurbsRequest, opts ...gax.CallOption) *BlurbIterator { return c.internalClient.ListBlurbs(ctx, req, opts...) } // SearchBlurbs this method searches through all blurbs across all rooms and profiles // for blurbs containing to words found in the query. Only posts that // contain an exact match of a queried word will be returned. func (c *MessagingClient) SearchBlurbs(ctx context.Context, req *genprotopb.SearchBlurbsRequest, opts ...gax.CallOption) (*SearchBlurbsOperation, error) { return c.internalClient.SearchBlurbs(ctx, req, opts...) } // SearchBlurbsOperation returns a new SearchBlurbsOperation from a given name. // The name must be that of a previously created SearchBlurbsOperation, possibly from a different process. func (c *MessagingClient) SearchBlurbsOperation(name string) *SearchBlurbsOperation { return c.internalClient.SearchBlurbsOperation(name) } // StreamBlurbs this returns a stream that emits the blurbs that are created for a // particular chat room or user profile. func (c *MessagingClient) StreamBlurbs(ctx context.Context, req *genprotopb.StreamBlurbsRequest, opts ...gax.CallOption) (genprotopb.Messaging_StreamBlurbsClient, error) { return c.internalClient.StreamBlurbs(ctx, req, opts...) } // SendBlurbs this is a stream to create multiple blurbs. If an invalid blurb is // requested to be created, the stream will close with an error. // // This method is not supported for the REST transport. func (c *MessagingClient) SendBlurbs(ctx context.Context, opts ...gax.CallOption) (genprotopb.Messaging_SendBlurbsClient, error) { return c.internalClient.SendBlurbs(ctx, opts...) } // Connect this method starts a bidirectional stream that receives all blurbs that // are being created after the stream has started and sends requests to create // blurbs. If an invalid blurb is requested to be created, the stream will // close with an error. // // This method is not supported for the REST transport. func (c *MessagingClient) Connect(ctx context.Context, opts ...gax.CallOption) (genprotopb.Messaging_ConnectClient, error) { return c.internalClient.Connect(ctx, opts...) } // ListLocations is a utility method from google.cloud.location.Locations. func (c *MessagingClient) ListLocations(ctx context.Context, req *locationpb.ListLocationsRequest, opts ...gax.CallOption) *LocationIterator { return c.internalClient.ListLocations(ctx, req, opts...) } // GetLocation is a utility method from google.cloud.location.Locations. func (c *MessagingClient) GetLocation(ctx context.Context, req *locationpb.GetLocationRequest, opts ...gax.CallOption) (*locationpb.Location, error) { return c.internalClient.GetLocation(ctx, req, opts...) } // SetIamPolicy is a utility method from google.iam.v1.IAMPolicy. func (c *MessagingClient) SetIamPolicy(ctx context.Context, req *iampb.SetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { return c.internalClient.SetIamPolicy(ctx, req, opts...) } // GetIamPolicy is a utility method from google.iam.v1.IAMPolicy. func (c *MessagingClient) GetIamPolicy(ctx context.Context, req *iampb.GetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { return c.internalClient.GetIamPolicy(ctx, req, opts...) } // TestIamPermissions is a utility method from google.iam.v1.IAMPolicy. func (c *MessagingClient) TestIamPermissions(ctx context.Context, req *iampb.TestIamPermissionsRequest, opts ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error) { return c.internalClient.TestIamPermissions(ctx, req, opts...) } // ListOperations is a utility method from google.longrunning.Operations. func (c *MessagingClient) ListOperations(ctx context.Context, req *longrunningpb.ListOperationsRequest, opts ...gax.CallOption) *OperationIterator { return c.internalClient.ListOperations(ctx, req, opts...) } // GetOperation is a utility method from google.longrunning.Operations. func (c *MessagingClient) GetOperation(ctx context.Context, req *longrunningpb.GetOperationRequest, opts ...gax.CallOption) (*longrunningpb.Operation, error) { return c.internalClient.GetOperation(ctx, req, opts...) } // DeleteOperation is a utility method from google.longrunning.Operations. func (c *MessagingClient) DeleteOperation(ctx context.Context, req *longrunningpb.DeleteOperationRequest, opts ...gax.CallOption) error { return c.internalClient.DeleteOperation(ctx, req, opts...) } // CancelOperation is a utility method from google.longrunning.Operations. func (c *MessagingClient) CancelOperation(ctx context.Context, req *longrunningpb.CancelOperationRequest, opts ...gax.CallOption) error { return c.internalClient.CancelOperation(ctx, req, opts...) } // messagingGRPCClient is a client for interacting with Client Libraries Showcase API over gRPC transport. // // Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls. type messagingGRPCClient struct { // Connection pool of gRPC connections to the service. connPool gtransport.ConnPool // Points back to the CallOptions field of the containing MessagingClient CallOptions **MessagingCallOptions // The gRPC API client. messagingClient genprotopb.MessagingClient // LROClient is used internally to handle long-running operations. // It is exposed so that its CallOptions can be modified if required. // Users should not Close this client. LROClient **lroauto.OperationsClient operationsClient longrunningpb.OperationsClient iamPolicyClient iampb.IAMPolicyClient locationsClient locationpb.LocationsClient // The x-goog-* metadata to be sent with each request. xGoogHeaders []string logger *slog.Logger } // NewMessagingClient creates a new messaging client based on gRPC. // The returned client must be Closed when it is done being used to clean up its underlying connections. // // A simple messaging service that implements chat rooms and profile posts. // // This messaging service showcases the features that API clients // generated by gapic-generators implement. func NewMessagingClient(ctx context.Context, opts ...option.ClientOption) (*MessagingClient, error) { clientOpts := defaultMessagingGRPCClientOptions() if newMessagingClientHook != nil { hookOpts, err := newMessagingClientHook(ctx, clientHookParams{}) if err != nil { return nil, err } clientOpts = append(clientOpts, hookOpts...) } connPool, err := gtransport.DialPool(ctx, append(clientOpts, opts...)...) if err != nil { return nil, err } client := MessagingClient{CallOptions: defaultMessagingCallOptions()} c := &messagingGRPCClient{ connPool: connPool, messagingClient: genprotopb.NewMessagingClient(connPool), CallOptions: &client.CallOptions, logger: internaloption.GetLogger(opts), operationsClient: longrunningpb.NewOperationsClient(connPool), iamPolicyClient: iampb.NewIAMPolicyClient(connPool), locationsClient: locationpb.NewLocationsClient(connPool), } c.setGoogleClientInfo() client.internalClient = c client.LROClient, err = lroauto.NewOperationsClient(ctx, gtransport.WithConnPool(connPool)) if err != nil { // This error "should not happen", since we are just reusing old connection pool // and never actually need to dial. // If this does happen, we could leak connp. However, we cannot close conn: // If the user invoked the constructor with option.WithGRPCConn, // we would close a connection that's still in use. // TODO: investigate error conditions. return nil, err } c.LROClient = &client.LROClient return &client, nil } // Connection returns a connection to the API service. // // Deprecated: Connections are now pooled so this method does not always // return the same resource. func (c *messagingGRPCClient) Connection() *grpc.ClientConn { return c.connPool.Conn() } // setGoogleClientInfo sets the name and version of the application in // the `x-goog-api-client` header passed on each request. Intended for // use by Google-written clients. func (c *messagingGRPCClient) setGoogleClientInfo(keyval ...string) { kv := append([]string{"gl-go", gax.GoVersion}, keyval...) kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "grpc", grpc.Version, "pb", protoVersion) c.xGoogHeaders = []string{ "x-goog-api-client", gax.XGoogHeader(kv...), } } // Close closes the connection to the API service. The user should invoke this when // the client is no longer required. func (c *messagingGRPCClient) Close() error { return c.connPool.Close() } // Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls. type messagingRESTClient struct { // The http endpoint to connect to. endpoint string // The http client. httpClient *http.Client // LROClient is used internally to handle long-running operations. // It is exposed so that its CallOptions can be modified if required. // Users should not Close this client. LROClient **lroauto.OperationsClient // The x-goog-* headers to be sent with each request. xGoogHeaders []string // Points back to the CallOptions field of the containing MessagingClient CallOptions **MessagingCallOptions logger *slog.Logger } // NewMessagingRESTClient creates a new messaging rest client. // // A simple messaging service that implements chat rooms and profile posts. // // This messaging service showcases the features that API clients // generated by gapic-generators implement. func NewMessagingRESTClient(ctx context.Context, opts ...option.ClientOption) (*MessagingClient, error) { clientOpts := append(defaultMessagingRESTClientOptions(), opts...) httpClient, endpoint, err := httptransport.NewClient(ctx, clientOpts...) if err != nil { return nil, err } callOpts := defaultMessagingRESTCallOptions() c := &messagingRESTClient{ endpoint: endpoint, httpClient: httpClient, CallOptions: &callOpts, logger: internaloption.GetLogger(opts), } c.setGoogleClientInfo() lroOpts := []option.ClientOption{ option.WithHTTPClient(httpClient), option.WithEndpoint(endpoint), } opClient, err := lroauto.NewOperationsRESTClient(ctx, lroOpts...) if err != nil { return nil, err } c.LROClient = &opClient return &MessagingClient{internalClient: c, CallOptions: callOpts}, nil } func defaultMessagingRESTClientOptions() []option.ClientOption { return []option.ClientOption{ internaloption.WithDefaultEndpoint("https://localhost:7469"), internaloption.WithDefaultEndpointTemplate("https://localhost:7469"), internaloption.WithDefaultMTLSEndpoint("https://localhost:7469"), internaloption.WithDefaultUniverseDomain("googleapis.com"), internaloption.WithDefaultAudience("https://localhost/"), internaloption.WithDefaultScopes(DefaultAuthScopes()...), internaloption.EnableNewAuthLibrary(), } } // setGoogleClientInfo sets the name and version of the application in // the `x-goog-api-client` header passed on each request. Intended for // use by Google-written clients. func (c *messagingRESTClient) setGoogleClientInfo(keyval ...string) { kv := append([]string{"gl-go", gax.GoVersion}, keyval...) kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "rest", "UNKNOWN", "pb", protoVersion) c.xGoogHeaders = []string{ "x-goog-api-client", gax.XGoogHeader(kv...), } } // Close closes the connection to the API service. The user should invoke this when // the client is no longer required. func (c *messagingRESTClient) Close() error { // Replace httpClient with nil to force cleanup. c.httpClient = nil return nil } // Connection returns a connection to the API service. // // Deprecated: This method always returns nil. func (c *messagingRESTClient) Connection() *grpc.ClientConn { return nil } func (c *messagingGRPCClient) CreateRoom(ctx context.Context, req *genprotopb.CreateRoomRequest, opts ...gax.CallOption) (*genprotopb.Room, error) { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).CreateRoom[0:len((*c.CallOptions).CreateRoom):len((*c.CallOptions).CreateRoom)], opts...) var resp *genprotopb.Room err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.messagingClient.CreateRoom, req, settings.GRPC, c.logger, "CreateRoom") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *messagingGRPCClient) GetRoom(ctx context.Context, req *genprotopb.GetRoomRequest, opts ...gax.CallOption) (*genprotopb.Room, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).GetRoom[0:len((*c.CallOptions).GetRoom):len((*c.CallOptions).GetRoom)], opts...) var resp *genprotopb.Room err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.messagingClient.GetRoom, req, settings.GRPC, c.logger, "GetRoom") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *messagingGRPCClient) UpdateRoom(ctx context.Context, req *genprotopb.UpdateRoomRequest, opts ...gax.CallOption) (*genprotopb.Room, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "room.name", url.QueryEscape(req.GetRoom().GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).UpdateRoom[0:len((*c.CallOptions).UpdateRoom):len((*c.CallOptions).UpdateRoom)], opts...) var resp *genprotopb.Room err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.messagingClient.UpdateRoom, req, settings.GRPC, c.logger, "UpdateRoom") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *messagingGRPCClient) DeleteRoom(ctx context.Context, req *genprotopb.DeleteRoomRequest, opts ...gax.CallOption) error { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).DeleteRoom[0:len((*c.CallOptions).DeleteRoom):len((*c.CallOptions).DeleteRoom)], opts...) err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error _, err = executeRPC(ctx, c.messagingClient.DeleteRoom, req, settings.GRPC, c.logger, "DeleteRoom") return err }, opts...) return err } func (c *messagingGRPCClient) ListRooms(ctx context.Context, req *genprotopb.ListRoomsRequest, opts ...gax.CallOption) *RoomIterator { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).ListRooms[0:len((*c.CallOptions).ListRooms):len((*c.CallOptions).ListRooms)], opts...) it := &RoomIterator{} req = proto.Clone(req).(*genprotopb.ListRoomsRequest) it.InternalFetch = func(pageSize int, pageToken string) ([]*genprotopb.Room, string, error) { resp := &genprotopb.ListRoomsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.messagingClient.ListRooms, req, settings.GRPC, c.logger, "ListRooms") return err }, opts...) if err != nil { return nil, "", err } it.Response = resp return resp.GetRooms(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } func (c *messagingGRPCClient) CreateBlurb(ctx context.Context, req *genprotopb.CreateBlurbRequest, opts ...gax.CallOption) (*genprotopb.Blurb, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "parent", url.QueryEscape(req.GetParent()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).CreateBlurb[0:len((*c.CallOptions).CreateBlurb):len((*c.CallOptions).CreateBlurb)], opts...) var resp *genprotopb.Blurb err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.messagingClient.CreateBlurb, req, settings.GRPC, c.logger, "CreateBlurb") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *messagingGRPCClient) GetBlurb(ctx context.Context, req *genprotopb.GetBlurbRequest, opts ...gax.CallOption) (*genprotopb.Blurb, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).GetBlurb[0:len((*c.CallOptions).GetBlurb):len((*c.CallOptions).GetBlurb)], opts...) var resp *genprotopb.Blurb err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.messagingClient.GetBlurb, req, settings.GRPC, c.logger, "GetBlurb") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *messagingGRPCClient) UpdateBlurb(ctx context.Context, req *genprotopb.UpdateBlurbRequest, opts ...gax.CallOption) (*genprotopb.Blurb, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "blurb.name", url.QueryEscape(req.GetBlurb().GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).UpdateBlurb[0:len((*c.CallOptions).UpdateBlurb):len((*c.CallOptions).UpdateBlurb)], opts...) var resp *genprotopb.Blurb err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.messagingClient.UpdateBlurb, req, settings.GRPC, c.logger, "UpdateBlurb") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *messagingGRPCClient) DeleteBlurb(ctx context.Context, req *genprotopb.DeleteBlurbRequest, opts ...gax.CallOption) error { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).DeleteBlurb[0:len((*c.CallOptions).DeleteBlurb):len((*c.CallOptions).DeleteBlurb)], opts...) err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error _, err = executeRPC(ctx, c.messagingClient.DeleteBlurb, req, settings.GRPC, c.logger, "DeleteBlurb") return err }, opts...) return err } func (c *messagingGRPCClient) ListBlurbs(ctx context.Context, req *genprotopb.ListBlurbsRequest, opts ...gax.CallOption) *BlurbIterator { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "parent", url.QueryEscape(req.GetParent()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).ListBlurbs[0:len((*c.CallOptions).ListBlurbs):len((*c.CallOptions).ListBlurbs)], opts...) it := &BlurbIterator{} req = proto.Clone(req).(*genprotopb.ListBlurbsRequest) it.InternalFetch = func(pageSize int, pageToken string) ([]*genprotopb.Blurb, string, error) { resp := &genprotopb.ListBlurbsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.messagingClient.ListBlurbs, req, settings.GRPC, c.logger, "ListBlurbs") return err }, opts...) if err != nil { return nil, "", err } it.Response = resp return resp.GetBlurbs(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } func (c *messagingGRPCClient) SearchBlurbs(ctx context.Context, req *genprotopb.SearchBlurbsRequest, opts ...gax.CallOption) (*SearchBlurbsOperation, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "parent", url.QueryEscape(req.GetParent()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).SearchBlurbs[0:len((*c.CallOptions).SearchBlurbs):len((*c.CallOptions).SearchBlurbs)], opts...) var resp *longrunningpb.Operation err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.messagingClient.SearchBlurbs, req, settings.GRPC, c.logger, "SearchBlurbs") return err }, opts...) if err != nil { return nil, err } return &SearchBlurbsOperation{ lro: longrunning.InternalNewOperation(*c.LROClient, resp), }, nil } func (c *messagingGRPCClient) StreamBlurbs(ctx context.Context, req *genprotopb.StreamBlurbsRequest, opts ...gax.CallOption) (genprotopb.Messaging_StreamBlurbsClient, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).StreamBlurbs[0:len((*c.CallOptions).StreamBlurbs):len((*c.CallOptions).StreamBlurbs)], opts...) var resp genprotopb.Messaging_StreamBlurbsClient err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error c.logger.DebugContext(ctx, "api streaming client request", "serviceName", serviceName, "rpcName", "StreamBlurbs") resp, err = c.messagingClient.StreamBlurbs(ctx, req, settings.GRPC...) c.logger.DebugContext(ctx, "api streaming client response", "serviceName", serviceName, "rpcName", "StreamBlurbs") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *messagingGRPCClient) SendBlurbs(ctx context.Context, opts ...gax.CallOption) (genprotopb.Messaging_SendBlurbsClient, error) { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) var resp genprotopb.Messaging_SendBlurbsClient opts = append((*c.CallOptions).SendBlurbs[0:len((*c.CallOptions).SendBlurbs):len((*c.CallOptions).SendBlurbs)], opts...) err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error c.logger.DebugContext(ctx, "api streaming client request", "serviceName", serviceName, "rpcName", "SendBlurbs") resp, err = c.messagingClient.SendBlurbs(ctx, settings.GRPC...) c.logger.DebugContext(ctx, "api streaming client response", "serviceName", serviceName, "rpcName", "SendBlurbs") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *messagingGRPCClient) Connect(ctx context.Context, opts ...gax.CallOption) (genprotopb.Messaging_ConnectClient, error) { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) var resp genprotopb.Messaging_ConnectClient opts = append((*c.CallOptions).Connect[0:len((*c.CallOptions).Connect):len((*c.CallOptions).Connect)], opts...) err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error c.logger.DebugContext(ctx, "api streaming client request", "serviceName", serviceName, "rpcName", "Connect") resp, err = c.messagingClient.Connect(ctx, settings.GRPC...) c.logger.DebugContext(ctx, "api streaming client response", "serviceName", serviceName, "rpcName", "Connect") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *messagingGRPCClient) ListLocations(ctx context.Context, req *locationpb.ListLocationsRequest, opts ...gax.CallOption) *LocationIterator { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).ListLocations[0:len((*c.CallOptions).ListLocations):len((*c.CallOptions).ListLocations)], opts...) it := &LocationIterator{} req = proto.Clone(req).(*locationpb.ListLocationsRequest) it.InternalFetch = func(pageSize int, pageToken string) ([]*locationpb.Location, string, error) { resp := &locationpb.ListLocationsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.locationsClient.ListLocations, req, settings.GRPC, c.logger, "ListLocations") return err }, opts...) if err != nil { return nil, "", err } it.Response = resp return resp.GetLocations(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } func (c *messagingGRPCClient) GetLocation(ctx context.Context, req *locationpb.GetLocationRequest, opts ...gax.CallOption) (*locationpb.Location, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).GetLocation[0:len((*c.CallOptions).GetLocation):len((*c.CallOptions).GetLocation)], opts...) var resp *locationpb.Location err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.locationsClient.GetLocation, req, settings.GRPC, c.logger, "GetLocation") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *messagingGRPCClient) SetIamPolicy(ctx context.Context, req *iampb.SetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).SetIamPolicy[0:len((*c.CallOptions).SetIamPolicy):len((*c.CallOptions).SetIamPolicy)], opts...) var resp *iampb.Policy err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.iamPolicyClient.SetIamPolicy, req, settings.GRPC, c.logger, "SetIamPolicy") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *messagingGRPCClient) GetIamPolicy(ctx context.Context, req *iampb.GetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).GetIamPolicy[0:len((*c.CallOptions).GetIamPolicy):len((*c.CallOptions).GetIamPolicy)], opts...) var resp *iampb.Policy err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.iamPolicyClient.GetIamPolicy, req, settings.GRPC, c.logger, "GetIamPolicy") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *messagingGRPCClient) TestIamPermissions(ctx context.Context, req *iampb.TestIamPermissionsRequest, opts ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).TestIamPermissions[0:len((*c.CallOptions).TestIamPermissions):len((*c.CallOptions).TestIamPermissions)], opts...) var resp *iampb.TestIamPermissionsResponse err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.iamPolicyClient.TestIamPermissions, req, settings.GRPC, c.logger, "TestIamPermissions") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *messagingGRPCClient) ListOperations(ctx context.Context, req *longrunningpb.ListOperationsRequest, opts ...gax.CallOption) *OperationIterator { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).ListOperations[0:len((*c.CallOptions).ListOperations):len((*c.CallOptions).ListOperations)], opts...) it := &OperationIterator{} req = proto.Clone(req).(*longrunningpb.ListOperationsRequest) it.InternalFetch = func(pageSize int, pageToken string) ([]*longrunningpb.Operation, string, error) { resp := &longrunningpb.ListOperationsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.operationsClient.ListOperations, req, settings.GRPC, c.logger, "ListOperations") return err }, opts...) if err != nil { return nil, "", err } it.Response = resp return resp.GetOperations(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } func (c *messagingGRPCClient) GetOperation(ctx context.Context, req *longrunningpb.GetOperationRequest, opts ...gax.CallOption) (*longrunningpb.Operation, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).GetOperation[0:len((*c.CallOptions).GetOperation):len((*c.CallOptions).GetOperation)], opts...) var resp *longrunningpb.Operation err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.operationsClient.GetOperation, req, settings.GRPC, c.logger, "GetOperation") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *messagingGRPCClient) DeleteOperation(ctx context.Context, req *longrunningpb.DeleteOperationRequest, opts ...gax.CallOption) error { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).DeleteOperation[0:len((*c.CallOptions).DeleteOperation):len((*c.CallOptions).DeleteOperation)], opts...) err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error _, err = executeRPC(ctx, c.operationsClient.DeleteOperation, req, settings.GRPC, c.logger, "DeleteOperation") return err }, opts...) return err } func (c *messagingGRPCClient) CancelOperation(ctx context.Context, req *longrunningpb.CancelOperationRequest, opts ...gax.CallOption) error { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).CancelOperation[0:len((*c.CallOptions).CancelOperation):len((*c.CallOptions).CancelOperation)], opts...) err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error _, err = executeRPC(ctx, c.operationsClient.CancelOperation, req, settings.GRPC, c.logger, "CancelOperation") return err }, opts...) return err } // CreateRoom creates a room. func (c *messagingRESTClient) CreateRoom(ctx context.Context, req *genprotopb.CreateRoomRequest, opts ...gax.CallOption) (*genprotopb.Room, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/rooms") // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).CreateRoom[0:len((*c.CallOptions).CreateRoom):len((*c.CallOptions).CreateRoom)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.Room{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "CreateRoom") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // GetRoom retrieves the Room with the given resource name. func (c *messagingRESTClient) GetRoom(ctx context.Context, req *genprotopb.GetRoomRequest, opts ...gax.CallOption) (*genprotopb.Room, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).GetRoom[0:len((*c.CallOptions).GetRoom):len((*c.CallOptions).GetRoom)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.Room{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "GetRoom") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // UpdateRoom updates a room. func (c *messagingRESTClient) UpdateRoom(ctx context.Context, req *genprotopb.UpdateRoomRequest, opts ...gax.CallOption) (*genprotopb.Room, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} body := req.GetRoom() jsonReq, err := m.Marshal(body) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetRoom().GetName()) params := url.Values{} if req.GetUpdateMask() != nil { field, err := protojson.Marshal(req.GetUpdateMask()) if err != nil { return nil, err } params.Add("updateMask", string(field[1:len(field)-1])) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "room.name", url.QueryEscape(req.GetRoom().GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).UpdateRoom[0:len((*c.CallOptions).UpdateRoom):len((*c.CallOptions).UpdateRoom)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.Room{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("PATCH", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "UpdateRoom") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // DeleteRoom deletes a room and all of its blurbs. func (c *messagingRESTClient) DeleteRoom(ctx context.Context, req *genprotopb.DeleteRoomRequest, opts ...gax.CallOption) error { baseUrl, err := url.Parse(c.endpoint) if err != nil { return err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) return gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("DELETE", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers _, err = executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "DeleteRoom") return err }, opts...) } // ListRooms lists all chat rooms. func (c *messagingRESTClient) ListRooms(ctx context.Context, req *genprotopb.ListRoomsRequest, opts ...gax.CallOption) *RoomIterator { it := &RoomIterator{} req = proto.Clone(req).(*genprotopb.ListRoomsRequest) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} it.InternalFetch = func(pageSize int, pageToken string) ([]*genprotopb.Room, string, error) { resp := &genprotopb.ListRoomsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, "", err } baseUrl.Path += fmt.Sprintf("/v1beta1/rooms") params := url.Values{} if req.GetPageSize() != 0 { params.Add("pageSize", fmt.Sprintf("%v", req.GetPageSize())) } if req.GetPageToken() != "" { params.Add("pageToken", fmt.Sprintf("%v", req.GetPageToken())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "ListRooms") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, "", e } it.Response = resp return resp.GetRooms(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } // CreateBlurb creates a blurb. If the parent is a room, the blurb is understood to be a // message in that room. If the parent is a profile, the blurb is understood // to be a post on the profile. func (c *messagingRESTClient) CreateBlurb(ctx context.Context, req *genprotopb.CreateBlurbRequest, opts ...gax.CallOption) (*genprotopb.Blurb, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v/blurbs", req.GetParent()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "parent", url.QueryEscape(req.GetParent()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).CreateBlurb[0:len((*c.CallOptions).CreateBlurb):len((*c.CallOptions).CreateBlurb)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.Blurb{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "CreateBlurb") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // GetBlurb retrieves the Blurb with the given resource name. func (c *messagingRESTClient) GetBlurb(ctx context.Context, req *genprotopb.GetBlurbRequest, opts ...gax.CallOption) (*genprotopb.Blurb, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).GetBlurb[0:len((*c.CallOptions).GetBlurb):len((*c.CallOptions).GetBlurb)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.Blurb{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "GetBlurb") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // UpdateBlurb updates a blurb. func (c *messagingRESTClient) UpdateBlurb(ctx context.Context, req *genprotopb.UpdateBlurbRequest, opts ...gax.CallOption) (*genprotopb.Blurb, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} body := req.GetBlurb() jsonReq, err := m.Marshal(body) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetBlurb().GetName()) params := url.Values{} if req.GetUpdateMask() != nil { field, err := protojson.Marshal(req.GetUpdateMask()) if err != nil { return nil, err } params.Add("updateMask", string(field[1:len(field)-1])) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "blurb.name", url.QueryEscape(req.GetBlurb().GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).UpdateBlurb[0:len((*c.CallOptions).UpdateBlurb):len((*c.CallOptions).UpdateBlurb)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.Blurb{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("PATCH", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "UpdateBlurb") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // DeleteBlurb deletes a blurb. func (c *messagingRESTClient) DeleteBlurb(ctx context.Context, req *genprotopb.DeleteBlurbRequest, opts ...gax.CallOption) error { baseUrl, err := url.Parse(c.endpoint) if err != nil { return err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) return gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("DELETE", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers _, err = executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "DeleteBlurb") return err }, opts...) } // ListBlurbs lists blurbs for a specific chat room or user profile depending on the // parent resource name. func (c *messagingRESTClient) ListBlurbs(ctx context.Context, req *genprotopb.ListBlurbsRequest, opts ...gax.CallOption) *BlurbIterator { it := &BlurbIterator{} req = proto.Clone(req).(*genprotopb.ListBlurbsRequest) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} it.InternalFetch = func(pageSize int, pageToken string) ([]*genprotopb.Blurb, string, error) { resp := &genprotopb.ListBlurbsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, "", err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v/blurbs", req.GetParent()) params := url.Values{} if req.GetPageSize() != 0 { params.Add("pageSize", fmt.Sprintf("%v", req.GetPageSize())) } if req.GetPageToken() != "" { params.Add("pageToken", fmt.Sprintf("%v", req.GetPageToken())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "ListBlurbs") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, "", e } it.Response = resp return resp.GetBlurbs(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } // SearchBlurbs this method searches through all blurbs across all rooms and profiles // for blurbs containing to words found in the query. Only posts that // contain an exact match of a queried word will be returned. func (c *messagingRESTClient) SearchBlurbs(ctx context.Context, req *genprotopb.SearchBlurbsRequest, opts ...gax.CallOption) (*SearchBlurbsOperation, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v/blurbs:search", req.GetParent()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "parent", url.QueryEscape(req.GetParent()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &longrunningpb.Operation{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "SearchBlurbs") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } override := fmt.Sprintf("/v1beta1/%s", resp.GetName()) return &SearchBlurbsOperation{ lro: longrunning.InternalNewOperation(*c.LROClient, resp), pollPath: override, }, nil } // StreamBlurbs this returns a stream that emits the blurbs that are created for a // particular chat room or user profile. func (c *messagingRESTClient) StreamBlurbs(ctx context.Context, req *genprotopb.StreamBlurbsRequest, opts ...gax.CallOption) (genprotopb.Messaging_StreamBlurbsClient, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v/blurbs:stream", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) var streamClient *streamBlurbsRESTStreamClient e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers httpRsp, err := executeStreamingHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "StreamBlurbs") if err != nil { return err } streamClient = &streamBlurbsRESTStreamClient{ ctx: ctx, md: metadata.MD(httpRsp.Header), stream: gax.NewProtoJSONStreamReader(httpRsp.Body, (&genprotopb.StreamBlurbsResponse{}).ProtoReflect().Type()), } return nil }, opts...) return streamClient, e } // streamBlurbsRESTStreamClient is the stream client used to consume the server stream created by // the REST implementation of StreamBlurbs. type streamBlurbsRESTStreamClient struct { ctx context.Context md metadata.MD stream *gax.ProtoJSONStream } func (c *streamBlurbsRESTStreamClient) Recv() (*genprotopb.StreamBlurbsResponse, error) { if err := c.ctx.Err(); err != nil { defer c.stream.Close() return nil, err } msg, err := c.stream.Recv() if err != nil { defer c.stream.Close() return nil, err } res := msg.(*genprotopb.StreamBlurbsResponse) return res, nil } func (c *streamBlurbsRESTStreamClient) Header() (metadata.MD, error) { return c.md, nil } func (c *streamBlurbsRESTStreamClient) Trailer() metadata.MD { return c.md } func (c *streamBlurbsRESTStreamClient) CloseSend() error { // This is a no-op to fulfill the interface. return errors.New("this method is not implemented for a server-stream") } func (c *streamBlurbsRESTStreamClient) Context() context.Context { return c.ctx } func (c *streamBlurbsRESTStreamClient) SendMsg(m interface{}) error { // This is a no-op to fulfill the interface. return errors.New("this method is not implemented for a server-stream") } func (c *streamBlurbsRESTStreamClient) RecvMsg(m interface{}) error { // This is a no-op to fulfill the interface. return errors.New("this method is not implemented, use Recv") } // SendBlurbs this is a stream to create multiple blurbs. If an invalid blurb is // requested to be created, the stream will close with an error. // // This method is not supported for the REST transport. func (c *messagingRESTClient) SendBlurbs(ctx context.Context, opts ...gax.CallOption) (genprotopb.Messaging_SendBlurbsClient, error) { return nil, errors.New("SendBlurbs not yet supported for REST clients") } // Connect this method starts a bidirectional stream that receives all blurbs that // are being created after the stream has started and sends requests to create // blurbs. If an invalid blurb is requested to be created, the stream will // close with an error. // // This method is not supported for the REST transport. func (c *messagingRESTClient) Connect(ctx context.Context, opts ...gax.CallOption) (genprotopb.Messaging_ConnectClient, error) { return nil, errors.New("Connect not yet supported for REST clients") } // ListLocations is a utility method from google.cloud.location.Locations. func (c *messagingRESTClient) ListLocations(ctx context.Context, req *locationpb.ListLocationsRequest, opts ...gax.CallOption) *LocationIterator { it := &LocationIterator{} req = proto.Clone(req).(*locationpb.ListLocationsRequest) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} it.InternalFetch = func(pageSize int, pageToken string) ([]*locationpb.Location, string, error) { resp := &locationpb.ListLocationsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, "", err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v/locations", req.GetName()) params := url.Values{} if req.GetFilter() != "" { params.Add("filter", fmt.Sprintf("%v", req.GetFilter())) } if req.GetPageSize() != 0 { params.Add("pageSize", fmt.Sprintf("%v", req.GetPageSize())) } if req.GetPageToken() != "" { params.Add("pageToken", fmt.Sprintf("%v", req.GetPageToken())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "ListLocations") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, "", e } it.Response = resp return resp.GetLocations(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } // GetLocation is a utility method from google.cloud.location.Locations. func (c *messagingRESTClient) GetLocation(ctx context.Context, req *locationpb.GetLocationRequest, opts ...gax.CallOption) (*locationpb.Location, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).GetLocation[0:len((*c.CallOptions).GetLocation):len((*c.CallOptions).GetLocation)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &locationpb.Location{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "GetLocation") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // SetIamPolicy is a utility method from google.iam.v1.IAMPolicy. func (c *messagingRESTClient) SetIamPolicy(ctx context.Context, req *iampb.SetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:setIamPolicy", req.GetResource()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).SetIamPolicy[0:len((*c.CallOptions).SetIamPolicy):len((*c.CallOptions).SetIamPolicy)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &iampb.Policy{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "SetIamPolicy") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // GetIamPolicy is a utility method from google.iam.v1.IAMPolicy. func (c *messagingRESTClient) GetIamPolicy(ctx context.Context, req *iampb.GetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:getIamPolicy", req.GetResource()) params := url.Values{} if req.GetOptions().GetRequestedPolicyVersion() != 0 { params.Add("options.requestedPolicyVersion", fmt.Sprintf("%v", req.GetOptions().GetRequestedPolicyVersion())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).GetIamPolicy[0:len((*c.CallOptions).GetIamPolicy):len((*c.CallOptions).GetIamPolicy)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &iampb.Policy{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "GetIamPolicy") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // TestIamPermissions is a utility method from google.iam.v1.IAMPolicy. func (c *messagingRESTClient) TestIamPermissions(ctx context.Context, req *iampb.TestIamPermissionsRequest, opts ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:testIamPermissions", req.GetResource()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).TestIamPermissions[0:len((*c.CallOptions).TestIamPermissions):len((*c.CallOptions).TestIamPermissions)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &iampb.TestIamPermissionsResponse{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "TestIamPermissions") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // ListOperations is a utility method from google.longrunning.Operations. func (c *messagingRESTClient) ListOperations(ctx context.Context, req *longrunningpb.ListOperationsRequest, opts ...gax.CallOption) *OperationIterator { it := &OperationIterator{} req = proto.Clone(req).(*longrunningpb.ListOperationsRequest) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} it.InternalFetch = func(pageSize int, pageToken string) ([]*longrunningpb.Operation, string, error) { resp := &longrunningpb.ListOperationsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, "", err } baseUrl.Path += fmt.Sprintf("/v1beta1/operations") params := url.Values{} if req.GetFilter() != "" { params.Add("filter", fmt.Sprintf("%v", req.GetFilter())) } if req.GetName() != "" { params.Add("name", fmt.Sprintf("%v", req.GetName())) } if req.GetPageSize() != 0 { params.Add("pageSize", fmt.Sprintf("%v", req.GetPageSize())) } if req.GetPageToken() != "" { params.Add("pageToken", fmt.Sprintf("%v", req.GetPageToken())) } if req.GetReturnPartialSuccess() { params.Add("returnPartialSuccess", fmt.Sprintf("%v", req.GetReturnPartialSuccess())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "ListOperations") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, "", e } it.Response = resp return resp.GetOperations(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } // GetOperation is a utility method from google.longrunning.Operations. func (c *messagingRESTClient) GetOperation(ctx context.Context, req *longrunningpb.GetOperationRequest, opts ...gax.CallOption) (*longrunningpb.Operation, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).GetOperation[0:len((*c.CallOptions).GetOperation):len((*c.CallOptions).GetOperation)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &longrunningpb.Operation{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "GetOperation") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // DeleteOperation is a utility method from google.longrunning.Operations. func (c *messagingRESTClient) DeleteOperation(ctx context.Context, req *longrunningpb.DeleteOperationRequest, opts ...gax.CallOption) error { baseUrl, err := url.Parse(c.endpoint) if err != nil { return err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) return gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("DELETE", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers _, err = executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "DeleteOperation") return err }, opts...) } // CancelOperation is a utility method from google.longrunning.Operations. func (c *messagingRESTClient) CancelOperation(ctx context.Context, req *longrunningpb.CancelOperationRequest, opts ...gax.CallOption) error { baseUrl, err := url.Parse(c.endpoint) if err != nil { return err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:cancel", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) return gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers _, err = executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "CancelOperation") return err }, opts...) } // SearchBlurbsOperation returns a new SearchBlurbsOperation from a given name. // The name must be that of a previously created SearchBlurbsOperation, possibly from a different process. func (c *messagingGRPCClient) SearchBlurbsOperation(name string) *SearchBlurbsOperation { return &SearchBlurbsOperation{ lro: longrunning.InternalNewOperation(*c.LROClient, &longrunningpb.Operation{Name: name}), } } // SearchBlurbsOperation returns a new SearchBlurbsOperation from a given name. // The name must be that of a previously created SearchBlurbsOperation, possibly from a different process. func (c *messagingRESTClient) SearchBlurbsOperation(name string) *SearchBlurbsOperation { override := fmt.Sprintf("/v1beta1/%s", name) return &SearchBlurbsOperation{ lro: longrunning.InternalNewOperation(*c.LROClient, &longrunningpb.Operation{Name: name}), pollPath: override, } } ================================================ FILE: client/messaging_client_example_go123_test.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go_gapic. DO NOT EDIT. //go:build go1.23 package client_test import ( "context" longrunningpb "cloud.google.com/go/longrunning/autogen/longrunningpb" client "github.com/googleapis/gapic-showcase/client" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" locationpb "google.golang.org/genproto/googleapis/cloud/location" ) func ExampleMessagingClient_ListBlurbs_all() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.ListBlurbsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#ListBlurbsRequest. } for resp, err := range c.ListBlurbs(ctx, req).All() { if err != nil { // TODO: Handle error and break/return/continue. Iteration will stop after any error. } // TODO: Use resp. _ = resp } } func ExampleMessagingClient_ListRooms_all() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.ListRoomsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#ListRoomsRequest. } for resp, err := range c.ListRooms(ctx, req).All() { if err != nil { // TODO: Handle error and break/return/continue. Iteration will stop after any error. } // TODO: Use resp. _ = resp } } func ExampleMessagingClient_ListLocations_all() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &locationpb.ListLocationsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/google.golang.org/genproto/googleapis/cloud/location#ListLocationsRequest. } for resp, err := range c.ListLocations(ctx, req).All() { if err != nil { // TODO: Handle error and break/return/continue. Iteration will stop after any error. } // TODO: Use resp. _ = resp } } func ExampleMessagingClient_ListOperations_all() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.ListOperationsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#ListOperationsRequest. } for resp, err := range c.ListOperations(ctx, req).All() { if err != nil { // TODO: Handle error and break/return/continue. Iteration will stop after any error. } // TODO: Use resp. _ = resp } } ================================================ FILE: client/messaging_client_example_test.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go_gapic. DO NOT EDIT. package client_test import ( "context" "io" iampb "cloud.google.com/go/iam/apiv1/iampb" longrunningpb "cloud.google.com/go/longrunning/autogen/longrunningpb" client "github.com/googleapis/gapic-showcase/client" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "google.golang.org/api/iterator" locationpb "google.golang.org/genproto/googleapis/cloud/location" ) func ExampleNewMessagingClient() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() // TODO: Use client. _ = c } func ExampleNewMessagingRESTClient() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingRESTClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() // TODO: Use client. _ = c } func ExampleMessagingClient_Connect() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() stream, err := c.Connect(ctx) if err != nil { // TODO: Handle error. } go func() { reqs := []*genprotopb.ConnectRequest{ // TODO: Create requests. } for _, req := range reqs { if err := stream.Send(req); err != nil { // TODO: Handle error. } } stream.CloseSend() }() for { resp, err := stream.Recv() if err == io.EOF { break } if err != nil { // TODO: handle error. } // TODO: Use resp. _ = resp } } func ExampleMessagingClient_CreateBlurb() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.CreateBlurbRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#CreateBlurbRequest. } resp, err := c.CreateBlurb(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleMessagingClient_CreateRoom() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.CreateRoomRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#CreateRoomRequest. } resp, err := c.CreateRoom(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleMessagingClient_DeleteBlurb() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.DeleteBlurbRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#DeleteBlurbRequest. } err = c.DeleteBlurb(ctx, req) if err != nil { // TODO: Handle error. } } func ExampleMessagingClient_DeleteRoom() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.DeleteRoomRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#DeleteRoomRequest. } err = c.DeleteRoom(ctx, req) if err != nil { // TODO: Handle error. } } func ExampleMessagingClient_GetBlurb() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.GetBlurbRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#GetBlurbRequest. } resp, err := c.GetBlurb(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleMessagingClient_GetRoom() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.GetRoomRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#GetRoomRequest. } resp, err := c.GetRoom(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleMessagingClient_ListBlurbs() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.ListBlurbsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#ListBlurbsRequest. } it := c.ListBlurbs(ctx, req) for { resp, err := it.Next() if err == iterator.Done { break } if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp // If you need to access the underlying RPC response, // you can do so by casting the `Response` as below. // Otherwise, remove this line. Only populated after // first call to Next(). Not safe for concurrent access. _ = it.Response.(*genprotopb.ListBlurbsResponse) } } func ExampleMessagingClient_ListRooms() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.ListRoomsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#ListRoomsRequest. } it := c.ListRooms(ctx, req) for { resp, err := it.Next() if err == iterator.Done { break } if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp // If you need to access the underlying RPC response, // you can do so by casting the `Response` as below. // Otherwise, remove this line. Only populated after // first call to Next(). Not safe for concurrent access. _ = it.Response.(*genprotopb.ListRoomsResponse) } } func ExampleMessagingClient_SearchBlurbs() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.SearchBlurbsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#SearchBlurbsRequest. } op, err := c.SearchBlurbs(ctx, req) if err != nil { // TODO: Handle error. } resp, err := op.Wait(ctx) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleMessagingClient_UpdateBlurb() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.UpdateBlurbRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#UpdateBlurbRequest. } resp, err := c.UpdateBlurb(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleMessagingClient_UpdateRoom() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.UpdateRoomRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#UpdateRoomRequest. } resp, err := c.UpdateRoom(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleMessagingClient_ListLocations() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &locationpb.ListLocationsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/google.golang.org/genproto/googleapis/cloud/location#ListLocationsRequest. } it := c.ListLocations(ctx, req) for { resp, err := it.Next() if err == iterator.Done { break } if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp // If you need to access the underlying RPC response, // you can do so by casting the `Response` as below. // Otherwise, remove this line. Only populated after // first call to Next(). Not safe for concurrent access. _ = it.Response.(*locationpb.ListLocationsResponse) } } func ExampleMessagingClient_GetLocation() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &locationpb.GetLocationRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/google.golang.org/genproto/googleapis/cloud/location#GetLocationRequest. } resp, err := c.GetLocation(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleMessagingClient_SetIamPolicy() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &iampb.SetIamPolicyRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/iam/apiv1/iampb#SetIamPolicyRequest. } resp, err := c.SetIamPolicy(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleMessagingClient_GetIamPolicy() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &iampb.GetIamPolicyRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/iam/apiv1/iampb#GetIamPolicyRequest. } resp, err := c.GetIamPolicy(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleMessagingClient_TestIamPermissions() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &iampb.TestIamPermissionsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/iam/apiv1/iampb#TestIamPermissionsRequest. } resp, err := c.TestIamPermissions(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleMessagingClient_ListOperations() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.ListOperationsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#ListOperationsRequest. } it := c.ListOperations(ctx, req) for { resp, err := it.Next() if err == iterator.Done { break } if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp // If you need to access the underlying RPC response, // you can do so by casting the `Response` as below. // Otherwise, remove this line. Only populated after // first call to Next(). Not safe for concurrent access. _ = it.Response.(*longrunningpb.ListOperationsResponse) } } func ExampleMessagingClient_GetOperation() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.GetOperationRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#GetOperationRequest. } resp, err := c.GetOperation(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleMessagingClient_DeleteOperation() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.DeleteOperationRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#DeleteOperationRequest. } err = c.DeleteOperation(ctx, req) if err != nil { // TODO: Handle error. } } func ExampleMessagingClient_CancelOperation() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewMessagingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.CancelOperationRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#CancelOperationRequest. } err = c.CancelOperation(ctx, req) if err != nil { // TODO: Handle error. } } ================================================ FILE: client/sequence_client.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go_gapic. DO NOT EDIT. package client import ( "bytes" "context" "errors" "fmt" "log/slog" "math" "net/http" "net/url" "time" iampb "cloud.google.com/go/iam/apiv1/iampb" longrunningpb "cloud.google.com/go/longrunning/autogen/longrunningpb" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" gax "github.com/googleapis/gax-go/v2" "google.golang.org/api/iterator" "google.golang.org/api/option" "google.golang.org/api/option/internaloption" gtransport "google.golang.org/api/transport/grpc" httptransport "google.golang.org/api/transport/http" locationpb "google.golang.org/genproto/googleapis/cloud/location" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" ) var newSequenceClientHook clientHook // SequenceCallOptions contains the retry settings for each method of SequenceClient. type SequenceCallOptions struct { CreateSequence []gax.CallOption CreateStreamingSequence []gax.CallOption GetSequenceReport []gax.CallOption GetStreamingSequenceReport []gax.CallOption AttemptSequence []gax.CallOption AttemptStreamingSequence []gax.CallOption ListLocations []gax.CallOption GetLocation []gax.CallOption SetIamPolicy []gax.CallOption GetIamPolicy []gax.CallOption TestIamPermissions []gax.CallOption ListOperations []gax.CallOption GetOperation []gax.CallOption DeleteOperation []gax.CallOption CancelOperation []gax.CallOption } func defaultSequenceGRPCClientOptions() []option.ClientOption { return []option.ClientOption{ internaloption.WithDefaultEndpoint("localhost:7469"), internaloption.WithDefaultEndpointTemplate("localhost:7469"), internaloption.WithDefaultMTLSEndpoint("localhost:7469"), internaloption.WithDefaultUniverseDomain("googleapis.com"), internaloption.WithDefaultAudience("https://localhost/"), internaloption.WithDefaultScopes(DefaultAuthScopes()...), internaloption.EnableJwtWithScope(), internaloption.EnableNewAuthLibrary(), option.WithGRPCDialOption(grpc.WithDefaultCallOptions( grpc.MaxCallRecvMsgSize(math.MaxInt32))), } } func defaultSequenceCallOptions() *SequenceCallOptions { return &SequenceCallOptions{ CreateSequence: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, CreateStreamingSequence: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, GetSequenceReport: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, GetStreamingSequenceReport: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, AttemptSequence: []gax.CallOption{ gax.WithTimeout(10000 * time.Millisecond), gax.WithRetry(func() gax.Retryer { return gax.OnCodes([]codes.Code{ codes.Unavailable, codes.Unknown, }, gax.Backoff{ Initial: 100 * time.Millisecond, Max: 3000 * time.Millisecond, Multiplier: 2.00, }) }), }, AttemptStreamingSequence: []gax.CallOption{}, ListLocations: []gax.CallOption{}, GetLocation: []gax.CallOption{}, SetIamPolicy: []gax.CallOption{}, GetIamPolicy: []gax.CallOption{}, TestIamPermissions: []gax.CallOption{}, ListOperations: []gax.CallOption{}, GetOperation: []gax.CallOption{}, DeleteOperation: []gax.CallOption{}, CancelOperation: []gax.CallOption{}, } } func defaultSequenceRESTCallOptions() *SequenceCallOptions { return &SequenceCallOptions{ CreateSequence: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, CreateStreamingSequence: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, GetSequenceReport: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, GetStreamingSequenceReport: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, AttemptSequence: []gax.CallOption{ gax.WithTimeout(10000 * time.Millisecond), gax.WithRetry(func() gax.Retryer { return gax.OnHTTPCodes(gax.Backoff{ Initial: 100 * time.Millisecond, Max: 3000 * time.Millisecond, Multiplier: 2.00, }, http.StatusServiceUnavailable, http.StatusInternalServerError) }), }, AttemptStreamingSequence: []gax.CallOption{ gax.WithTimeout(5000 * time.Millisecond), }, ListLocations: []gax.CallOption{}, GetLocation: []gax.CallOption{}, SetIamPolicy: []gax.CallOption{}, GetIamPolicy: []gax.CallOption{}, TestIamPermissions: []gax.CallOption{}, ListOperations: []gax.CallOption{}, GetOperation: []gax.CallOption{}, DeleteOperation: []gax.CallOption{}, CancelOperation: []gax.CallOption{}, } } // internalSequenceClient is an interface that defines the methods available from Client Libraries Showcase API. type internalSequenceClient interface { Close() error setGoogleClientInfo(...string) Connection() *grpc.ClientConn CreateSequence(context.Context, *genprotopb.CreateSequenceRequest, ...gax.CallOption) (*genprotopb.Sequence, error) CreateStreamingSequence(context.Context, *genprotopb.CreateStreamingSequenceRequest, ...gax.CallOption) (*genprotopb.StreamingSequence, error) GetSequenceReport(context.Context, *genprotopb.GetSequenceReportRequest, ...gax.CallOption) (*genprotopb.SequenceReport, error) GetStreamingSequenceReport(context.Context, *genprotopb.GetStreamingSequenceReportRequest, ...gax.CallOption) (*genprotopb.StreamingSequenceReport, error) AttemptSequence(context.Context, *genprotopb.AttemptSequenceRequest, ...gax.CallOption) error AttemptStreamingSequence(context.Context, *genprotopb.AttemptStreamingSequenceRequest, ...gax.CallOption) (genprotopb.SequenceService_AttemptStreamingSequenceClient, error) ListLocations(context.Context, *locationpb.ListLocationsRequest, ...gax.CallOption) *LocationIterator GetLocation(context.Context, *locationpb.GetLocationRequest, ...gax.CallOption) (*locationpb.Location, error) SetIamPolicy(context.Context, *iampb.SetIamPolicyRequest, ...gax.CallOption) (*iampb.Policy, error) GetIamPolicy(context.Context, *iampb.GetIamPolicyRequest, ...gax.CallOption) (*iampb.Policy, error) TestIamPermissions(context.Context, *iampb.TestIamPermissionsRequest, ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error) ListOperations(context.Context, *longrunningpb.ListOperationsRequest, ...gax.CallOption) *OperationIterator GetOperation(context.Context, *longrunningpb.GetOperationRequest, ...gax.CallOption) (*longrunningpb.Operation, error) DeleteOperation(context.Context, *longrunningpb.DeleteOperationRequest, ...gax.CallOption) error CancelOperation(context.Context, *longrunningpb.CancelOperationRequest, ...gax.CallOption) error } // SequenceClient is a client for interacting with Client Libraries Showcase API. // Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls. // // A service that enables testing of unary and server streaming calls // by specifying a specific, predictable sequence of responses from the service type SequenceClient struct { // The internal transport-dependent client. internalClient internalSequenceClient // The call options for this service. CallOptions *SequenceCallOptions } // Wrapper methods routed to the internal client. // Close closes the connection to the API service. The user should invoke this when // the client is no longer required. func (c *SequenceClient) Close() error { return c.internalClient.Close() } // setGoogleClientInfo sets the name and version of the application in // the `x-goog-api-client` header passed on each request. Intended for // use by Google-written clients. func (c *SequenceClient) setGoogleClientInfo(keyval ...string) { c.internalClient.setGoogleClientInfo(keyval...) } // Connection returns a connection to the API service. // // Deprecated: Connections are now pooled so this method does not always // return the same resource. func (c *SequenceClient) Connection() *grpc.ClientConn { return c.internalClient.Connection() } // CreateSequence create a sequence of responses to be returned as unary calls func (c *SequenceClient) CreateSequence(ctx context.Context, req *genprotopb.CreateSequenceRequest, opts ...gax.CallOption) (*genprotopb.Sequence, error) { return c.internalClient.CreateSequence(ctx, req, opts...) } // CreateStreamingSequence creates a sequence of responses to be returned in a server streaming call func (c *SequenceClient) CreateStreamingSequence(ctx context.Context, req *genprotopb.CreateStreamingSequenceRequest, opts ...gax.CallOption) (*genprotopb.StreamingSequence, error) { return c.internalClient.CreateStreamingSequence(ctx, req, opts...) } // GetSequenceReport retrieves a sequence report which can be used to retrieve information about a // sequence of unary calls. func (c *SequenceClient) GetSequenceReport(ctx context.Context, req *genprotopb.GetSequenceReportRequest, opts ...gax.CallOption) (*genprotopb.SequenceReport, error) { return c.internalClient.GetSequenceReport(ctx, req, opts...) } // GetStreamingSequenceReport retrieves a sequence report which can be used to retrieve information // about a sequences of responses in a server streaming call. func (c *SequenceClient) GetStreamingSequenceReport(ctx context.Context, req *genprotopb.GetStreamingSequenceReportRequest, opts ...gax.CallOption) (*genprotopb.StreamingSequenceReport, error) { return c.internalClient.GetStreamingSequenceReport(ctx, req, opts...) } // AttemptSequence attempts a sequence of unary responses. func (c *SequenceClient) AttemptSequence(ctx context.Context, req *genprotopb.AttemptSequenceRequest, opts ...gax.CallOption) error { return c.internalClient.AttemptSequence(ctx, req, opts...) } // AttemptStreamingSequence attempts a server streaming call with a sequence of responses // Can be used to test retries and stream resumption logic // May not function as expected in HTTP mode due to when http statuses are sent // See https://github.com/googleapis/gapic-showcase/issues/1377 (at https://github.com/googleapis/gapic-showcase/issues/1377) for more details func (c *SequenceClient) AttemptStreamingSequence(ctx context.Context, req *genprotopb.AttemptStreamingSequenceRequest, opts ...gax.CallOption) (genprotopb.SequenceService_AttemptStreamingSequenceClient, error) { return c.internalClient.AttemptStreamingSequence(ctx, req, opts...) } // ListLocations is a utility method from google.cloud.location.Locations. func (c *SequenceClient) ListLocations(ctx context.Context, req *locationpb.ListLocationsRequest, opts ...gax.CallOption) *LocationIterator { return c.internalClient.ListLocations(ctx, req, opts...) } // GetLocation is a utility method from google.cloud.location.Locations. func (c *SequenceClient) GetLocation(ctx context.Context, req *locationpb.GetLocationRequest, opts ...gax.CallOption) (*locationpb.Location, error) { return c.internalClient.GetLocation(ctx, req, opts...) } // SetIamPolicy is a utility method from google.iam.v1.IAMPolicy. func (c *SequenceClient) SetIamPolicy(ctx context.Context, req *iampb.SetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { return c.internalClient.SetIamPolicy(ctx, req, opts...) } // GetIamPolicy is a utility method from google.iam.v1.IAMPolicy. func (c *SequenceClient) GetIamPolicy(ctx context.Context, req *iampb.GetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { return c.internalClient.GetIamPolicy(ctx, req, opts...) } // TestIamPermissions is a utility method from google.iam.v1.IAMPolicy. func (c *SequenceClient) TestIamPermissions(ctx context.Context, req *iampb.TestIamPermissionsRequest, opts ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error) { return c.internalClient.TestIamPermissions(ctx, req, opts...) } // ListOperations is a utility method from google.longrunning.Operations. func (c *SequenceClient) ListOperations(ctx context.Context, req *longrunningpb.ListOperationsRequest, opts ...gax.CallOption) *OperationIterator { return c.internalClient.ListOperations(ctx, req, opts...) } // GetOperation is a utility method from google.longrunning.Operations. func (c *SequenceClient) GetOperation(ctx context.Context, req *longrunningpb.GetOperationRequest, opts ...gax.CallOption) (*longrunningpb.Operation, error) { return c.internalClient.GetOperation(ctx, req, opts...) } // DeleteOperation is a utility method from google.longrunning.Operations. func (c *SequenceClient) DeleteOperation(ctx context.Context, req *longrunningpb.DeleteOperationRequest, opts ...gax.CallOption) error { return c.internalClient.DeleteOperation(ctx, req, opts...) } // CancelOperation is a utility method from google.longrunning.Operations. func (c *SequenceClient) CancelOperation(ctx context.Context, req *longrunningpb.CancelOperationRequest, opts ...gax.CallOption) error { return c.internalClient.CancelOperation(ctx, req, opts...) } // sequenceGRPCClient is a client for interacting with Client Libraries Showcase API over gRPC transport. // // Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls. type sequenceGRPCClient struct { // Connection pool of gRPC connections to the service. connPool gtransport.ConnPool // Points back to the CallOptions field of the containing SequenceClient CallOptions **SequenceCallOptions // The gRPC API client. sequenceClient genprotopb.SequenceServiceClient operationsClient longrunningpb.OperationsClient iamPolicyClient iampb.IAMPolicyClient locationsClient locationpb.LocationsClient // The x-goog-* metadata to be sent with each request. xGoogHeaders []string logger *slog.Logger } // NewSequenceClient creates a new sequence service client based on gRPC. // The returned client must be Closed when it is done being used to clean up its underlying connections. // // A service that enables testing of unary and server streaming calls // by specifying a specific, predictable sequence of responses from the service func NewSequenceClient(ctx context.Context, opts ...option.ClientOption) (*SequenceClient, error) { clientOpts := defaultSequenceGRPCClientOptions() if newSequenceClientHook != nil { hookOpts, err := newSequenceClientHook(ctx, clientHookParams{}) if err != nil { return nil, err } clientOpts = append(clientOpts, hookOpts...) } connPool, err := gtransport.DialPool(ctx, append(clientOpts, opts...)...) if err != nil { return nil, err } client := SequenceClient{CallOptions: defaultSequenceCallOptions()} c := &sequenceGRPCClient{ connPool: connPool, sequenceClient: genprotopb.NewSequenceServiceClient(connPool), CallOptions: &client.CallOptions, logger: internaloption.GetLogger(opts), operationsClient: longrunningpb.NewOperationsClient(connPool), iamPolicyClient: iampb.NewIAMPolicyClient(connPool), locationsClient: locationpb.NewLocationsClient(connPool), } c.setGoogleClientInfo() client.internalClient = c return &client, nil } // Connection returns a connection to the API service. // // Deprecated: Connections are now pooled so this method does not always // return the same resource. func (c *sequenceGRPCClient) Connection() *grpc.ClientConn { return c.connPool.Conn() } // setGoogleClientInfo sets the name and version of the application in // the `x-goog-api-client` header passed on each request. Intended for // use by Google-written clients. func (c *sequenceGRPCClient) setGoogleClientInfo(keyval ...string) { kv := append([]string{"gl-go", gax.GoVersion}, keyval...) kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "grpc", grpc.Version, "pb", protoVersion) c.xGoogHeaders = []string{ "x-goog-api-client", gax.XGoogHeader(kv...), } } // Close closes the connection to the API service. The user should invoke this when // the client is no longer required. func (c *sequenceGRPCClient) Close() error { return c.connPool.Close() } // Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls. type sequenceRESTClient struct { // The http endpoint to connect to. endpoint string // The http client. httpClient *http.Client // The x-goog-* headers to be sent with each request. xGoogHeaders []string // Points back to the CallOptions field of the containing SequenceClient CallOptions **SequenceCallOptions logger *slog.Logger } // NewSequenceRESTClient creates a new sequence service rest client. // // A service that enables testing of unary and server streaming calls // by specifying a specific, predictable sequence of responses from the service func NewSequenceRESTClient(ctx context.Context, opts ...option.ClientOption) (*SequenceClient, error) { clientOpts := append(defaultSequenceRESTClientOptions(), opts...) httpClient, endpoint, err := httptransport.NewClient(ctx, clientOpts...) if err != nil { return nil, err } callOpts := defaultSequenceRESTCallOptions() c := &sequenceRESTClient{ endpoint: endpoint, httpClient: httpClient, CallOptions: &callOpts, logger: internaloption.GetLogger(opts), } c.setGoogleClientInfo() return &SequenceClient{internalClient: c, CallOptions: callOpts}, nil } func defaultSequenceRESTClientOptions() []option.ClientOption { return []option.ClientOption{ internaloption.WithDefaultEndpoint("https://localhost:7469"), internaloption.WithDefaultEndpointTemplate("https://localhost:7469"), internaloption.WithDefaultMTLSEndpoint("https://localhost:7469"), internaloption.WithDefaultUniverseDomain("googleapis.com"), internaloption.WithDefaultAudience("https://localhost/"), internaloption.WithDefaultScopes(DefaultAuthScopes()...), internaloption.EnableNewAuthLibrary(), } } // setGoogleClientInfo sets the name and version of the application in // the `x-goog-api-client` header passed on each request. Intended for // use by Google-written clients. func (c *sequenceRESTClient) setGoogleClientInfo(keyval ...string) { kv := append([]string{"gl-go", gax.GoVersion}, keyval...) kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "rest", "UNKNOWN", "pb", protoVersion) c.xGoogHeaders = []string{ "x-goog-api-client", gax.XGoogHeader(kv...), } } // Close closes the connection to the API service. The user should invoke this when // the client is no longer required. func (c *sequenceRESTClient) Close() error { // Replace httpClient with nil to force cleanup. c.httpClient = nil return nil } // Connection returns a connection to the API service. // // Deprecated: This method always returns nil. func (c *sequenceRESTClient) Connection() *grpc.ClientConn { return nil } func (c *sequenceGRPCClient) CreateSequence(ctx context.Context, req *genprotopb.CreateSequenceRequest, opts ...gax.CallOption) (*genprotopb.Sequence, error) { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).CreateSequence[0:len((*c.CallOptions).CreateSequence):len((*c.CallOptions).CreateSequence)], opts...) var resp *genprotopb.Sequence err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.sequenceClient.CreateSequence, req, settings.GRPC, c.logger, "CreateSequence") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *sequenceGRPCClient) CreateStreamingSequence(ctx context.Context, req *genprotopb.CreateStreamingSequenceRequest, opts ...gax.CallOption) (*genprotopb.StreamingSequence, error) { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).CreateStreamingSequence[0:len((*c.CallOptions).CreateStreamingSequence):len((*c.CallOptions).CreateStreamingSequence)], opts...) var resp *genprotopb.StreamingSequence err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.sequenceClient.CreateStreamingSequence, req, settings.GRPC, c.logger, "CreateStreamingSequence") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *sequenceGRPCClient) GetSequenceReport(ctx context.Context, req *genprotopb.GetSequenceReportRequest, opts ...gax.CallOption) (*genprotopb.SequenceReport, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).GetSequenceReport[0:len((*c.CallOptions).GetSequenceReport):len((*c.CallOptions).GetSequenceReport)], opts...) var resp *genprotopb.SequenceReport err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.sequenceClient.GetSequenceReport, req, settings.GRPC, c.logger, "GetSequenceReport") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *sequenceGRPCClient) GetStreamingSequenceReport(ctx context.Context, req *genprotopb.GetStreamingSequenceReportRequest, opts ...gax.CallOption) (*genprotopb.StreamingSequenceReport, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).GetStreamingSequenceReport[0:len((*c.CallOptions).GetStreamingSequenceReport):len((*c.CallOptions).GetStreamingSequenceReport)], opts...) var resp *genprotopb.StreamingSequenceReport err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.sequenceClient.GetStreamingSequenceReport, req, settings.GRPC, c.logger, "GetStreamingSequenceReport") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *sequenceGRPCClient) AttemptSequence(ctx context.Context, req *genprotopb.AttemptSequenceRequest, opts ...gax.CallOption) error { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).AttemptSequence[0:len((*c.CallOptions).AttemptSequence):len((*c.CallOptions).AttemptSequence)], opts...) err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error _, err = executeRPC(ctx, c.sequenceClient.AttemptSequence, req, settings.GRPC, c.logger, "AttemptSequence") return err }, opts...) return err } func (c *sequenceGRPCClient) AttemptStreamingSequence(ctx context.Context, req *genprotopb.AttemptStreamingSequenceRequest, opts ...gax.CallOption) (genprotopb.SequenceService_AttemptStreamingSequenceClient, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).AttemptStreamingSequence[0:len((*c.CallOptions).AttemptStreamingSequence):len((*c.CallOptions).AttemptStreamingSequence)], opts...) var resp genprotopb.SequenceService_AttemptStreamingSequenceClient err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error c.logger.DebugContext(ctx, "api streaming client request", "serviceName", serviceName, "rpcName", "AttemptStreamingSequence") resp, err = c.sequenceClient.AttemptStreamingSequence(ctx, req, settings.GRPC...) c.logger.DebugContext(ctx, "api streaming client response", "serviceName", serviceName, "rpcName", "AttemptStreamingSequence") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *sequenceGRPCClient) ListLocations(ctx context.Context, req *locationpb.ListLocationsRequest, opts ...gax.CallOption) *LocationIterator { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).ListLocations[0:len((*c.CallOptions).ListLocations):len((*c.CallOptions).ListLocations)], opts...) it := &LocationIterator{} req = proto.Clone(req).(*locationpb.ListLocationsRequest) it.InternalFetch = func(pageSize int, pageToken string) ([]*locationpb.Location, string, error) { resp := &locationpb.ListLocationsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.locationsClient.ListLocations, req, settings.GRPC, c.logger, "ListLocations") return err }, opts...) if err != nil { return nil, "", err } it.Response = resp return resp.GetLocations(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } func (c *sequenceGRPCClient) GetLocation(ctx context.Context, req *locationpb.GetLocationRequest, opts ...gax.CallOption) (*locationpb.Location, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).GetLocation[0:len((*c.CallOptions).GetLocation):len((*c.CallOptions).GetLocation)], opts...) var resp *locationpb.Location err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.locationsClient.GetLocation, req, settings.GRPC, c.logger, "GetLocation") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *sequenceGRPCClient) SetIamPolicy(ctx context.Context, req *iampb.SetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).SetIamPolicy[0:len((*c.CallOptions).SetIamPolicy):len((*c.CallOptions).SetIamPolicy)], opts...) var resp *iampb.Policy err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.iamPolicyClient.SetIamPolicy, req, settings.GRPC, c.logger, "SetIamPolicy") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *sequenceGRPCClient) GetIamPolicy(ctx context.Context, req *iampb.GetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).GetIamPolicy[0:len((*c.CallOptions).GetIamPolicy):len((*c.CallOptions).GetIamPolicy)], opts...) var resp *iampb.Policy err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.iamPolicyClient.GetIamPolicy, req, settings.GRPC, c.logger, "GetIamPolicy") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *sequenceGRPCClient) TestIamPermissions(ctx context.Context, req *iampb.TestIamPermissionsRequest, opts ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).TestIamPermissions[0:len((*c.CallOptions).TestIamPermissions):len((*c.CallOptions).TestIamPermissions)], opts...) var resp *iampb.TestIamPermissionsResponse err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.iamPolicyClient.TestIamPermissions, req, settings.GRPC, c.logger, "TestIamPermissions") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *sequenceGRPCClient) ListOperations(ctx context.Context, req *longrunningpb.ListOperationsRequest, opts ...gax.CallOption) *OperationIterator { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).ListOperations[0:len((*c.CallOptions).ListOperations):len((*c.CallOptions).ListOperations)], opts...) it := &OperationIterator{} req = proto.Clone(req).(*longrunningpb.ListOperationsRequest) it.InternalFetch = func(pageSize int, pageToken string) ([]*longrunningpb.Operation, string, error) { resp := &longrunningpb.ListOperationsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.operationsClient.ListOperations, req, settings.GRPC, c.logger, "ListOperations") return err }, opts...) if err != nil { return nil, "", err } it.Response = resp return resp.GetOperations(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } func (c *sequenceGRPCClient) GetOperation(ctx context.Context, req *longrunningpb.GetOperationRequest, opts ...gax.CallOption) (*longrunningpb.Operation, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).GetOperation[0:len((*c.CallOptions).GetOperation):len((*c.CallOptions).GetOperation)], opts...) var resp *longrunningpb.Operation err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.operationsClient.GetOperation, req, settings.GRPC, c.logger, "GetOperation") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *sequenceGRPCClient) DeleteOperation(ctx context.Context, req *longrunningpb.DeleteOperationRequest, opts ...gax.CallOption) error { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).DeleteOperation[0:len((*c.CallOptions).DeleteOperation):len((*c.CallOptions).DeleteOperation)], opts...) err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error _, err = executeRPC(ctx, c.operationsClient.DeleteOperation, req, settings.GRPC, c.logger, "DeleteOperation") return err }, opts...) return err } func (c *sequenceGRPCClient) CancelOperation(ctx context.Context, req *longrunningpb.CancelOperationRequest, opts ...gax.CallOption) error { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).CancelOperation[0:len((*c.CallOptions).CancelOperation):len((*c.CallOptions).CancelOperation)], opts...) err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error _, err = executeRPC(ctx, c.operationsClient.CancelOperation, req, settings.GRPC, c.logger, "CancelOperation") return err }, opts...) return err } // CreateSequence create a sequence of responses to be returned as unary calls func (c *sequenceRESTClient) CreateSequence(ctx context.Context, req *genprotopb.CreateSequenceRequest, opts ...gax.CallOption) (*genprotopb.Sequence, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} body := req.GetSequence() jsonReq, err := m.Marshal(body) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/sequences") // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).CreateSequence[0:len((*c.CallOptions).CreateSequence):len((*c.CallOptions).CreateSequence)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.Sequence{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "CreateSequence") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // CreateStreamingSequence creates a sequence of responses to be returned in a server streaming call func (c *sequenceRESTClient) CreateStreamingSequence(ctx context.Context, req *genprotopb.CreateStreamingSequenceRequest, opts ...gax.CallOption) (*genprotopb.StreamingSequence, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} body := req.GetStreamingSequence() jsonReq, err := m.Marshal(body) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/streamingSequences") // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).CreateStreamingSequence[0:len((*c.CallOptions).CreateStreamingSequence):len((*c.CallOptions).CreateStreamingSequence)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.StreamingSequence{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "CreateStreamingSequence") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // GetSequenceReport retrieves a sequence report which can be used to retrieve information about a // sequence of unary calls. func (c *sequenceRESTClient) GetSequenceReport(ctx context.Context, req *genprotopb.GetSequenceReportRequest, opts ...gax.CallOption) (*genprotopb.SequenceReport, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).GetSequenceReport[0:len((*c.CallOptions).GetSequenceReport):len((*c.CallOptions).GetSequenceReport)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.SequenceReport{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "GetSequenceReport") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // GetStreamingSequenceReport retrieves a sequence report which can be used to retrieve information // about a sequences of responses in a server streaming call. func (c *sequenceRESTClient) GetStreamingSequenceReport(ctx context.Context, req *genprotopb.GetStreamingSequenceReportRequest, opts ...gax.CallOption) (*genprotopb.StreamingSequenceReport, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).GetStreamingSequenceReport[0:len((*c.CallOptions).GetStreamingSequenceReport):len((*c.CallOptions).GetStreamingSequenceReport)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.StreamingSequenceReport{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "GetStreamingSequenceReport") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // AttemptSequence attempts a sequence of unary responses. func (c *sequenceRESTClient) AttemptSequence(ctx context.Context, req *genprotopb.AttemptSequenceRequest, opts ...gax.CallOption) error { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) return gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers _, err = executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "AttemptSequence") return err }, opts...) } // AttemptStreamingSequence attempts a server streaming call with a sequence of responses // Can be used to test retries and stream resumption logic // May not function as expected in HTTP mode due to when http statuses are sent // See https://github.com/googleapis/gapic-showcase/issues/1377 (at https://github.com/googleapis/gapic-showcase/issues/1377) for more details func (c *sequenceRESTClient) AttemptStreamingSequence(ctx context.Context, req *genprotopb.AttemptStreamingSequenceRequest, opts ...gax.CallOption) (genprotopb.SequenceService_AttemptStreamingSequenceClient, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:stream", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) var streamClient *attemptStreamingSequenceRESTStreamClient e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers httpRsp, err := executeStreamingHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "AttemptStreamingSequence") if err != nil { return err } streamClient = &attemptStreamingSequenceRESTStreamClient{ ctx: ctx, md: metadata.MD(httpRsp.Header), stream: gax.NewProtoJSONStreamReader(httpRsp.Body, (&genprotopb.AttemptStreamingSequenceResponse{}).ProtoReflect().Type()), } return nil }, opts...) return streamClient, e } // attemptStreamingSequenceRESTStreamClient is the stream client used to consume the server stream created by // the REST implementation of AttemptStreamingSequence. type attemptStreamingSequenceRESTStreamClient struct { ctx context.Context md metadata.MD stream *gax.ProtoJSONStream } func (c *attemptStreamingSequenceRESTStreamClient) Recv() (*genprotopb.AttemptStreamingSequenceResponse, error) { if err := c.ctx.Err(); err != nil { defer c.stream.Close() return nil, err } msg, err := c.stream.Recv() if err != nil { defer c.stream.Close() return nil, err } res := msg.(*genprotopb.AttemptStreamingSequenceResponse) return res, nil } func (c *attemptStreamingSequenceRESTStreamClient) Header() (metadata.MD, error) { return c.md, nil } func (c *attemptStreamingSequenceRESTStreamClient) Trailer() metadata.MD { return c.md } func (c *attemptStreamingSequenceRESTStreamClient) CloseSend() error { // This is a no-op to fulfill the interface. return errors.New("this method is not implemented for a server-stream") } func (c *attemptStreamingSequenceRESTStreamClient) Context() context.Context { return c.ctx } func (c *attemptStreamingSequenceRESTStreamClient) SendMsg(m interface{}) error { // This is a no-op to fulfill the interface. return errors.New("this method is not implemented for a server-stream") } func (c *attemptStreamingSequenceRESTStreamClient) RecvMsg(m interface{}) error { // This is a no-op to fulfill the interface. return errors.New("this method is not implemented, use Recv") } // ListLocations is a utility method from google.cloud.location.Locations. func (c *sequenceRESTClient) ListLocations(ctx context.Context, req *locationpb.ListLocationsRequest, opts ...gax.CallOption) *LocationIterator { it := &LocationIterator{} req = proto.Clone(req).(*locationpb.ListLocationsRequest) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} it.InternalFetch = func(pageSize int, pageToken string) ([]*locationpb.Location, string, error) { resp := &locationpb.ListLocationsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, "", err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v/locations", req.GetName()) params := url.Values{} if req.GetFilter() != "" { params.Add("filter", fmt.Sprintf("%v", req.GetFilter())) } if req.GetPageSize() != 0 { params.Add("pageSize", fmt.Sprintf("%v", req.GetPageSize())) } if req.GetPageToken() != "" { params.Add("pageToken", fmt.Sprintf("%v", req.GetPageToken())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "ListLocations") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, "", e } it.Response = resp return resp.GetLocations(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } // GetLocation is a utility method from google.cloud.location.Locations. func (c *sequenceRESTClient) GetLocation(ctx context.Context, req *locationpb.GetLocationRequest, opts ...gax.CallOption) (*locationpb.Location, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).GetLocation[0:len((*c.CallOptions).GetLocation):len((*c.CallOptions).GetLocation)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &locationpb.Location{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "GetLocation") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // SetIamPolicy is a utility method from google.iam.v1.IAMPolicy. func (c *sequenceRESTClient) SetIamPolicy(ctx context.Context, req *iampb.SetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:setIamPolicy", req.GetResource()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).SetIamPolicy[0:len((*c.CallOptions).SetIamPolicy):len((*c.CallOptions).SetIamPolicy)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &iampb.Policy{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "SetIamPolicy") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // GetIamPolicy is a utility method from google.iam.v1.IAMPolicy. func (c *sequenceRESTClient) GetIamPolicy(ctx context.Context, req *iampb.GetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:getIamPolicy", req.GetResource()) params := url.Values{} if req.GetOptions().GetRequestedPolicyVersion() != 0 { params.Add("options.requestedPolicyVersion", fmt.Sprintf("%v", req.GetOptions().GetRequestedPolicyVersion())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).GetIamPolicy[0:len((*c.CallOptions).GetIamPolicy):len((*c.CallOptions).GetIamPolicy)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &iampb.Policy{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "GetIamPolicy") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // TestIamPermissions is a utility method from google.iam.v1.IAMPolicy. func (c *sequenceRESTClient) TestIamPermissions(ctx context.Context, req *iampb.TestIamPermissionsRequest, opts ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:testIamPermissions", req.GetResource()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).TestIamPermissions[0:len((*c.CallOptions).TestIamPermissions):len((*c.CallOptions).TestIamPermissions)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &iampb.TestIamPermissionsResponse{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "TestIamPermissions") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // ListOperations is a utility method from google.longrunning.Operations. func (c *sequenceRESTClient) ListOperations(ctx context.Context, req *longrunningpb.ListOperationsRequest, opts ...gax.CallOption) *OperationIterator { it := &OperationIterator{} req = proto.Clone(req).(*longrunningpb.ListOperationsRequest) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} it.InternalFetch = func(pageSize int, pageToken string) ([]*longrunningpb.Operation, string, error) { resp := &longrunningpb.ListOperationsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, "", err } baseUrl.Path += fmt.Sprintf("/v1beta1/operations") params := url.Values{} if req.GetFilter() != "" { params.Add("filter", fmt.Sprintf("%v", req.GetFilter())) } if req.GetName() != "" { params.Add("name", fmt.Sprintf("%v", req.GetName())) } if req.GetPageSize() != 0 { params.Add("pageSize", fmt.Sprintf("%v", req.GetPageSize())) } if req.GetPageToken() != "" { params.Add("pageToken", fmt.Sprintf("%v", req.GetPageToken())) } if req.GetReturnPartialSuccess() { params.Add("returnPartialSuccess", fmt.Sprintf("%v", req.GetReturnPartialSuccess())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "ListOperations") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, "", e } it.Response = resp return resp.GetOperations(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } // GetOperation is a utility method from google.longrunning.Operations. func (c *sequenceRESTClient) GetOperation(ctx context.Context, req *longrunningpb.GetOperationRequest, opts ...gax.CallOption) (*longrunningpb.Operation, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).GetOperation[0:len((*c.CallOptions).GetOperation):len((*c.CallOptions).GetOperation)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &longrunningpb.Operation{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "GetOperation") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // DeleteOperation is a utility method from google.longrunning.Operations. func (c *sequenceRESTClient) DeleteOperation(ctx context.Context, req *longrunningpb.DeleteOperationRequest, opts ...gax.CallOption) error { baseUrl, err := url.Parse(c.endpoint) if err != nil { return err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) return gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("DELETE", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers _, err = executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "DeleteOperation") return err }, opts...) } // CancelOperation is a utility method from google.longrunning.Operations. func (c *sequenceRESTClient) CancelOperation(ctx context.Context, req *longrunningpb.CancelOperationRequest, opts ...gax.CallOption) error { baseUrl, err := url.Parse(c.endpoint) if err != nil { return err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:cancel", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) return gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers _, err = executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "CancelOperation") return err }, opts...) } ================================================ FILE: client/sequence_client_example_go123_test.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go_gapic. DO NOT EDIT. //go:build go1.23 package client_test import ( "context" longrunningpb "cloud.google.com/go/longrunning/autogen/longrunningpb" client "github.com/googleapis/gapic-showcase/client" locationpb "google.golang.org/genproto/googleapis/cloud/location" ) func ExampleSequenceClient_ListLocations_all() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewSequenceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &locationpb.ListLocationsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/google.golang.org/genproto/googleapis/cloud/location#ListLocationsRequest. } for resp, err := range c.ListLocations(ctx, req).All() { if err != nil { // TODO: Handle error and break/return/continue. Iteration will stop after any error. } // TODO: Use resp. _ = resp } } func ExampleSequenceClient_ListOperations_all() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewSequenceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.ListOperationsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#ListOperationsRequest. } for resp, err := range c.ListOperations(ctx, req).All() { if err != nil { // TODO: Handle error and break/return/continue. Iteration will stop after any error. } // TODO: Use resp. _ = resp } } ================================================ FILE: client/sequence_client_example_test.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go_gapic. DO NOT EDIT. package client_test import ( "context" iampb "cloud.google.com/go/iam/apiv1/iampb" longrunningpb "cloud.google.com/go/longrunning/autogen/longrunningpb" client "github.com/googleapis/gapic-showcase/client" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "google.golang.org/api/iterator" locationpb "google.golang.org/genproto/googleapis/cloud/location" ) func ExampleNewSequenceClient() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewSequenceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() // TODO: Use client. _ = c } func ExampleNewSequenceRESTClient() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewSequenceRESTClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() // TODO: Use client. _ = c } func ExampleSequenceClient_AttemptSequence() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewSequenceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.AttemptSequenceRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#AttemptSequenceRequest. } err = c.AttemptSequence(ctx, req) if err != nil { // TODO: Handle error. } } func ExampleSequenceClient_CreateSequence() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewSequenceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.CreateSequenceRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#CreateSequenceRequest. } resp, err := c.CreateSequence(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleSequenceClient_CreateStreamingSequence() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewSequenceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.CreateStreamingSequenceRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#CreateStreamingSequenceRequest. } resp, err := c.CreateStreamingSequence(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleSequenceClient_GetSequenceReport() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewSequenceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.GetSequenceReportRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#GetSequenceReportRequest. } resp, err := c.GetSequenceReport(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleSequenceClient_GetStreamingSequenceReport() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewSequenceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.GetStreamingSequenceReportRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#GetStreamingSequenceReportRequest. } resp, err := c.GetStreamingSequenceReport(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleSequenceClient_ListLocations() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewSequenceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &locationpb.ListLocationsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/google.golang.org/genproto/googleapis/cloud/location#ListLocationsRequest. } it := c.ListLocations(ctx, req) for { resp, err := it.Next() if err == iterator.Done { break } if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp // If you need to access the underlying RPC response, // you can do so by casting the `Response` as below. // Otherwise, remove this line. Only populated after // first call to Next(). Not safe for concurrent access. _ = it.Response.(*locationpb.ListLocationsResponse) } } func ExampleSequenceClient_GetLocation() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewSequenceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &locationpb.GetLocationRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/google.golang.org/genproto/googleapis/cloud/location#GetLocationRequest. } resp, err := c.GetLocation(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleSequenceClient_SetIamPolicy() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewSequenceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &iampb.SetIamPolicyRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/iam/apiv1/iampb#SetIamPolicyRequest. } resp, err := c.SetIamPolicy(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleSequenceClient_GetIamPolicy() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewSequenceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &iampb.GetIamPolicyRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/iam/apiv1/iampb#GetIamPolicyRequest. } resp, err := c.GetIamPolicy(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleSequenceClient_TestIamPermissions() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewSequenceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &iampb.TestIamPermissionsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/iam/apiv1/iampb#TestIamPermissionsRequest. } resp, err := c.TestIamPermissions(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleSequenceClient_ListOperations() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewSequenceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.ListOperationsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#ListOperationsRequest. } it := c.ListOperations(ctx, req) for { resp, err := it.Next() if err == iterator.Done { break } if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp // If you need to access the underlying RPC response, // you can do so by casting the `Response` as below. // Otherwise, remove this line. Only populated after // first call to Next(). Not safe for concurrent access. _ = it.Response.(*longrunningpb.ListOperationsResponse) } } func ExampleSequenceClient_GetOperation() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewSequenceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.GetOperationRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#GetOperationRequest. } resp, err := c.GetOperation(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleSequenceClient_DeleteOperation() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewSequenceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.DeleteOperationRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#DeleteOperationRequest. } err = c.DeleteOperation(ctx, req) if err != nil { // TODO: Handle error. } } func ExampleSequenceClient_CancelOperation() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewSequenceClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.CancelOperationRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#CancelOperationRequest. } err = c.CancelOperation(ctx, req) if err != nil { // TODO: Handle error. } } ================================================ FILE: client/testing_client.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go_gapic. DO NOT EDIT. package client import ( "bytes" "context" "fmt" "log/slog" "math" "net/http" "net/url" iampb "cloud.google.com/go/iam/apiv1/iampb" longrunningpb "cloud.google.com/go/longrunning/autogen/longrunningpb" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" gax "github.com/googleapis/gax-go/v2" "google.golang.org/api/iterator" "google.golang.org/api/option" "google.golang.org/api/option/internaloption" gtransport "google.golang.org/api/transport/grpc" httptransport "google.golang.org/api/transport/http" locationpb "google.golang.org/genproto/googleapis/cloud/location" "google.golang.org/grpc" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" ) var newTestingClientHook clientHook // TestingCallOptions contains the retry settings for each method of TestingClient. type TestingCallOptions struct { CreateSession []gax.CallOption GetSession []gax.CallOption ListSessions []gax.CallOption DeleteSession []gax.CallOption ReportSession []gax.CallOption ListTests []gax.CallOption DeleteTest []gax.CallOption VerifyTest []gax.CallOption ListLocations []gax.CallOption GetLocation []gax.CallOption SetIamPolicy []gax.CallOption GetIamPolicy []gax.CallOption TestIamPermissions []gax.CallOption ListOperations []gax.CallOption GetOperation []gax.CallOption DeleteOperation []gax.CallOption CancelOperation []gax.CallOption } func defaultTestingGRPCClientOptions() []option.ClientOption { return []option.ClientOption{ internaloption.WithDefaultEndpoint("localhost:7469"), internaloption.WithDefaultEndpointTemplate("localhost:7469"), internaloption.WithDefaultMTLSEndpoint("localhost:7469"), internaloption.WithDefaultUniverseDomain("googleapis.com"), internaloption.WithDefaultAudience("https://localhost/"), internaloption.WithDefaultScopes(DefaultAuthScopes()...), internaloption.EnableJwtWithScope(), internaloption.EnableNewAuthLibrary(), option.WithGRPCDialOption(grpc.WithDefaultCallOptions( grpc.MaxCallRecvMsgSize(math.MaxInt32))), } } func defaultTestingCallOptions() *TestingCallOptions { return &TestingCallOptions{ CreateSession: []gax.CallOption{}, GetSession: []gax.CallOption{}, ListSessions: []gax.CallOption{}, DeleteSession: []gax.CallOption{}, ReportSession: []gax.CallOption{}, ListTests: []gax.CallOption{}, DeleteTest: []gax.CallOption{}, VerifyTest: []gax.CallOption{}, ListLocations: []gax.CallOption{}, GetLocation: []gax.CallOption{}, SetIamPolicy: []gax.CallOption{}, GetIamPolicy: []gax.CallOption{}, TestIamPermissions: []gax.CallOption{}, ListOperations: []gax.CallOption{}, GetOperation: []gax.CallOption{}, DeleteOperation: []gax.CallOption{}, CancelOperation: []gax.CallOption{}, } } func defaultTestingRESTCallOptions() *TestingCallOptions { return &TestingCallOptions{ CreateSession: []gax.CallOption{}, GetSession: []gax.CallOption{}, ListSessions: []gax.CallOption{}, DeleteSession: []gax.CallOption{}, ReportSession: []gax.CallOption{}, ListTests: []gax.CallOption{}, DeleteTest: []gax.CallOption{}, VerifyTest: []gax.CallOption{}, ListLocations: []gax.CallOption{}, GetLocation: []gax.CallOption{}, SetIamPolicy: []gax.CallOption{}, GetIamPolicy: []gax.CallOption{}, TestIamPermissions: []gax.CallOption{}, ListOperations: []gax.CallOption{}, GetOperation: []gax.CallOption{}, DeleteOperation: []gax.CallOption{}, CancelOperation: []gax.CallOption{}, } } // internalTestingClient is an interface that defines the methods available from Client Libraries Showcase API. type internalTestingClient interface { Close() error setGoogleClientInfo(...string) Connection() *grpc.ClientConn CreateSession(context.Context, *genprotopb.CreateSessionRequest, ...gax.CallOption) (*genprotopb.Session, error) GetSession(context.Context, *genprotopb.GetSessionRequest, ...gax.CallOption) (*genprotopb.Session, error) ListSessions(context.Context, *genprotopb.ListSessionsRequest, ...gax.CallOption) *SessionIterator DeleteSession(context.Context, *genprotopb.DeleteSessionRequest, ...gax.CallOption) error ReportSession(context.Context, *genprotopb.ReportSessionRequest, ...gax.CallOption) (*genprotopb.ReportSessionResponse, error) ListTests(context.Context, *genprotopb.ListTestsRequest, ...gax.CallOption) *TestIterator DeleteTest(context.Context, *genprotopb.DeleteTestRequest, ...gax.CallOption) error VerifyTest(context.Context, *genprotopb.VerifyTestRequest, ...gax.CallOption) (*genprotopb.VerifyTestResponse, error) ListLocations(context.Context, *locationpb.ListLocationsRequest, ...gax.CallOption) *LocationIterator GetLocation(context.Context, *locationpb.GetLocationRequest, ...gax.CallOption) (*locationpb.Location, error) SetIamPolicy(context.Context, *iampb.SetIamPolicyRequest, ...gax.CallOption) (*iampb.Policy, error) GetIamPolicy(context.Context, *iampb.GetIamPolicyRequest, ...gax.CallOption) (*iampb.Policy, error) TestIamPermissions(context.Context, *iampb.TestIamPermissionsRequest, ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error) ListOperations(context.Context, *longrunningpb.ListOperationsRequest, ...gax.CallOption) *OperationIterator GetOperation(context.Context, *longrunningpb.GetOperationRequest, ...gax.CallOption) (*longrunningpb.Operation, error) DeleteOperation(context.Context, *longrunningpb.DeleteOperationRequest, ...gax.CallOption) error CancelOperation(context.Context, *longrunningpb.CancelOperationRequest, ...gax.CallOption) error } // TestingClient is a client for interacting with Client Libraries Showcase API. // Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls. // // A service to facilitate running discrete sets of tests // against Showcase. // Adding this comment with special characters for comment formatting tests: // // (abra->kadabra->alakazam) // // Nonsense: pokemon/*/psychic/* type TestingClient struct { // The internal transport-dependent client. internalClient internalTestingClient // The call options for this service. CallOptions *TestingCallOptions } // Wrapper methods routed to the internal client. // Close closes the connection to the API service. The user should invoke this when // the client is no longer required. func (c *TestingClient) Close() error { return c.internalClient.Close() } // setGoogleClientInfo sets the name and version of the application in // the `x-goog-api-client` header passed on each request. Intended for // use by Google-written clients. func (c *TestingClient) setGoogleClientInfo(keyval ...string) { c.internalClient.setGoogleClientInfo(keyval...) } // Connection returns a connection to the API service. // // Deprecated: Connections are now pooled so this method does not always // return the same resource. func (c *TestingClient) Connection() *grpc.ClientConn { return c.internalClient.Connection() } // CreateSession creates a new testing session. // Adding this comment with special characters for comment formatting tests: // // (abra->kadabra->alakazam) // // Nonsense: pokemon/*/psychic/* func (c *TestingClient) CreateSession(ctx context.Context, req *genprotopb.CreateSessionRequest, opts ...gax.CallOption) (*genprotopb.Session, error) { return c.internalClient.CreateSession(ctx, req, opts...) } // GetSession gets a testing session. func (c *TestingClient) GetSession(ctx context.Context, req *genprotopb.GetSessionRequest, opts ...gax.CallOption) (*genprotopb.Session, error) { return c.internalClient.GetSession(ctx, req, opts...) } // ListSessions lists the current test sessions. func (c *TestingClient) ListSessions(ctx context.Context, req *genprotopb.ListSessionsRequest, opts ...gax.CallOption) *SessionIterator { return c.internalClient.ListSessions(ctx, req, opts...) } // DeleteSession delete a test session. func (c *TestingClient) DeleteSession(ctx context.Context, req *genprotopb.DeleteSessionRequest, opts ...gax.CallOption) error { return c.internalClient.DeleteSession(ctx, req, opts...) } // ReportSession report on the status of a session. // This generates a report detailing which tests have been completed, // and an overall rollup. func (c *TestingClient) ReportSession(ctx context.Context, req *genprotopb.ReportSessionRequest, opts ...gax.CallOption) (*genprotopb.ReportSessionResponse, error) { return c.internalClient.ReportSession(ctx, req, opts...) } // ListTests list the tests of a sessesion. func (c *TestingClient) ListTests(ctx context.Context, req *genprotopb.ListTestsRequest, opts ...gax.CallOption) *TestIterator { return c.internalClient.ListTests(ctx, req, opts...) } // DeleteTest explicitly decline to implement a test. // // This removes the test from subsequent ListTests calls, and // attempting to do the test will error. // // This method will error if attempting to delete a required test. func (c *TestingClient) DeleteTest(ctx context.Context, req *genprotopb.DeleteTestRequest, opts ...gax.CallOption) error { return c.internalClient.DeleteTest(ctx, req, opts...) } // VerifyTest register a response to a test. // // In cases where a test involves registering a final answer at the // end of the test, this method provides the means to do so. func (c *TestingClient) VerifyTest(ctx context.Context, req *genprotopb.VerifyTestRequest, opts ...gax.CallOption) (*genprotopb.VerifyTestResponse, error) { return c.internalClient.VerifyTest(ctx, req, opts...) } // ListLocations is a utility method from google.cloud.location.Locations. func (c *TestingClient) ListLocations(ctx context.Context, req *locationpb.ListLocationsRequest, opts ...gax.CallOption) *LocationIterator { return c.internalClient.ListLocations(ctx, req, opts...) } // GetLocation is a utility method from google.cloud.location.Locations. func (c *TestingClient) GetLocation(ctx context.Context, req *locationpb.GetLocationRequest, opts ...gax.CallOption) (*locationpb.Location, error) { return c.internalClient.GetLocation(ctx, req, opts...) } // SetIamPolicy is a utility method from google.iam.v1.IAMPolicy. func (c *TestingClient) SetIamPolicy(ctx context.Context, req *iampb.SetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { return c.internalClient.SetIamPolicy(ctx, req, opts...) } // GetIamPolicy is a utility method from google.iam.v1.IAMPolicy. func (c *TestingClient) GetIamPolicy(ctx context.Context, req *iampb.GetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { return c.internalClient.GetIamPolicy(ctx, req, opts...) } // TestIamPermissions is a utility method from google.iam.v1.IAMPolicy. func (c *TestingClient) TestIamPermissions(ctx context.Context, req *iampb.TestIamPermissionsRequest, opts ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error) { return c.internalClient.TestIamPermissions(ctx, req, opts...) } // ListOperations is a utility method from google.longrunning.Operations. func (c *TestingClient) ListOperations(ctx context.Context, req *longrunningpb.ListOperationsRequest, opts ...gax.CallOption) *OperationIterator { return c.internalClient.ListOperations(ctx, req, opts...) } // GetOperation is a utility method from google.longrunning.Operations. func (c *TestingClient) GetOperation(ctx context.Context, req *longrunningpb.GetOperationRequest, opts ...gax.CallOption) (*longrunningpb.Operation, error) { return c.internalClient.GetOperation(ctx, req, opts...) } // DeleteOperation is a utility method from google.longrunning.Operations. func (c *TestingClient) DeleteOperation(ctx context.Context, req *longrunningpb.DeleteOperationRequest, opts ...gax.CallOption) error { return c.internalClient.DeleteOperation(ctx, req, opts...) } // CancelOperation is a utility method from google.longrunning.Operations. func (c *TestingClient) CancelOperation(ctx context.Context, req *longrunningpb.CancelOperationRequest, opts ...gax.CallOption) error { return c.internalClient.CancelOperation(ctx, req, opts...) } // testingGRPCClient is a client for interacting with Client Libraries Showcase API over gRPC transport. // // Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls. type testingGRPCClient struct { // Connection pool of gRPC connections to the service. connPool gtransport.ConnPool // Points back to the CallOptions field of the containing TestingClient CallOptions **TestingCallOptions // The gRPC API client. testingClient genprotopb.TestingClient operationsClient longrunningpb.OperationsClient iamPolicyClient iampb.IAMPolicyClient locationsClient locationpb.LocationsClient // The x-goog-* metadata to be sent with each request. xGoogHeaders []string logger *slog.Logger } // NewTestingClient creates a new testing client based on gRPC. // The returned client must be Closed when it is done being used to clean up its underlying connections. // // A service to facilitate running discrete sets of tests // against Showcase. // Adding this comment with special characters for comment formatting tests: // // (abra->kadabra->alakazam) // // Nonsense: pokemon/*/psychic/* func NewTestingClient(ctx context.Context, opts ...option.ClientOption) (*TestingClient, error) { clientOpts := defaultTestingGRPCClientOptions() if newTestingClientHook != nil { hookOpts, err := newTestingClientHook(ctx, clientHookParams{}) if err != nil { return nil, err } clientOpts = append(clientOpts, hookOpts...) } connPool, err := gtransport.DialPool(ctx, append(clientOpts, opts...)...) if err != nil { return nil, err } client := TestingClient{CallOptions: defaultTestingCallOptions()} c := &testingGRPCClient{ connPool: connPool, testingClient: genprotopb.NewTestingClient(connPool), CallOptions: &client.CallOptions, logger: internaloption.GetLogger(opts), operationsClient: longrunningpb.NewOperationsClient(connPool), iamPolicyClient: iampb.NewIAMPolicyClient(connPool), locationsClient: locationpb.NewLocationsClient(connPool), } c.setGoogleClientInfo() client.internalClient = c return &client, nil } // Connection returns a connection to the API service. // // Deprecated: Connections are now pooled so this method does not always // return the same resource. func (c *testingGRPCClient) Connection() *grpc.ClientConn { return c.connPool.Conn() } // setGoogleClientInfo sets the name and version of the application in // the `x-goog-api-client` header passed on each request. Intended for // use by Google-written clients. func (c *testingGRPCClient) setGoogleClientInfo(keyval ...string) { kv := append([]string{"gl-go", gax.GoVersion}, keyval...) kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "grpc", grpc.Version, "pb", protoVersion) c.xGoogHeaders = []string{ "x-goog-api-client", gax.XGoogHeader(kv...), } } // Close closes the connection to the API service. The user should invoke this when // the client is no longer required. func (c *testingGRPCClient) Close() error { return c.connPool.Close() } // Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls. type testingRESTClient struct { // The http endpoint to connect to. endpoint string // The http client. httpClient *http.Client // The x-goog-* headers to be sent with each request. xGoogHeaders []string // Points back to the CallOptions field of the containing TestingClient CallOptions **TestingCallOptions logger *slog.Logger } // NewTestingRESTClient creates a new testing rest client. // // A service to facilitate running discrete sets of tests // against Showcase. // Adding this comment with special characters for comment formatting tests: // // (abra->kadabra->alakazam) // // Nonsense: pokemon/*/psychic/* func NewTestingRESTClient(ctx context.Context, opts ...option.ClientOption) (*TestingClient, error) { clientOpts := append(defaultTestingRESTClientOptions(), opts...) httpClient, endpoint, err := httptransport.NewClient(ctx, clientOpts...) if err != nil { return nil, err } callOpts := defaultTestingRESTCallOptions() c := &testingRESTClient{ endpoint: endpoint, httpClient: httpClient, CallOptions: &callOpts, logger: internaloption.GetLogger(opts), } c.setGoogleClientInfo() return &TestingClient{internalClient: c, CallOptions: callOpts}, nil } func defaultTestingRESTClientOptions() []option.ClientOption { return []option.ClientOption{ internaloption.WithDefaultEndpoint("https://localhost:7469"), internaloption.WithDefaultEndpointTemplate("https://localhost:7469"), internaloption.WithDefaultMTLSEndpoint("https://localhost:7469"), internaloption.WithDefaultUniverseDomain("googleapis.com"), internaloption.WithDefaultAudience("https://localhost/"), internaloption.WithDefaultScopes(DefaultAuthScopes()...), internaloption.EnableNewAuthLibrary(), } } // setGoogleClientInfo sets the name and version of the application in // the `x-goog-api-client` header passed on each request. Intended for // use by Google-written clients. func (c *testingRESTClient) setGoogleClientInfo(keyval ...string) { kv := append([]string{"gl-go", gax.GoVersion}, keyval...) kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "rest", "UNKNOWN", "pb", protoVersion) c.xGoogHeaders = []string{ "x-goog-api-client", gax.XGoogHeader(kv...), } } // Close closes the connection to the API service. The user should invoke this when // the client is no longer required. func (c *testingRESTClient) Close() error { // Replace httpClient with nil to force cleanup. c.httpClient = nil return nil } // Connection returns a connection to the API service. // // Deprecated: This method always returns nil. func (c *testingRESTClient) Connection() *grpc.ClientConn { return nil } func (c *testingGRPCClient) CreateSession(ctx context.Context, req *genprotopb.CreateSessionRequest, opts ...gax.CallOption) (*genprotopb.Session, error) { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).CreateSession[0:len((*c.CallOptions).CreateSession):len((*c.CallOptions).CreateSession)], opts...) var resp *genprotopb.Session err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.testingClient.CreateSession, req, settings.GRPC, c.logger, "CreateSession") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *testingGRPCClient) GetSession(ctx context.Context, req *genprotopb.GetSessionRequest, opts ...gax.CallOption) (*genprotopb.Session, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).GetSession[0:len((*c.CallOptions).GetSession):len((*c.CallOptions).GetSession)], opts...) var resp *genprotopb.Session err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.testingClient.GetSession, req, settings.GRPC, c.logger, "GetSession") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *testingGRPCClient) ListSessions(ctx context.Context, req *genprotopb.ListSessionsRequest, opts ...gax.CallOption) *SessionIterator { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).ListSessions[0:len((*c.CallOptions).ListSessions):len((*c.CallOptions).ListSessions)], opts...) it := &SessionIterator{} req = proto.Clone(req).(*genprotopb.ListSessionsRequest) it.InternalFetch = func(pageSize int, pageToken string) ([]*genprotopb.Session, string, error) { resp := &genprotopb.ListSessionsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.testingClient.ListSessions, req, settings.GRPC, c.logger, "ListSessions") return err }, opts...) if err != nil { return nil, "", err } it.Response = resp return resp.GetSessions(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } func (c *testingGRPCClient) DeleteSession(ctx context.Context, req *genprotopb.DeleteSessionRequest, opts ...gax.CallOption) error { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).DeleteSession[0:len((*c.CallOptions).DeleteSession):len((*c.CallOptions).DeleteSession)], opts...) err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error _, err = executeRPC(ctx, c.testingClient.DeleteSession, req, settings.GRPC, c.logger, "DeleteSession") return err }, opts...) return err } func (c *testingGRPCClient) ReportSession(ctx context.Context, req *genprotopb.ReportSessionRequest, opts ...gax.CallOption) (*genprotopb.ReportSessionResponse, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).ReportSession[0:len((*c.CallOptions).ReportSession):len((*c.CallOptions).ReportSession)], opts...) var resp *genprotopb.ReportSessionResponse err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.testingClient.ReportSession, req, settings.GRPC, c.logger, "ReportSession") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *testingGRPCClient) ListTests(ctx context.Context, req *genprotopb.ListTestsRequest, opts ...gax.CallOption) *TestIterator { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "parent", url.QueryEscape(req.GetParent()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).ListTests[0:len((*c.CallOptions).ListTests):len((*c.CallOptions).ListTests)], opts...) it := &TestIterator{} req = proto.Clone(req).(*genprotopb.ListTestsRequest) it.InternalFetch = func(pageSize int, pageToken string) ([]*genprotopb.Test, string, error) { resp := &genprotopb.ListTestsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.testingClient.ListTests, req, settings.GRPC, c.logger, "ListTests") return err }, opts...) if err != nil { return nil, "", err } it.Response = resp return resp.GetTests(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } func (c *testingGRPCClient) DeleteTest(ctx context.Context, req *genprotopb.DeleteTestRequest, opts ...gax.CallOption) error { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).DeleteTest[0:len((*c.CallOptions).DeleteTest):len((*c.CallOptions).DeleteTest)], opts...) err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error _, err = executeRPC(ctx, c.testingClient.DeleteTest, req, settings.GRPC, c.logger, "DeleteTest") return err }, opts...) return err } func (c *testingGRPCClient) VerifyTest(ctx context.Context, req *genprotopb.VerifyTestRequest, opts ...gax.CallOption) (*genprotopb.VerifyTestResponse, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).VerifyTest[0:len((*c.CallOptions).VerifyTest):len((*c.CallOptions).VerifyTest)], opts...) var resp *genprotopb.VerifyTestResponse err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.testingClient.VerifyTest, req, settings.GRPC, c.logger, "VerifyTest") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *testingGRPCClient) ListLocations(ctx context.Context, req *locationpb.ListLocationsRequest, opts ...gax.CallOption) *LocationIterator { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).ListLocations[0:len((*c.CallOptions).ListLocations):len((*c.CallOptions).ListLocations)], opts...) it := &LocationIterator{} req = proto.Clone(req).(*locationpb.ListLocationsRequest) it.InternalFetch = func(pageSize int, pageToken string) ([]*locationpb.Location, string, error) { resp := &locationpb.ListLocationsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.locationsClient.ListLocations, req, settings.GRPC, c.logger, "ListLocations") return err }, opts...) if err != nil { return nil, "", err } it.Response = resp return resp.GetLocations(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } func (c *testingGRPCClient) GetLocation(ctx context.Context, req *locationpb.GetLocationRequest, opts ...gax.CallOption) (*locationpb.Location, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).GetLocation[0:len((*c.CallOptions).GetLocation):len((*c.CallOptions).GetLocation)], opts...) var resp *locationpb.Location err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.locationsClient.GetLocation, req, settings.GRPC, c.logger, "GetLocation") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *testingGRPCClient) SetIamPolicy(ctx context.Context, req *iampb.SetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).SetIamPolicy[0:len((*c.CallOptions).SetIamPolicy):len((*c.CallOptions).SetIamPolicy)], opts...) var resp *iampb.Policy err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.iamPolicyClient.SetIamPolicy, req, settings.GRPC, c.logger, "SetIamPolicy") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *testingGRPCClient) GetIamPolicy(ctx context.Context, req *iampb.GetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).GetIamPolicy[0:len((*c.CallOptions).GetIamPolicy):len((*c.CallOptions).GetIamPolicy)], opts...) var resp *iampb.Policy err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.iamPolicyClient.GetIamPolicy, req, settings.GRPC, c.logger, "GetIamPolicy") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *testingGRPCClient) TestIamPermissions(ctx context.Context, req *iampb.TestIamPermissionsRequest, opts ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).TestIamPermissions[0:len((*c.CallOptions).TestIamPermissions):len((*c.CallOptions).TestIamPermissions)], opts...) var resp *iampb.TestIamPermissionsResponse err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.iamPolicyClient.TestIamPermissions, req, settings.GRPC, c.logger, "TestIamPermissions") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *testingGRPCClient) ListOperations(ctx context.Context, req *longrunningpb.ListOperationsRequest, opts ...gax.CallOption) *OperationIterator { ctx = gax.InsertMetadataIntoOutgoingContext(ctx, c.xGoogHeaders...) opts = append((*c.CallOptions).ListOperations[0:len((*c.CallOptions).ListOperations):len((*c.CallOptions).ListOperations)], opts...) it := &OperationIterator{} req = proto.Clone(req).(*longrunningpb.ListOperationsRequest) it.InternalFetch = func(pageSize int, pageToken string) ([]*longrunningpb.Operation, string, error) { resp := &longrunningpb.ListOperationsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.operationsClient.ListOperations, req, settings.GRPC, c.logger, "ListOperations") return err }, opts...) if err != nil { return nil, "", err } it.Response = resp return resp.GetOperations(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } func (c *testingGRPCClient) GetOperation(ctx context.Context, req *longrunningpb.GetOperationRequest, opts ...gax.CallOption) (*longrunningpb.Operation, error) { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).GetOperation[0:len((*c.CallOptions).GetOperation):len((*c.CallOptions).GetOperation)], opts...) var resp *longrunningpb.Operation err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error resp, err = executeRPC(ctx, c.operationsClient.GetOperation, req, settings.GRPC, c.logger, "GetOperation") return err }, opts...) if err != nil { return nil, err } return resp, nil } func (c *testingGRPCClient) DeleteOperation(ctx context.Context, req *longrunningpb.DeleteOperationRequest, opts ...gax.CallOption) error { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).DeleteOperation[0:len((*c.CallOptions).DeleteOperation):len((*c.CallOptions).DeleteOperation)], opts...) err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error _, err = executeRPC(ctx, c.operationsClient.DeleteOperation, req, settings.GRPC, c.logger, "DeleteOperation") return err }, opts...) return err } func (c *testingGRPCClient) CancelOperation(ctx context.Context, req *longrunningpb.CancelOperationRequest, opts ...gax.CallOption) error { hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) ctx = gax.InsertMetadataIntoOutgoingContext(ctx, hds...) opts = append((*c.CallOptions).CancelOperation[0:len((*c.CallOptions).CancelOperation):len((*c.CallOptions).CancelOperation)], opts...) err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { var err error _, err = executeRPC(ctx, c.operationsClient.CancelOperation, req, settings.GRPC, c.logger, "CancelOperation") return err }, opts...) return err } // CreateSession creates a new testing session. // Adding this comment with special characters for comment formatting tests: // // (abra->kadabra->alakazam) // // Nonsense: pokemon/*/psychic/* func (c *testingRESTClient) CreateSession(ctx context.Context, req *genprotopb.CreateSessionRequest, opts ...gax.CallOption) (*genprotopb.Session, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} body := req.GetSession() jsonReq, err := m.Marshal(body) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/sessions") // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).CreateSession[0:len((*c.CallOptions).CreateSession):len((*c.CallOptions).CreateSession)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.Session{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "CreateSession") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // GetSession gets a testing session. func (c *testingRESTClient) GetSession(ctx context.Context, req *genprotopb.GetSessionRequest, opts ...gax.CallOption) (*genprotopb.Session, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).GetSession[0:len((*c.CallOptions).GetSession):len((*c.CallOptions).GetSession)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.Session{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "GetSession") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // ListSessions lists the current test sessions. func (c *testingRESTClient) ListSessions(ctx context.Context, req *genprotopb.ListSessionsRequest, opts ...gax.CallOption) *SessionIterator { it := &SessionIterator{} req = proto.Clone(req).(*genprotopb.ListSessionsRequest) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} it.InternalFetch = func(pageSize int, pageToken string) ([]*genprotopb.Session, string, error) { resp := &genprotopb.ListSessionsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, "", err } baseUrl.Path += fmt.Sprintf("/v1beta1/sessions") params := url.Values{} if req.GetPageSize() != 0 { params.Add("pageSize", fmt.Sprintf("%v", req.GetPageSize())) } if req.GetPageToken() != "" { params.Add("pageToken", fmt.Sprintf("%v", req.GetPageToken())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "ListSessions") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, "", e } it.Response = resp return resp.GetSessions(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } // DeleteSession delete a test session. func (c *testingRESTClient) DeleteSession(ctx context.Context, req *genprotopb.DeleteSessionRequest, opts ...gax.CallOption) error { baseUrl, err := url.Parse(c.endpoint) if err != nil { return err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) return gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("DELETE", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers _, err = executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "DeleteSession") return err }, opts...) } // ReportSession report on the status of a session. // This generates a report detailing which tests have been completed, // and an overall rollup. func (c *testingRESTClient) ReportSession(ctx context.Context, req *genprotopb.ReportSessionRequest, opts ...gax.CallOption) (*genprotopb.ReportSessionResponse, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:report", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).ReportSession[0:len((*c.CallOptions).ReportSession):len((*c.CallOptions).ReportSession)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.ReportSessionResponse{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "ReportSession") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // ListTests list the tests of a sessesion. func (c *testingRESTClient) ListTests(ctx context.Context, req *genprotopb.ListTestsRequest, opts ...gax.CallOption) *TestIterator { it := &TestIterator{} req = proto.Clone(req).(*genprotopb.ListTestsRequest) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} it.InternalFetch = func(pageSize int, pageToken string) ([]*genprotopb.Test, string, error) { resp := &genprotopb.ListTestsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, "", err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v/tests", req.GetParent()) params := url.Values{} if req.GetPageSize() != 0 { params.Add("pageSize", fmt.Sprintf("%v", req.GetPageSize())) } if req.GetPageToken() != "" { params.Add("pageToken", fmt.Sprintf("%v", req.GetPageToken())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "ListTests") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, "", e } it.Response = resp return resp.GetTests(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } // DeleteTest explicitly decline to implement a test. // // This removes the test from subsequent ListTests calls, and // attempting to do the test will error. // // This method will error if attempting to delete a required test. func (c *testingRESTClient) DeleteTest(ctx context.Context, req *genprotopb.DeleteTestRequest, opts ...gax.CallOption) error { baseUrl, err := url.Parse(c.endpoint) if err != nil { return err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) return gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("DELETE", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers _, err = executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "DeleteTest") return err }, opts...) } // VerifyTest register a response to a test. // // In cases where a test involves registering a final answer at the // end of the test, this method provides the means to do so. func (c *testingRESTClient) VerifyTest(ctx context.Context, req *genprotopb.VerifyTestRequest, opts ...gax.CallOption) (*genprotopb.VerifyTestResponse, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:check", req.GetName()) params := url.Values{} if req.GetAnswer() != nil { params.Add("answer", fmt.Sprintf("%v", req.GetAnswer())) } if items := req.GetAnswers(); len(items) > 0 { for _, item := range items { params.Add("answers", fmt.Sprintf("%v", item)) } } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).VerifyTest[0:len((*c.CallOptions).VerifyTest):len((*c.CallOptions).VerifyTest)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &genprotopb.VerifyTestResponse{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "VerifyTest") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // ListLocations is a utility method from google.cloud.location.Locations. func (c *testingRESTClient) ListLocations(ctx context.Context, req *locationpb.ListLocationsRequest, opts ...gax.CallOption) *LocationIterator { it := &LocationIterator{} req = proto.Clone(req).(*locationpb.ListLocationsRequest) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} it.InternalFetch = func(pageSize int, pageToken string) ([]*locationpb.Location, string, error) { resp := &locationpb.ListLocationsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, "", err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v/locations", req.GetName()) params := url.Values{} if req.GetFilter() != "" { params.Add("filter", fmt.Sprintf("%v", req.GetFilter())) } if req.GetPageSize() != 0 { params.Add("pageSize", fmt.Sprintf("%v", req.GetPageSize())) } if req.GetPageToken() != "" { params.Add("pageToken", fmt.Sprintf("%v", req.GetPageToken())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "ListLocations") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, "", e } it.Response = resp return resp.GetLocations(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } // GetLocation is a utility method from google.cloud.location.Locations. func (c *testingRESTClient) GetLocation(ctx context.Context, req *locationpb.GetLocationRequest, opts ...gax.CallOption) (*locationpb.Location, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).GetLocation[0:len((*c.CallOptions).GetLocation):len((*c.CallOptions).GetLocation)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &locationpb.Location{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "GetLocation") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // SetIamPolicy is a utility method from google.iam.v1.IAMPolicy. func (c *testingRESTClient) SetIamPolicy(ctx context.Context, req *iampb.SetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:setIamPolicy", req.GetResource()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).SetIamPolicy[0:len((*c.CallOptions).SetIamPolicy):len((*c.CallOptions).SetIamPolicy)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &iampb.Policy{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "SetIamPolicy") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // GetIamPolicy is a utility method from google.iam.v1.IAMPolicy. func (c *testingRESTClient) GetIamPolicy(ctx context.Context, req *iampb.GetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:getIamPolicy", req.GetResource()) params := url.Values{} if req.GetOptions().GetRequestedPolicyVersion() != 0 { params.Add("options.requestedPolicyVersion", fmt.Sprintf("%v", req.GetOptions().GetRequestedPolicyVersion())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).GetIamPolicy[0:len((*c.CallOptions).GetIamPolicy):len((*c.CallOptions).GetIamPolicy)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &iampb.Policy{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "GetIamPolicy") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // TestIamPermissions is a utility method from google.iam.v1.IAMPolicy. func (c *testingRESTClient) TestIamPermissions(ctx context.Context, req *iampb.TestIamPermissionsRequest, opts ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error) { m := protojson.MarshalOptions{AllowPartial: true, UseEnumNumbers: true} jsonReq, err := m.Marshal(req) if err != nil { return nil, err } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:testIamPermissions", req.GetResource()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).TestIamPermissions[0:len((*c.CallOptions).TestIamPermissions):len((*c.CallOptions).TestIamPermissions)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &iampb.TestIamPermissionsResponse{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), bytes.NewReader(jsonReq)) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, jsonReq, "TestIamPermissions") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // ListOperations is a utility method from google.longrunning.Operations. func (c *testingRESTClient) ListOperations(ctx context.Context, req *longrunningpb.ListOperationsRequest, opts ...gax.CallOption) *OperationIterator { it := &OperationIterator{} req = proto.Clone(req).(*longrunningpb.ListOperationsRequest) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} it.InternalFetch = func(pageSize int, pageToken string) ([]*longrunningpb.Operation, string, error) { resp := &longrunningpb.ListOperationsResponse{} if pageToken != "" { req.PageToken = pageToken } if pageSize > math.MaxInt32 { req.PageSize = math.MaxInt32 } else if pageSize != 0 { req.PageSize = int32(pageSize) } baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, "", err } baseUrl.Path += fmt.Sprintf("/v1beta1/operations") params := url.Values{} if req.GetFilter() != "" { params.Add("filter", fmt.Sprintf("%v", req.GetFilter())) } if req.GetName() != "" { params.Add("name", fmt.Sprintf("%v", req.GetName())) } if req.GetPageSize() != 0 { params.Add("pageSize", fmt.Sprintf("%v", req.GetPageSize())) } if req.GetPageToken() != "" { params.Add("pageToken", fmt.Sprintf("%v", req.GetPageToken())) } if req.GetReturnPartialSuccess() { params.Add("returnPartialSuccess", fmt.Sprintf("%v", req.GetReturnPartialSuccess())) } baseUrl.RawQuery = params.Encode() // Build HTTP headers from client and context metadata. hds := append(c.xGoogHeaders, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "ListOperations") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, "", e } it.Response = resp return resp.GetOperations(), resp.GetNextPageToken(), nil } fetch := func(pageSize int, pageToken string) (string, error) { items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) if err != nil { return "", err } it.items = append(it.items, items...) return nextPageToken, nil } it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) it.pageInfo.MaxSize = int(req.GetPageSize()) it.pageInfo.Token = req.GetPageToken() return it } // GetOperation is a utility method from google.longrunning.Operations. func (c *testingRESTClient) GetOperation(ctx context.Context, req *longrunningpb.GetOperationRequest, opts ...gax.CallOption) (*longrunningpb.Operation, error) { baseUrl, err := url.Parse(c.endpoint) if err != nil { return nil, err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) opts = append((*c.CallOptions).GetOperation[0:len((*c.CallOptions).GetOperation):len((*c.CallOptions).GetOperation)], opts...) unm := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true} resp := &longrunningpb.Operation{} e := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("GET", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers buf, err := executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "GetOperation") if err != nil { return err } if err := unm.Unmarshal(buf, resp); err != nil { return err } return nil }, opts...) if e != nil { return nil, e } return resp, nil } // DeleteOperation is a utility method from google.longrunning.Operations. func (c *testingRESTClient) DeleteOperation(ctx context.Context, req *longrunningpb.DeleteOperationRequest, opts ...gax.CallOption) error { baseUrl, err := url.Parse(c.endpoint) if err != nil { return err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) return gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("DELETE", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers _, err = executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "DeleteOperation") return err }, opts...) } // CancelOperation is a utility method from google.longrunning.Operations. func (c *testingRESTClient) CancelOperation(ctx context.Context, req *longrunningpb.CancelOperationRequest, opts ...gax.CallOption) error { baseUrl, err := url.Parse(c.endpoint) if err != nil { return err } baseUrl.Path += fmt.Sprintf("/v1beta1/%v:cancel", req.GetName()) // Build HTTP headers from client and context metadata. hds := []string{"x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName()))} hds = append(c.xGoogHeaders, hds...) hds = append(hds, "Content-Type", "application/json") headers := gax.BuildHeaders(ctx, hds...) return gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { if settings.Path != "" { baseUrl.Path = settings.Path } httpReq, err := http.NewRequest("POST", baseUrl.String(), nil) if err != nil { return err } httpReq = httpReq.WithContext(ctx) httpReq.Header = headers _, err = executeHTTPRequest(ctx, c.httpClient, httpReq, c.logger, nil, "CancelOperation") return err }, opts...) } ================================================ FILE: client/testing_client_example_go123_test.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go_gapic. DO NOT EDIT. //go:build go1.23 package client_test import ( "context" longrunningpb "cloud.google.com/go/longrunning/autogen/longrunningpb" client "github.com/googleapis/gapic-showcase/client" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" locationpb "google.golang.org/genproto/googleapis/cloud/location" ) func ExampleTestingClient_ListSessions_all() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewTestingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.ListSessionsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#ListSessionsRequest. } for resp, err := range c.ListSessions(ctx, req).All() { if err != nil { // TODO: Handle error and break/return/continue. Iteration will stop after any error. } // TODO: Use resp. _ = resp } } func ExampleTestingClient_ListTests_all() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewTestingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.ListTestsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#ListTestsRequest. } for resp, err := range c.ListTests(ctx, req).All() { if err != nil { // TODO: Handle error and break/return/continue. Iteration will stop after any error. } // TODO: Use resp. _ = resp } } func ExampleTestingClient_ListLocations_all() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewTestingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &locationpb.ListLocationsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/google.golang.org/genproto/googleapis/cloud/location#ListLocationsRequest. } for resp, err := range c.ListLocations(ctx, req).All() { if err != nil { // TODO: Handle error and break/return/continue. Iteration will stop after any error. } // TODO: Use resp. _ = resp } } func ExampleTestingClient_ListOperations_all() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewTestingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.ListOperationsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#ListOperationsRequest. } for resp, err := range c.ListOperations(ctx, req).All() { if err != nil { // TODO: Handle error and break/return/continue. Iteration will stop after any error. } // TODO: Use resp. _ = resp } } ================================================ FILE: client/testing_client_example_test.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go_gapic. DO NOT EDIT. package client_test import ( "context" iampb "cloud.google.com/go/iam/apiv1/iampb" longrunningpb "cloud.google.com/go/longrunning/autogen/longrunningpb" client "github.com/googleapis/gapic-showcase/client" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "google.golang.org/api/iterator" locationpb "google.golang.org/genproto/googleapis/cloud/location" ) func ExampleNewTestingClient() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewTestingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() // TODO: Use client. _ = c } func ExampleNewTestingRESTClient() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewTestingRESTClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() // TODO: Use client. _ = c } func ExampleTestingClient_CreateSession() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewTestingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.CreateSessionRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#CreateSessionRequest. } resp, err := c.CreateSession(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleTestingClient_DeleteSession() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewTestingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.DeleteSessionRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#DeleteSessionRequest. } err = c.DeleteSession(ctx, req) if err != nil { // TODO: Handle error. } } func ExampleTestingClient_DeleteTest() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewTestingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.DeleteTestRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#DeleteTestRequest. } err = c.DeleteTest(ctx, req) if err != nil { // TODO: Handle error. } } func ExampleTestingClient_GetSession() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewTestingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.GetSessionRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#GetSessionRequest. } resp, err := c.GetSession(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleTestingClient_ListSessions() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewTestingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.ListSessionsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#ListSessionsRequest. } it := c.ListSessions(ctx, req) for { resp, err := it.Next() if err == iterator.Done { break } if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp // If you need to access the underlying RPC response, // you can do so by casting the `Response` as below. // Otherwise, remove this line. Only populated after // first call to Next(). Not safe for concurrent access. _ = it.Response.(*genprotopb.ListSessionsResponse) } } func ExampleTestingClient_ListTests() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewTestingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.ListTestsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#ListTestsRequest. } it := c.ListTests(ctx, req) for { resp, err := it.Next() if err == iterator.Done { break } if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp // If you need to access the underlying RPC response, // you can do so by casting the `Response` as below. // Otherwise, remove this line. Only populated after // first call to Next(). Not safe for concurrent access. _ = it.Response.(*genprotopb.ListTestsResponse) } } func ExampleTestingClient_ReportSession() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewTestingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.ReportSessionRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#ReportSessionRequest. } resp, err := c.ReportSession(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleTestingClient_VerifyTest() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewTestingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &genprotopb.VerifyTestRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/github.com/googleapis/gapic-showcase/server/genproto#VerifyTestRequest. } resp, err := c.VerifyTest(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleTestingClient_ListLocations() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewTestingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &locationpb.ListLocationsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/google.golang.org/genproto/googleapis/cloud/location#ListLocationsRequest. } it := c.ListLocations(ctx, req) for { resp, err := it.Next() if err == iterator.Done { break } if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp // If you need to access the underlying RPC response, // you can do so by casting the `Response` as below. // Otherwise, remove this line. Only populated after // first call to Next(). Not safe for concurrent access. _ = it.Response.(*locationpb.ListLocationsResponse) } } func ExampleTestingClient_GetLocation() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewTestingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &locationpb.GetLocationRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/google.golang.org/genproto/googleapis/cloud/location#GetLocationRequest. } resp, err := c.GetLocation(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleTestingClient_SetIamPolicy() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewTestingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &iampb.SetIamPolicyRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/iam/apiv1/iampb#SetIamPolicyRequest. } resp, err := c.SetIamPolicy(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleTestingClient_GetIamPolicy() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewTestingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &iampb.GetIamPolicyRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/iam/apiv1/iampb#GetIamPolicyRequest. } resp, err := c.GetIamPolicy(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleTestingClient_TestIamPermissions() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewTestingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &iampb.TestIamPermissionsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/iam/apiv1/iampb#TestIamPermissionsRequest. } resp, err := c.TestIamPermissions(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleTestingClient_ListOperations() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewTestingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.ListOperationsRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#ListOperationsRequest. } it := c.ListOperations(ctx, req) for { resp, err := it.Next() if err == iterator.Done { break } if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp // If you need to access the underlying RPC response, // you can do so by casting the `Response` as below. // Otherwise, remove this line. Only populated after // first call to Next(). Not safe for concurrent access. _ = it.Response.(*longrunningpb.ListOperationsResponse) } } func ExampleTestingClient_GetOperation() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewTestingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.GetOperationRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#GetOperationRequest. } resp, err := c.GetOperation(ctx, req) if err != nil { // TODO: Handle error. } // TODO: Use resp. _ = resp } func ExampleTestingClient_DeleteOperation() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewTestingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.DeleteOperationRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#DeleteOperationRequest. } err = c.DeleteOperation(ctx, req) if err != nil { // TODO: Handle error. } } func ExampleTestingClient_CancelOperation() { ctx := context.Background() // This snippet has been automatically generated and should be regarded as a code template only. // It will require modifications to work: // - It may require correct/in-range values for request initialization. // - It may require specifying regional endpoints when creating the service client as shown in: // https://pkg.go.dev/cloud.google.com/go#hdr-Client_Options c, err := client.NewTestingClient(ctx) if err != nil { // TODO: Handle error. } defer c.Close() req := &longrunningpb.CancelOperationRequest{ // TODO: Fill request struct fields. // See https://pkg.go.dev/cloud.google.com/go/longrunning/autogen/longrunningpb#CancelOperationRequest. } err = c.CancelOperation(ctx, req) if err != nil { // TODO: Handle error. } } ================================================ FILE: cmd/gapic-showcase/README.md ================================================ # gapic-showcase This directory contains the command line interface (CLI) used to run the Showcase API server as well as make requests to the Showcase API. ## Installation ```sh $ go install github.com/googleapis/gapic-showcase/cmd/gapic-showcase ``` ## Usage ```sh $ gapic-showcase --help > Root command of gapic-showcase > > Usage: > gapic-showcase [command] > > Available Commands: > completion Emits bash a completion for gapic-showcase > echo This service is used showcase the four main types... > help Help about any command > identity A simple identity service. > messaging A simple messaging service that implements chat... > run Runs the showcase server > testing A service to facilitate running discrete sets of... > > Flags: > -h, --help help for gapic-showcase > -j, --json Print JSON output > -v, --verbose Print verbose output > --version version for gapic-showcase > > Use "gapic-showcase [command] --help" for more information about a command. ``` ### Running the server ```sh $ gapic-showcase run --help > Runs the showcase server > > Usage: > gapic-showcase run [flags] > > Flags: > -h, --help help for run > -p, --port string The port that showcase will be served on. (default ":7469") > > Global Flags: > -j, --json Print JSON output > -v, --verbose Print verbose output $ gapic-showcase run --port 1234 > 2019/04/01 12:36:35 Showcase listening on port: :1234 ``` ### Making a request A request can also be made to the Showcase API using this CLI. The command to make a request is done by using a service's subcommand, the method's subcommand and passing the request values as flags as shown below. ``` $ gapic-showcase {service_name} {method_name} --{request_field_name} {value} ``` #### Example ```sh $ gapic-showcase identity --help > A simple identity service. > > Usage: > gapic-showcase identity [command] > > Available Commands: > create-user Creates a user. > delete-user Deletes a user, their profile, and all of their... > get-user Retrieves the User with the given uri. > list-users Lists all users. > update-user Updates a user. > > Flags: > --address string Set API address used by client. Or use GAPIC-SHOWCASE_IDENTITY_ADDRESS. > --api_key string Set API Key used by the client. Or use GAPIC-SHOWCASE_IDENTITY_API_KEY. > -h, --help help for identity > --insecure Make insecure client connection. Or use GAPIC-SHOWCASE_IDENTITY_INSECURE. Must be used with "address" option > --token string Set Bearer token used by the client. Or use GAPIC-SHOWCASE_IDENTITY_TOKEN. > > Global Flags: > -j, --json Print JSON output > -v, --verbose Print verbose output > > Use "gapic-showcase identity [command] --help" for more information about a command. $ gapic-showcase identity create-user --help > Creates a user. > > Usage: > gapic-showcase identity create-user [flags] > > Flags: > --from_file string Absolute path to JSON file containing request payload > -h, --help help for create-user > --user.create_time.nanos int32 > --user.create_time.seconds int > --user.display_name string > --user.email string > --user.name string > --user.update_time.nanos int32 > --user.update_time.seconds int > > Global Flags: > --address string Set API address used by client. Or use GAPIC-SHOWCASE_IDENTITY_ADDRESS. > --api_key string Set API Key used by the client. Or use GAPIC-SHOWCASE_IDENTITY_API_KEY. > --insecure Make insecure client connection. Or use GAPIC-SHOWCASE_IDENTITY_INSECURE. Must be used with "address" option > -j, --json Print JSON output > --token string Set Bearer token used by the client. Or use GAPIC-SHOWCASE_IDENTITY_TOKEN. > -v, --verbose Print verbose output $ gapic-showcase identity create-user --user.display_name Rumble --user.email rumble@goodboi.com > name:"users/0" display_name:"Rumble" email:"rumble@goodboi.com" create_time: update_time: ``` ## Development Most of the files in this directory are generated by the [go_cli](https://github.com/googleapis/gapic-generator-go/tree/main/cmd/protoc-gen-go_cli) protoc plug-in (invoked in `util/cmd/compile_protos/main.go` from `.circlec1/config.yml`) as sub-commands to allow interacting with the various Showcase services via the `showcase` command. The other files (`grep -L "DO NOT EDIT" *`) are authored manually. In particular, these include `run.go`, which runs the Showcase API servers. ================================================ FILE: cmd/gapic-showcase/attempt-sequence.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var AttemptSequenceInput genprotopb.AttemptSequenceRequest var AttemptSequenceFromFile string func init() { SequenceServiceCmd.AddCommand(AttemptSequenceCmd) AttemptSequenceCmd.Flags().StringVar(&AttemptSequenceInput.Name, "name", "", "Required. ") AttemptSequenceCmd.Flags().StringVar(&AttemptSequenceFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var AttemptSequenceCmd = &cobra.Command{ Use: "attempt-sequence", Short: "Attempts a sequence of unary responses.", Long: "Attempts a sequence of unary responses.", PreRun: func(cmd *cobra.Command, args []string) { if AttemptSequenceFromFile == "" { cmd.MarkFlagRequired("name") } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if AttemptSequenceFromFile != "" { in, err = os.Open(AttemptSequenceFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &AttemptSequenceInput) if err != nil { return err } } if Verbose { printVerboseInput("Sequence", "AttemptSequence", &AttemptSequenceInput) } err = SequenceClient.AttemptSequence(ctx, &AttemptSequenceInput) if err != nil { return err } return err }, } ================================================ FILE: cmd/gapic-showcase/attempt-streaming-sequence.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "io" "os" ) var AttemptStreamingSequenceInput genprotopb.AttemptStreamingSequenceRequest var AttemptStreamingSequenceFromFile string func init() { SequenceServiceCmd.AddCommand(AttemptStreamingSequenceCmd) AttemptStreamingSequenceCmd.Flags().StringVar(&AttemptStreamingSequenceInput.Name, "name", "", "Required. ") AttemptStreamingSequenceCmd.Flags().Int32Var(&AttemptStreamingSequenceInput.LastFailIndex, "last_fail_index", 0, "used to send the index of the last failed message...") AttemptStreamingSequenceCmd.Flags().StringVar(&AttemptStreamingSequenceFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var AttemptStreamingSequenceCmd = &cobra.Command{ Use: "attempt-streaming-sequence", Short: "Attempts a server streaming call with a sequence...", Long: "Attempts a server streaming call with a sequence of responses Can be used to test retries and stream resumption logic May not function as expected...", PreRun: func(cmd *cobra.Command, args []string) { if AttemptStreamingSequenceFromFile == "" { cmd.MarkFlagRequired("name") } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if AttemptStreamingSequenceFromFile != "" { in, err = os.Open(AttemptStreamingSequenceFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &AttemptStreamingSequenceInput) if err != nil { return err } } if Verbose { printVerboseInput("Sequence", "AttemptStreamingSequence", &AttemptStreamingSequenceInput) } resp, err := SequenceClient.AttemptStreamingSequence(ctx, &AttemptStreamingSequenceInput) if err != nil { return err } var item *genprotopb.AttemptStreamingSequenceResponse for { item, err = resp.Recv() if err != nil { break } if Verbose { fmt.Print("Output: ") } printMessage(item) } if err == io.EOF { return nil } return err }, } ================================================ FILE: cmd/gapic-showcase/block.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" anypb "google.golang.org/protobuf/types/known/anypb" durationpb "google.golang.org/protobuf/types/known/durationpb" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" statuspb "google.golang.org/genproto/googleapis/rpc/status" ) var BlockInput genprotopb.BlockRequest var BlockFromFile string var BlockInputResponse string var BlockInputResponseError genprotopb.BlockRequest_Error var BlockInputResponseSuccess genprotopb.BlockRequest_Success var BlockInputResponseErrorDetails []string func init() { EchoServiceCmd.AddCommand(BlockCmd) BlockInput.ResponseDelay = new(durationpb.Duration) BlockInputResponseError.Error = new(statuspb.Status) BlockInputResponseSuccess.Success = new(genprotopb.BlockResponse) BlockCmd.Flags().Int64Var(&BlockInput.ResponseDelay.Seconds, "response_delay.seconds", 0, "Signed seconds of the span of time. Must be from...") BlockCmd.Flags().Int32Var(&BlockInput.ResponseDelay.Nanos, "response_delay.nanos", 0, "Signed fractions of a second at nanosecond...") BlockCmd.Flags().Int32Var(&BlockInputResponseError.Error.Code, "response.error.code", 0, "The status code, which should be an enum value of...") BlockCmd.Flags().StringVar(&BlockInputResponseError.Error.Message, "response.error.message", "", "A developer-facing error message, which should be...") BlockCmd.Flags().StringArrayVar(&BlockInputResponseErrorDetails, "response.error.details", []string{}, "A list of messages that carry the error details. ...") BlockCmd.Flags().StringVar(&BlockInputResponseSuccess.Success.Content, "response.success.content", "", "This content can contain anything, the server...") BlockCmd.Flags().StringVar(&BlockInputResponse, "response", "", "Choices: error, success") BlockCmd.Flags().StringVar(&BlockFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var BlockCmd = &cobra.Command{ Use: "block", Short: "This method will block (wait) for the requested...", Long: "This method will block (wait) for the requested amount of time and then return the response or error. This method showcases how a client handles...", PreRun: func(cmd *cobra.Command, args []string) { if BlockFromFile == "" { cmd.MarkFlagRequired("response") } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if BlockFromFile != "" { in, err = os.Open(BlockFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &BlockInput) if err != nil { return err } } else { switch BlockInputResponse { case "error": BlockInput.Response = &BlockInputResponseError case "success": BlockInput.Response = &BlockInputResponseSuccess default: return fmt.Errorf("Missing oneof choice for response") } } // unmarshal JSON strings into slice of structs for _, item := range BlockInputResponseErrorDetails { tmp := anypb.Any{} err = jsonpb.UnmarshalString(item, &tmp) if err != nil { return } BlockInputResponseError.Error.Details = append(BlockInputResponseError.Error.Details, &tmp) } if Verbose { printVerboseInput("Echo", "Block", &BlockInput) } resp, err := EchoClient.Block(ctx, &BlockInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/chat.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "bufio" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var ChatFromFile string var ChatOutFile string func init() { EchoServiceCmd.AddCommand(ChatCmd) ChatCmd.Flags().StringVar(&ChatFromFile, "from_file", "", "Absolute path to JSON file containing request payload") ChatCmd.Flags().StringVar(&ChatOutFile, "out_file", "", "Absolute path to a file to pipe output to") ChatCmd.MarkFlagRequired("out_file") } var ChatCmd = &cobra.Command{ Use: "chat", Short: "This method, upon receiving a request on the...", Long: "This method, upon receiving a request on the stream, will pass the same content back on the stream. This method showcases bidirectional streaming...", PreRun: func(cmd *cobra.Command, args []string) { }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if ChatFromFile != "" { in, err = os.Open(ChatFromFile) if err != nil { return err } defer in.Close() } stream, err := EchoClient.Chat(ctx) if err != nil { return err } out, err := os.OpenFile(ChatOutFile, os.O_APPEND|os.O_WRONLY, os.ModeAppend) if err != nil { return err } // start background stream receive go func() { var res *genprotopb.EchoResponse for { res, err = stream.Recv() if err != nil { return } str := res.String() if OutputJSON { str, _ = marshaler.MarshalToString(res) } fmt.Fprintln(out, str) } }() if Verbose { fmt.Println("Client stream open. Close with ctrl+D.") } var ChatInput genprotopb.EchoRequest scanner := bufio.NewScanner(in) for scanner.Scan() { input := scanner.Text() if input == "" { continue } err = jsonpb.UnmarshalString(input, &ChatInput) if err != nil { return err } err = stream.Send(&ChatInput) if err != nil { return err } } if err = scanner.Err(); err != nil { return err } err = stream.CloseSend() return err }, } ================================================ FILE: cmd/gapic-showcase/collect.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "bufio" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var CollectFromFile string func init() { EchoServiceCmd.AddCommand(CollectCmd) CollectCmd.Flags().StringVar(&CollectFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var CollectCmd = &cobra.Command{ Use: "collect", Short: "This method will collect the words given to it....", Long: "This method will collect the words given to it. When the stream is closed by the client, this method will return the a concatenation of the strings ...", PreRun: func(cmd *cobra.Command, args []string) { }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if CollectFromFile != "" { in, err = os.Open(CollectFromFile) if err != nil { return err } defer in.Close() } stream, err := EchoClient.Collect(ctx) if err != nil { return err } if Verbose { fmt.Println("Client stream open. Close with ctrl+D.") } var CollectInput genprotopb.EchoRequest scanner := bufio.NewScanner(in) for scanner.Scan() { input := scanner.Text() if input == "" { continue } err = jsonpb.UnmarshalString(input, &CollectInput) if err != nil { return err } err = stream.Send(&CollectInput) if err != nil { return err } } if err = scanner.Err(); err != nil { return err } resp, err := stream.CloseAndRecv() if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/completion.go ================================================ // Code generated. DO NOT EDIT. package main import ( "os" "github.com/spf13/cobra" ) func init() { rootCmd.AddCommand(completionCmd) } // completionCmd represents the completion command var completionCmd = &cobra.Command{ Use: "completion", Short: "Emits bash a completion for gapic-showcase", Long: `Enable bash completion like so: Linux: source <(gapic-showcase completion) Mac: brew install bash-completion gapic-showcase completion > $(brew --prefix)/etc/bash_completion.d/gapic-showcase`, Run: func(cmd *cobra.Command, args []string) { rootCmd.GenBashCompletion(os.Stdout) }, } ================================================ FILE: cmd/gapic-showcase/compliance_service.go ================================================ // Code generated. DO NOT EDIT. package main import ( "fmt" "github.com/spf13/cobra" "github.com/spf13/viper" "golang.org/x/oauth2" "google.golang.org/api/option" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" gapic "github.com/googleapis/gapic-showcase/client" ) var ComplianceConfig *viper.Viper var ComplianceClient *gapic.ComplianceClient var ComplianceSubCommands []string = []string{ "repeat-data-body", "repeat-data-body-info", "repeat-data-query", "repeat-data-simple-path", "repeat-data-path-resource", "repeat-data-path-trailing-resource", "repeat-data-body-put", "repeat-data-body-patch", "get-enum", "verify-enum", } func init() { rootCmd.AddCommand(ComplianceServiceCmd) ComplianceConfig = viper.New() ComplianceConfig.SetEnvPrefix("GAPIC-SHOWCASE_COMPLIANCE") ComplianceConfig.AutomaticEnv() ComplianceServiceCmd.PersistentFlags().Bool("insecure", false, "Make insecure client connection. Or use GAPIC-SHOWCASE_COMPLIANCE_INSECURE. Must be used with \"address\" option") ComplianceConfig.BindPFlag("insecure", ComplianceServiceCmd.PersistentFlags().Lookup("insecure")) ComplianceConfig.BindEnv("insecure") ComplianceServiceCmd.PersistentFlags().String("address", "", "Set API address used by client. Or use GAPIC-SHOWCASE_COMPLIANCE_ADDRESS.") ComplianceConfig.BindPFlag("address", ComplianceServiceCmd.PersistentFlags().Lookup("address")) ComplianceConfig.BindEnv("address") ComplianceServiceCmd.PersistentFlags().String("token", "", "Set Bearer token used by the client. Or use GAPIC-SHOWCASE_COMPLIANCE_TOKEN.") ComplianceConfig.BindPFlag("token", ComplianceServiceCmd.PersistentFlags().Lookup("token")) ComplianceConfig.BindEnv("token") ComplianceServiceCmd.PersistentFlags().String("api_key", "", "Set API Key used by the client. Or use GAPIC-SHOWCASE_COMPLIANCE_API_KEY.") ComplianceConfig.BindPFlag("api_key", ComplianceServiceCmd.PersistentFlags().Lookup("api_key")) ComplianceConfig.BindEnv("api_key") } var ComplianceServiceCmd = &cobra.Command{ Use: "compliance", Short: "This service is used to test that GAPICs...", Long: "This service is used to test that GAPICs implement various REST-related features correctly. This mostly means transcoding proto3 requests to REST...", ValidArgs: ComplianceSubCommands, PersistentPreRunE: func(cmd *cobra.Command, args []string) (err error) { var opts []option.ClientOption address := ComplianceConfig.GetString("address") if address != "" { opts = append(opts, option.WithEndpoint(address)) } if ComplianceConfig.GetBool("insecure") { if address == "" { return fmt.Errorf("Missing address to use with insecure connection") } conn, err := grpc.Dial(address, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { return err } opts = append(opts, option.WithGRPCConn(conn)) } if token := ComplianceConfig.GetString("token"); token != "" { opts = append(opts, option.WithTokenSource(oauth2.StaticTokenSource( &oauth2.Token{ AccessToken: token, TokenType: "Bearer", }))) } if key := ComplianceConfig.GetString("api_key"); key != "" { opts = append(opts, option.WithAPIKey(key)) } ComplianceClient, err = gapic.NewComplianceClient(ctx, opts...) return }, } ================================================ FILE: cmd/gapic-showcase/compliance_suite_errors_test.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "fmt" "io" "net/http" "strings" "testing" "github.com/googleapis/gapic-showcase/server/genproto" pb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/googleapis/gapic-showcase/server/services" "github.com/googleapis/gapic-showcase/util/genrest/resttools" "google.golang.org/protobuf/encoding/protojson" ) // TestComplianceSuiteErrors checks for non-spec-compliant HTTP requests. Not all of these // conditions necessarily generate a server error in a real service, but the behavior is often // ill-defined. We want Showcase to require the generators be strict in the transcoding format they // use. func TestComplianceSuiteErrors(t *testing.T) { masterSuite, server, err := complianceSuiteTestSetup() if err != nil { t.Fatal(err) } server.Start() defer server.Close() restRPCs := map[string][]prepRepeatDataNegativeTestFunc{ "Compliance.RepeatDataBodyInfo": { prepRepeatDataBodyInfoNegativeTestInvalidFields, prepRepeatDataBodyInfoNegativeTestSnakeCasedFieldNames, }, "Compliance.RepeatDataQuery": { prepRepeatDataQueryNegativeTestSnakeCasedFieldNames, }, } for groupIdx, group := range masterSuite.GetGroup() { rpcsToTest := group.GetRpcs() for requestIdx, masterProto := range group.GetRequests() { for rpcIdx, rpcName := range rpcsToTest { errorPrefix := fmt.Sprintf("[request %d/%q: rpc %q/%d/%q]", requestIdx, masterProto.GetName(), group.Name, rpcIdx, rpcName) // Ensure that we issue only the RPCs the test suite is expecting. restTest, ok := restRPCs[rpcName] if !ok { // we don't have a negative test for this RPC continue } for _, rpcPrep := range restTest { // since these tests may modify the request protos, get a // clean request every time as the starting point, in order // to prevent previous modifications from affecting the // current test case suite, err := getCleanComplianceSuite() if err != nil { t.Fatal(err) } requestProto := suite.GetGroup()[groupIdx].GetRequests()[requestIdx] prepName, verb, path, requestBody, failure, err := rpcPrep(requestProto) if err != nil { t.Errorf("%s error: %s", errorPrefix, err) } if got, want := prepName, rpcName; !strings.HasPrefix(prepName, rpcName) { t.Errorf("%s retrieved mismatched prep function: got %q, want %q", errorPrefix, got, want) } checkExpectedFailure(t, verb, server.URL+path, requestBody, failure, errorPrefix, prepName) } } } } } // TestComplianceSuiteUnexpectedFieldPresence checks that we detect erroneous presence/absence of // optional fields. func TestComplianceSuiteUnexpectedFieldPresence(t *testing.T) { suite, server, err := complianceSuiteTestSetup() if err != nil { t.Fatal(err) } server.Start() defer server.Close() indexedSuite, err := services.IndexComplianceSuite(suite) if err != nil { t.Fatal(err) } requestsModified := map[string]bool{} for idx, testCase := range []struct { name string requestName string modify requestModifier subCases map[string]prepRepeatDataTestFunc failureMode string }{ { name: "detecting requests not included in test suite", requestName: "Zero values for all fields", modify: func(request *pb.RepeatRequest) { request.Name = "modified name" }, subCases: map[string]prepRepeatDataTestFunc{ "body": prepRepeatDataBodyTest, "query": prepRepeatDataQueryTest, }, failureMode: "(ComplianceSuiteRequestNotFoundError)", }, { name: "detecting set optional bool field erroneously not sent", requestName: "Zero values for all fields", modify: func(request *pb.RepeatRequest) { request.GetInfo().PBool = nil }, subCases: map[string]prepRepeatDataTestFunc{ "body": prepRepeatDataBodyTest, "query": prepRepeatDataQueryTest, }, failureMode: "(ComplianceSuiteRequestMismatchError)", }, { name: "detecting unset optional bool field erroneously sent", requestName: "Basic types, no optional fields", modify: func(request *pb.RepeatRequest) { myFalse := false request.GetInfo().PBool = &myFalse }, subCases: map[string]prepRepeatDataTestFunc{ "body": prepRepeatDataBodyTest, "query": prepRepeatDataQueryTest, }, failureMode: "(ComplianceSuiteRequestMismatchError)", }, { name: "detecting set optional string field erroneously not sent", requestName: "Zero values for all fields", modify: func(request *pb.RepeatRequest) { request.GetInfo().PString = nil }, subCases: map[string]prepRepeatDataTestFunc{ "body": prepRepeatDataBodyTest, "query": prepRepeatDataQueryTest, }, failureMode: "(ComplianceSuiteRequestMismatchError)", }, { name: "detecting unset optional string field erroneously sent", requestName: "Basic types, no optional fields", modify: func(request *pb.RepeatRequest) { myEmpty := "" request.GetInfo().PString = &myEmpty }, subCases: map[string]prepRepeatDataTestFunc{ "body": prepRepeatDataBodyTest, "query": prepRepeatDataQueryTest, }, failureMode: "(ComplianceSuiteRequestMismatchError)", }, { name: "detecting set optional int32 field erroneously not sent", requestName: "Zero values for all fields", modify: func(request *pb.RepeatRequest) { request.GetInfo().PInt32 = nil }, subCases: map[string]prepRepeatDataTestFunc{ "body": prepRepeatDataBodyTest, "query": prepRepeatDataQueryTest, }, failureMode: "(ComplianceSuiteRequestMismatchError)", }, { name: "detecting unset optional int32 field erroneously sent", requestName: "Basic types, no optional fields", modify: func(request *pb.RepeatRequest) { myInt := int32(0) request.GetInfo().PInt32 = &myInt }, subCases: map[string]prepRepeatDataTestFunc{ "body": prepRepeatDataBodyTest, "query": prepRepeatDataQueryTest, }, failureMode: "(ComplianceSuiteRequestMismatchError)", }, } { if _, done := requestsModified[testCase.requestName]; done { if suite, err = getCleanComplianceSuite(); err != nil { t.Fatal(err) } if indexedSuite, err = services.IndexComplianceSuite(suite); err != nil { t.Fatal(err) } requestsModified = map[string]bool{} } requestsModified[testCase.requestName] = true request, ok := indexedSuite[testCase.requestName] if !ok { t.Fatalf("could not find request by name: %q", testCase.requestName) } testCase.modify(request) for subCaseName, prep := range testCase.subCases { prefix := fmt.Sprintf("[case %d: %s: %s]", idx, testCase.name, subCaseName) verb, prepName, path, body, error := prep(request) if error != nil { t.Fatalf("%s could not construct request: %s", prefix, err) } checkExpectedFailure(t, verb, server.URL+path, body, testCase.failureMode, prefix, prepName) } } } type prepRepeatDataNegativeTestFunc func(request *genproto.RepeatRequest) (verb string, name string, path string, body string, expect string, err error) func prepRepeatDataBodyInfoNegativeTestInvalidFields(request *genproto.RepeatRequest) (verb string, name string, path string, body string, expect string, err error) { resttools.JSONMarshaler.Replace(nil) defer resttools.JSONMarshaler.Restore() name = "Compliance.RepeatDataBodyInfo#NegativeTestInvalidFields" bodyBytes, err := resttools.ToJSON().Marshal(request.Info) queryString := prepRepeatDataTestsQueryString(request, nil) // purposefully repeats query params, which should cause an error return name, "POST", "/v1beta1/repeat:bodyinfo" + queryString, string(bodyBytes), "(QueryParamsInvalidFieldError)", err } func prepRepeatDataBodyInfoNegativeTestSnakeCasedFieldNames(request *genproto.RepeatRequest) (verb string, name string, path string, body string, expect string, err error) { resttools.JSONMarshaler.Replace(&protojson.MarshalOptions{ Multiline: true, AllowPartial: false, UseEnumNumbers: false, EmitUnpopulated: true, UseProtoNames: true, // this should cause an error }) defer resttools.JSONMarshaler.Restore() name = "Compliance.RepeatDataBodyInfo#NegativeTestSnakeCasedFieldNames" request.Info.FString += name bodyBytes, err := resttools.ToJSON().Marshal(request.Info) return name, "POST", "/v1beta1/repeat:bodyinfo", string(bodyBytes), "(BodyFieldNameIncorrectlyCasedError)", err } func prepRepeatDataQueryNegativeTestSnakeCasedFieldNames(request *genproto.RepeatRequest) (verb string, name string, path string, body string, expect string, err error) { name = "Compliance.RepeatDataQuery#NegativeTestSnakeCasedFieldNames" queryParams := prepRepeatDataTestsQueryParams(request, nil, queryStringSnakeCaser) // this should cause an error queryString := prepQueryString(queryParams) return name, "GET", "/v1beta1/repeat:query" + queryString, body, "(QueryParameterNameIncorrectlyCasedError)", err } // checkExpectedFailure issues a request using the specified verb, URL, and request body. It expects // a failing HTTP code and a response message containing the substring in `failure`. Test errors are // reported using the given errorPrefix and the name prepName of the prepping function. func checkExpectedFailure(t *testing.T, verb, url, requestBody, failure, errorPrefix, prepName string) { // Issue the request httpRequest, err := http.NewRequest(verb, url, strings.NewReader(requestBody)) if err != nil { t.Errorf("%s error creating request: %s", errorPrefix, err) return } resttools.PopulateRequestHeaders(httpRequest) httpResponse, err := http.DefaultClient.Do(httpRequest) if err != nil { t.Errorf("%s error issuing call: %s", errorPrefix, err) return } // Check for unsuccessful response. if got, notWant := httpResponse.StatusCode, http.StatusOK; got == notWant { t.Errorf("%s response code: got %d, notWant %d name:%q\n %s %s\nrequest body: %s\n----------------------------------------\n", errorPrefix, got, notWant, prepName, verb, url, requestBody) return } body, err := io.ReadAll(httpResponse.Body) httpResponse.Body.Close() if err != nil { t.Fatalf("%s could not read response body: %s", errorPrefix, err) } if got, want := string(body), failure; !strings.Contains(got, want) { t.Errorf("%s response body: wanted response to include %q, but instead got: %q (status %d) header: %v name:%q\n %s %s\nrequest body: %s\n----------------------------------------\n", errorPrefix, want, got, httpResponse.StatusCode, httpResponse.Header, prepName, verb, url, requestBody) } } // requestModifer is a function that modifies a request in-place. type requestModifier func(*pb.RepeatRequest) ================================================ FILE: cmd/gapic-showcase/compliance_suite_test.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "fmt" "io" "net/http" "net/http/httptest" "net/url" "os" "path/filepath" "runtime" "strings" "testing" "github.com/google/go-cmp/cmp" "github.com/googleapis/gapic-showcase/server/genproto" pb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/googleapis/gapic-showcase/server/services" "github.com/googleapis/gapic-showcase/util/genrest/resttools" "github.com/iancoleman/strcase" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" ) // TestComplianceSuite ensures the REST test suite that we require GAPIC generators to pass works // correctly. GAPIC generators should generate GAPICs for the Showcase API and issue the unary calls // defined in the test suite using the GAPIC surface. The generators' test should follow the // high-level logic below, as described in the comments. func TestComplianceSuite(t *testing.T) { suite, server, err := complianceSuiteTestSetup() if err != nil { t.Fatal(err) } server.Start() defer server.Close() resttools.JSONMarshaler.Replace(nil) defer resttools.JSONMarshaler.Restore() // Set handlers for each test case. When GAPIC generator tests do this, they should have // each of their handlers invoking the correct GAPIC library method for the Showcase API. restRPCs := map[string]prepRepeatDataTestFunc{ "Compliance.RepeatDataBody": prepRepeatDataBodyTest, "Compliance.RepeatDataBodyPut": prepRepeatDataBodyPutTest, "Compliance.RepeatDataBodyPatch": prepRepeatDataBodyPatchTest, "Compliance.RepeatDataBodyInfo": prepRepeatDataBodyInfoTest, "Compliance.RepeatDataQuery": prepRepeatDataQueryTest, "Compliance.RepeatDataSimplePath": prepRepeatDataSimplePathTest, "Compliance.RepeatDataPathResource": prepRepeatDataPathResourceTest, "Compliance.RepeatDataPathTrailingResource": prepRepeatDataPathTrailingResourceTest, } for _, group := range suite.GetGroup() { rpcsToTest := group.GetRpcs() for requestIdx, requestProto := range group.GetRequests() { for rpcIdx, rpcName := range rpcsToTest { errorPrefix := fmt.Sprintf("[request %d/%q: rpc %q/%d/%q]", requestIdx, requestProto.GetName(), group.Name, rpcIdx, rpcName) // Ensure that we issue only the RPCs the test suite is expecting. rpcPrep, ok := restRPCs[rpcName] if !ok { t.Errorf("%s could not find prep function for this RPC", errorPrefix) continue } verb, prepName, path, requestBody, err := rpcPrep(requestProto) if err != nil { t.Errorf("%s error: %s", errorPrefix, err) } if got, want := prepName, rpcName; got != want { t.Errorf("%s retrieved mismatched prep function: got %q, want %q", errorPrefix, got, want) } // Issue the request. When GAPIC generator tests do this, they should simply // invoke the correct GAPIC library method for the Showcase API. httpRequest, err := http.NewRequest(verb, server.URL+path, strings.NewReader(requestBody)) if err != nil { t.Errorf("%s error creating request: %s", errorPrefix, err) continue } resttools.PopulateRequestHeaders(httpRequest) httpResponse, err := http.DefaultClient.Do(httpRequest) if err != nil { t.Errorf("%s error issuing call: %s", errorPrefix, err) continue } // Check for successful response. if got, want := httpResponse.StatusCode, http.StatusOK; got != want { t.Errorf("%s response code: got %d, want %d\n %s %s\n\n", errorPrefix, got, want, verb, server.URL+path) } // Unmarshal httpResponse body, interpreted as JSON. // should do this. responseBody, err := io.ReadAll(httpResponse.Body) httpResponse.Body.Close() if err != nil { t.Errorf("%s could not read httpResponse body: %s", errorPrefix, err) continue } var response genproto.RepeatResponse if err := protojson.Unmarshal(responseBody, &response); err != nil { t.Errorf("%s could not unmarshal httpResponse body: %s\n response body: %s\n request: %s\n", errorPrefix, err, string(responseBody), requestBody) continue } // Check for expected response. if diff := cmp.Diff(response.GetRequest(), requestProto, cmp.Comparer(proto.Equal)); diff != "" { t.Errorf("%s unexpected response: got=-, want=+:%s\n %s %s\n------------------------------\n", errorPrefix, diff, verb, server.URL+path) } } } } } func TestComplianceSuiteLoadedf(t *testing.T) { if services.ComplianceSuiteStatus != services.ComplianceSuiteLoaded { t.Fatalf("embedded compliance suite was not loaded: status %#v %s", services.ComplianceSuiteStatus, services.ComplianceSuiteStatusMessage) } suite, err := getCleanComplianceSuite() if err != nil { t.Fatal(err) } if diff := cmp.Diff(suite, services.ComplianceSuite, cmp.Comparer(proto.Equal)); diff != "" { t.Errorf("embedded compliance suite does not match released suite at %q", complianceSuiteFileName) } } // The following are helpers for TestComplianceSuite, since Showcase doesn't intrinsically define a // REST client. Each GAPIC generator should instead use the GAPIC it generated for the Showcase // API. type prepRepeatDataTestFunc func(request *genproto.RepeatRequest) (verb string, name string, path string, body string, err error) func prepRepeatDataBodyTest(request *genproto.RepeatRequest) (verb string, name string, path string, body string, err error) { name = "Compliance.RepeatDataBody" bodyBytes, err := resttools.ToJSON().Marshal(request) return "POST", name, "/v1beta1/repeat:body", string(bodyBytes), err } func prepRepeatDataBodyPutTest(request *genproto.RepeatRequest) (verb string, name string, path string, body string, err error) { _, _, path, body, err = prepRepeatDataBodyTest(request) return "PUT", "Compliance.RepeatDataBodyPut", path + "put", body, err } func prepRepeatDataBodyPatchTest(request *genproto.RepeatRequest) (verb string, name string, path string, body string, err error) { _, _, path, body, err = prepRepeatDataBodyTest(request) return "PATCH", "Compliance.RepeatDataBodyPatch", path + "patch", body, err } func prepRepeatDataBodyInfoTest(request *genproto.RepeatRequest) (verb string, name string, path string, body string, err error) { name = "Compliance.RepeatDataBodyInfo" bodyBytes, err := resttools.ToJSON().Marshal(request.Info) queryString := prepRepeatDataTestsQueryString(request, map[string]bool{"info": true}) _ = bodyBytes return "POST", name, "/v1beta1/repeat:bodyinfo" + queryString, string(bodyBytes), err } func prepRepeatDataQueryTest(request *genproto.RepeatRequest) (verb string, name string, path string, body string, err error) { name = "Compliance.RepeatDataQuery" queryString := prepRepeatDataTestsQueryString(request, nil) return "GET", name, "/v1beta1/repeat:query" + queryString, body, err } func prepRepeatDataSimplePathTest(request *genproto.RepeatRequest) (verb string, name string, path string, body string, err error) { name = "Compliance.RepeatDataSimplePath" info := request.GetInfo() // TODO: Determine behavior for a string field path param whose value is empty. This should be // a failure, probably, in which case we need to augment the ComplianceGroup to allow // specifying expected errors. pathParts := []string{} nonQueryParamNames := map[string]bool{} for _, part := range []struct { name string format string value interface{} }{ {"f_string", "%s", info.GetFString()}, {"f_int32", "%d", info.GetFInt32()}, {"f_double", "%g", info.GetFDouble()}, {"f_bool", "%t", info.GetFBool()}, {"f_kingdom", "%s", info.GetFKingdom()}, } { pathParts = append(pathParts, url.PathEscape(fmt.Sprintf(part.format, part.value))) nonQueryParamNames["info."+part.name] = true } path = fmt.Sprintf("/v1beta1/repeat/%s:simplepath", strings.Join(pathParts, "/")) queryString := prepRepeatDataTestsQueryString(request, nonQueryParamNames) return "GET", name, path + queryString, body, err } func prepRepeatDataPathResourceTest(request *genproto.RepeatRequest) (verb string, name string, path string, body string, err error) { name = "Compliance.RepeatDataPathResource" info := request.GetInfo() if strings.HasPrefix(info.GetFString(), "first/") { return prepRepeatDataPathResourceTestFirstBinding(request) } else { return prepRepeatDataPathResourceTestSecondBinding(request) } } func prepRepeatDataPathResourceTestFirstBinding(request *genproto.RepeatRequest) (verb string, name string, path string, body string, err error) { name = "Compliance.RepeatDataPathResource" info := request.GetInfo() pathParts := []string{} nonQueryParamNames := map[string]bool{} for _, part := range []struct { name string format string value interface{} requiredPrefix string }{ {"f_string", "%s", info.GetFString(), "first/"}, {"f_child.f_string", "%s", info.GetFChild().GetFString(), "second/"}, {"f_bool", "bool/%t", info.GetFBool(), ""}, } { if len(part.requiredPrefix) > 0 && !strings.HasPrefix(part.value.(string), part.requiredPrefix) { err = fmt.Errorf("expected value of %q to begin with %q; got %q", part.name, part.requiredPrefix, part.value) return } pathParts = append(pathParts, url.PathEscape(fmt.Sprintf(part.format, part.value))) nonQueryParamNames["info."+part.name] = true } path = fmt.Sprintf("/v1beta1/repeat/%s:pathresource", strings.Join(pathParts, "/")) queryString := prepRepeatDataTestsQueryString(request, nonQueryParamNames) return "GET", name, path + queryString, body, err } func prepRepeatDataPathResourceTestSecondBinding(request *genproto.RepeatRequest) (verb string, name string, path string, body string, err error) { name = "Compliance.RepeatDataPathResource" info := request.GetInfo() pathParts := []string{} nonQueryParamNames := map[string]bool{} for _, part := range []struct { name string format string value interface{} requiredPrefix string }{ {"f_child.f_string", "%s", info.GetFChild().GetFString(), "first/"}, {"f_string", "%s", info.GetFString(), "second/"}, {"f_bool", "bool/%t", info.GetFBool(), ""}, } { if len(part.requiredPrefix) > 0 && !strings.HasPrefix(part.value.(string), part.requiredPrefix) { err = fmt.Errorf("expected value of %q to begin with %q; got %q", part.name, part.requiredPrefix, part.value) return } pathParts = append(pathParts, url.PathEscape(fmt.Sprintf(part.format, part.value))) nonQueryParamNames["info."+part.name] = true } path = fmt.Sprintf("/v1beta1/repeat/%s:childfirstpathresource", strings.Join(pathParts, "/")) queryString := prepRepeatDataTestsQueryString(request, nonQueryParamNames) return "GET", name, path + queryString, body, err } func prepRepeatDataPathTrailingResourceTest(request *genproto.RepeatRequest) (verb string, name string, path string, body string, err error) { name = "Compliance.RepeatDataPathTrailingResource" info := request.GetInfo() pathParts := []string{} nonQueryParamNames := map[string]bool{} for _, part := range []struct { name string format string value interface{} requiredPrefix string }{ {"f_string", "%s", info.GetFString(), "first/"}, {"f_child.f_string", "%s", info.GetFChild().GetFString(), "second/"}, } { if len(part.requiredPrefix) > 0 && !strings.HasPrefix(part.value.(string), part.requiredPrefix) { err = fmt.Errorf("expected value of %q to begin with %q; got %q", part.name, part.requiredPrefix, part.value) return } pathParts = append(pathParts, url.PathEscape(fmt.Sprintf(part.format, part.value))) nonQueryParamNames["info."+part.name] = true } path = fmt.Sprintf("/v1beta1/repeat/%s:pathtrailingresource", strings.Join(pathParts, "/")) queryString := prepRepeatDataTestsQueryString(request, nonQueryParamNames) return "GET", name, path + queryString, body, err } // prepRepeatDataTestsQueryString returns the query string containing all fields in `request.info` // except for those whose proto name (relative to request.info) are present in the `exclude` map // with a value of `true`. func prepRepeatDataTestsQueryString(request *genproto.RepeatRequest, exclude map[string]bool) string { return prepQueryString(prepRepeatDataTestsQueryParams(request, exclude, queryStringLowerCamelCaser)) } // prepRepeatDataTestsQueryParams returns the list of key=value query params based on the contents // of request, excluding the fields in `exclude` and using the indicated caser. func prepRepeatDataTestsQueryParams(request *genproto.RepeatRequest, exclude map[string]bool, caser queryStringCaser) []string { info := request.GetInfo() queryParams := []string{} addParam := func(key string, condition bool, value string) { if (exclude["info"] && strings.HasPrefix(key, "info.")) || exclude[key] || !condition { return } queryParams = append(queryParams, fmt.Sprintf("%s=%s", caser(key), value)) } // Top-level fields addParam("server_verify", request.GetServerVerify(), "true") addParam("name", len(request.GetName()) > 0, url.QueryEscape(request.GetName())) addParam("intended_binding_uri", request.IntendedBindingUri != nil, url.QueryEscape(request.GetIntendedBindingUri())) addParam("f_int32", request.GetFInt32() != 0, fmt.Sprintf("%d", request.GetFInt32())) addParam("f_int64", request.GetFInt64() != 0, fmt.Sprintf("%d", request.GetFInt64())) addParam("f_double", request.GetFDouble() != 0, url.QueryEscape(fmt.Sprintf("%g", request.GetFDouble()))) addParam("p_int32", request.PInt32 != nil, fmt.Sprintf("%d", request.GetPInt32())) addParam("p_int64", request.PInt64 != nil, fmt.Sprintf("%d", request.GetPInt64())) addParam("p_double", request.PDouble != nil, url.QueryEscape(fmt.Sprintf("%g", request.GetPDouble()))) // info.* fields addParam("info.f_string", len(info.GetFString()) > 0, url.QueryEscape(info.GetFString())) addParam("info.f_int32", info.GetFInt32() != 0, fmt.Sprintf("%d", info.GetFInt32())) addParam("info.f_sint32", info.GetFSint32() != 0, fmt.Sprintf("%d", info.GetFSint32())) addParam("info.f_sfixed32", info.GetFSfixed32() != 0, fmt.Sprintf("%d", info.GetFSfixed32())) addParam("info.f_uint32", info.GetFUint32() != 0, fmt.Sprintf("%d", info.GetFUint32())) addParam("info.f_fixed32", info.GetFFixed32() != 0, fmt.Sprintf("%d", info.GetFFixed32())) addParam("info.f_int64", info.GetFInt64() != 0, fmt.Sprintf("%d", info.GetFInt64())) addParam("info.f_sint64", info.GetFSint64() != 0, fmt.Sprintf("%d", info.GetFSint64())) addParam("info.f_sfixed64", info.GetFSfixed64() != 0, fmt.Sprintf("%d", info.GetFSfixed64())) addParam("info.f_uint64", info.GetFUint64() != 0, fmt.Sprintf("%d", info.GetFUint64())) addParam("info.f_fixed64", info.GetFFixed64() != 0, fmt.Sprintf("%d", info.GetFFixed64())) addParam("info.f_double", info.GetFDouble() != 0, url.QueryEscape(fmt.Sprintf("%g", info.GetFDouble()))) addParam("info.f_float", info.GetFFloat() != 0, url.QueryEscape(fmt.Sprintf("%g", info.GetFFloat()))) addParam("info.f_bool", info.GetFBool(), "true") addParam("info.f_bytes", len(info.GetFBytes()) > 0, url.QueryEscape(string(info.GetFBytes()))) // TODO: Check this is correct, given runes in strings addParam("info.f_kingdom", info.GetFKingdom() != pb.ComplianceData_LIFE_KINGDOM_UNSPECIFIED, info.GetFKingdom().String()) addParam("info.p_string", info.PString != nil, url.QueryEscape(info.GetPString())) addParam("info.p_int32", info.PInt32 != nil, fmt.Sprintf("%d", info.GetPInt32())) addParam("info.p_double", info.PDouble != nil, url.QueryEscape(fmt.Sprintf("%g", info.GetPDouble()))) addParam("info.p_bool", info.PBool != nil, fmt.Sprintf("%t", info.GetPBool())) addParam("info.p_kingdom", info.PKingdom != nil, info.GetPKingdom().String()) addParam("info.f_child.f_string", len(info.GetFChild().GetFString()) > 0, url.QueryEscape(info.GetFChild().GetFString())) addParam("info.f_child.f_float", info.GetFChild().GetFFloat() != 0, url.QueryEscape(fmt.Sprintf("%g", info.GetFChild().GetFFloat()))) addParam("info.f_child.f_double", info.GetFChild().GetFDouble() != 0, url.QueryEscape(fmt.Sprintf("%g", info.GetFChild().GetFDouble()))) addParam("info.f_child.f_bool", info.GetFChild().GetFBool(), "true") // If needed for test cases, we'll have to add remaining nested message fields. return queryParams } func prepQueryString(queryParams []string) string { var queryString string if len(queryParams) > 0 { queryString = fmt.Sprintf("?%s", strings.Join(queryParams, "&")) } return queryString } // complianceSuiteTestSetup sets up the compliance suite test cases configuring the servers. func complianceSuiteTestSetup() (suite *pb.ComplianceSuite, server *httptest.Server, err error) { // Run the Showcase REST server locally. server = httptest.NewUnstartedServer(nil) backend := createBackends() restServer := newEndpointREST(nil, backend) server.Config = restServer.server suite, err = getCleanComplianceSuite() return suite, server, err } // getCleanComplianceSuite returns a clean copy of the compliance suite as parsed from the JSON // complianceSuiteFileName. This is needed because some negative tests modify requests, so we want to // always start with a fresh copy. func getCleanComplianceSuite() (*pb.ComplianceSuite, error) { if err := loadComplianceSuiteFile(); err != nil { return nil, err } suite := &pb.ComplianceSuite{} if err := protojson.Unmarshal(complianceSuiteJSON, suite); err != nil { return nil, fmt.Errorf("error unmarshalling from json %s:\n file: %s\n input was: %s", err, complianceSuiteFileName, complianceSuiteJSON) } return suite, nil } // loadComplianceSuiteFile loads the exported compliance_suite.json file (under schema/) to // complianceSuiteJSON if it hasn't been loaded already. This is done lazily at run-time rather than // in init() so we can report errors. func loadComplianceSuiteFile() (err error) { if len(complianceSuiteJSON) > 0 { // already loaded return nil } // Locate, load _, thisFile, _, _ := runtime.Caller(0) complianceSuiteFileName = filepath.Join(filepath.Dir(thisFile), "../../schema/google/showcase/v1beta1/compliance_suite.json") complianceSuiteJSON, err = os.ReadFile(complianceSuiteFileName) if err != nil { return fmt.Errorf("could not open suite file %q", complianceSuiteFileName) } return nil } // queryStringCaser is a convenience function type taking a string and returning its representation // under a particular casing scheme. type queryStringCaser func(string) string var queryStringLowerCamelCaser, queryStringSnakeCaser queryStringCaser var ( complianceSuiteJSON []byte // the contents of the suite file complianceSuiteFileName string // the name of the suite file ) func init() { queryStringLowerCamelCaser = resttools.ToDottedLowerCamel queryStringSnakeCaser = strcase.ToSnake } ================================================ FILE: cmd/gapic-showcase/connect.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "bufio" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var ConnectFromFile string var ConnectOutFile string func init() { MessagingServiceCmd.AddCommand(ConnectCmd) ConnectCmd.Flags().StringVar(&ConnectFromFile, "from_file", "", "Absolute path to JSON file containing request payload") ConnectCmd.Flags().StringVar(&ConnectOutFile, "out_file", "", "Absolute path to a file to pipe output to") ConnectCmd.MarkFlagRequired("out_file") } var ConnectCmd = &cobra.Command{ Use: "connect", Short: "This method starts a bidirectional stream that...", Long: "This method starts a bidirectional stream that receives all blurbs that are being created after the stream has started and sends requests to create ...", PreRun: func(cmd *cobra.Command, args []string) { }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if ConnectFromFile != "" { in, err = os.Open(ConnectFromFile) if err != nil { return err } defer in.Close() } stream, err := MessagingClient.Connect(ctx) if err != nil { return err } out, err := os.OpenFile(ConnectOutFile, os.O_APPEND|os.O_WRONLY, os.ModeAppend) if err != nil { return err } // start background stream receive go func() { var res *genprotopb.StreamBlurbsResponse for { res, err = stream.Recv() if err != nil { return } str := res.String() if OutputJSON { str, _ = marshaler.MarshalToString(res) } fmt.Fprintln(out, str) } }() if Verbose { fmt.Println("Client stream open. Close with ctrl+D.") } var ConnectInput genprotopb.ConnectRequest scanner := bufio.NewScanner(in) for scanner.Scan() { input := scanner.Text() if input == "" { continue } err = jsonpb.UnmarshalString(input, &ConnectInput) if err != nil { return err } err = stream.Send(&ConnectInput) if err != nil { return err } } if err = scanner.Err(); err != nil { return err } err = stream.CloseSend() return err }, } ================================================ FILE: cmd/gapic-showcase/create-blurb.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var CreateBlurbInput genprotopb.CreateBlurbRequest var CreateBlurbFromFile string var CreateBlurbInputBlurbContent string var CreateBlurbInputBlurbContentImage genprotopb.Blurb_Image var CreateBlurbInputBlurbContentText genprotopb.Blurb_Text var CreateBlurbInputBlurbLegacyId string var CreateBlurbInputBlurbLegacyIdLegacyRoomId genprotopb.Blurb_LegacyRoomId var CreateBlurbInputBlurbLegacyIdLegacyUserId genprotopb.Blurb_LegacyUserId func init() { MessagingServiceCmd.AddCommand(CreateBlurbCmd) CreateBlurbInput.Blurb = new(genprotopb.Blurb) CreateBlurbCmd.Flags().StringVar(&CreateBlurbInput.Parent, "parent", "", "Required. The resource name of the chat room or user...") CreateBlurbCmd.Flags().StringVar(&CreateBlurbInput.Blurb.Name, "blurb.name", "", "The resource name of the chat room.") CreateBlurbCmd.Flags().StringVar(&CreateBlurbInput.Blurb.User, "blurb.user", "", "Required. The resource name of the blurb's author.") CreateBlurbCmd.Flags().StringVar(&CreateBlurbInputBlurbContentText.Text, "blurb.content.text", "", "The textual content of this blurb.") CreateBlurbCmd.Flags().BytesHexVar(&CreateBlurbInputBlurbContentImage.Image, "blurb.content.image", []byte{}, "The image content of this blurb.") CreateBlurbCmd.Flags().StringVar(&CreateBlurbInputBlurbLegacyIdLegacyRoomId.LegacyRoomId, "blurb.legacy_id.legacy_room_id", "", "The legacy id of the room. This field is used to...") CreateBlurbCmd.Flags().StringVar(&CreateBlurbInputBlurbLegacyIdLegacyUserId.LegacyUserId, "blurb.legacy_id.legacy_user_id", "", "The legacy id of the user. This field is used to...") CreateBlurbCmd.Flags().StringVar(&CreateBlurbInputBlurbContent, "blurb.content", "", "Choices: text, image") CreateBlurbCmd.Flags().StringVar(&CreateBlurbInputBlurbLegacyId, "blurb.legacy_id", "", "Choices: legacy_room_id, legacy_user_id") CreateBlurbCmd.Flags().StringVar(&CreateBlurbFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var CreateBlurbCmd = &cobra.Command{ Use: "create-blurb", Short: "Creates a blurb. If the parent is a room, the...", Long: "Creates a blurb. If the parent is a room, the blurb is understood to be a message in that room. If the parent is a profile, the blurb is understood ...", PreRun: func(cmd *cobra.Command, args []string) { if CreateBlurbFromFile == "" { cmd.MarkFlagRequired("parent") cmd.MarkFlagRequired("blurb.user") cmd.MarkFlagRequired("blurb.content") cmd.MarkFlagRequired("blurb.legacy_id") } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if CreateBlurbFromFile != "" { in, err = os.Open(CreateBlurbFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &CreateBlurbInput) if err != nil { return err } } else { switch CreateBlurbInputBlurbContent { case "image": CreateBlurbInput.Blurb.Content = &CreateBlurbInputBlurbContentImage case "text": CreateBlurbInput.Blurb.Content = &CreateBlurbInputBlurbContentText default: return fmt.Errorf("Missing oneof choice for blurb.content") } switch CreateBlurbInputBlurbLegacyId { case "legacy_room_id": CreateBlurbInput.Blurb.LegacyId = &CreateBlurbInputBlurbLegacyIdLegacyRoomId case "legacy_user_id": CreateBlurbInput.Blurb.LegacyId = &CreateBlurbInputBlurbLegacyIdLegacyUserId default: return fmt.Errorf("Missing oneof choice for blurb.legacy_id") } } if Verbose { printVerboseInput("Messaging", "CreateBlurb", &CreateBlurbInput) } resp, err := MessagingClient.CreateBlurb(ctx, &CreateBlurbInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/create-room.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var CreateRoomInput genprotopb.CreateRoomRequest var CreateRoomFromFile string func init() { MessagingServiceCmd.AddCommand(CreateRoomCmd) CreateRoomInput.Room = new(genprotopb.Room) CreateRoomCmd.Flags().StringVar(&CreateRoomInput.Room.Name, "room.name", "", "The resource name of the chat room.") CreateRoomCmd.Flags().StringVar(&CreateRoomInput.Room.DisplayName, "room.display_name", "", "Required. The human readable name of the chat room.") CreateRoomCmd.Flags().StringVar(&CreateRoomInput.Room.Description, "room.description", "", "The description of the chat room.") CreateRoomCmd.Flags().StringVar(&CreateRoomFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var CreateRoomCmd = &cobra.Command{ Use: "create-room", Short: "Creates a room.", Long: "Creates a room.", PreRun: func(cmd *cobra.Command, args []string) { if CreateRoomFromFile == "" { cmd.MarkFlagRequired("room.display_name") } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if CreateRoomFromFile != "" { in, err = os.Open(CreateRoomFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &CreateRoomInput) if err != nil { return err } } if Verbose { printVerboseInput("Messaging", "CreateRoom", &CreateRoomInput) } resp, err := MessagingClient.CreateRoom(ctx, &CreateRoomInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/create-sequence.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var CreateSequenceInput genprotopb.CreateSequenceRequest var CreateSequenceFromFile string var CreateSequenceInputSequenceResponses []string func init() { SequenceServiceCmd.AddCommand(CreateSequenceCmd) CreateSequenceInput.Sequence = new(genprotopb.Sequence) CreateSequenceCmd.Flags().StringArrayVar(&CreateSequenceInputSequenceResponses, "sequence.responses", []string{}, "Sequence of responses to return in order for each...") CreateSequenceCmd.Flags().StringVar(&CreateSequenceFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var CreateSequenceCmd = &cobra.Command{ Use: "create-sequence", Short: "Create a sequence of responses to be returned as...", Long: "Create a sequence of responses to be returned as unary calls", PreRun: func(cmd *cobra.Command, args []string) { if CreateSequenceFromFile == "" { } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if CreateSequenceFromFile != "" { in, err = os.Open(CreateSequenceFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &CreateSequenceInput) if err != nil { return err } } // unmarshal JSON strings into slice of structs for _, item := range CreateSequenceInputSequenceResponses { tmp := genprotopb.Sequence_Response{} err = jsonpb.UnmarshalString(item, &tmp) if err != nil { return } CreateSequenceInput.Sequence.Responses = append(CreateSequenceInput.Sequence.Responses, &tmp) } if Verbose { printVerboseInput("Sequence", "CreateSequence", &CreateSequenceInput) } resp, err := SequenceClient.CreateSequence(ctx, &CreateSequenceInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/create-session.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" "strings" ) var CreateSessionInput genprotopb.CreateSessionRequest var CreateSessionFromFile string var CreateSessionInputSessionVersion string func init() { TestingServiceCmd.AddCommand(CreateSessionCmd) CreateSessionInput.Session = new(genprotopb.Session) CreateSessionCmd.Flags().StringVar(&CreateSessionInput.Session.Name, "session.name", "", "The name of the session. The ID must conform to...") CreateSessionCmd.Flags().StringVar(&CreateSessionInputSessionVersion, "session.version", "", "Required. The version this session is using.") CreateSessionCmd.Flags().StringVar(&CreateSessionFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var CreateSessionCmd = &cobra.Command{ Use: "create-session", Short: "Creates a new testing session. Adding this...", Long: "Creates a new testing session. Adding this comment with special characters for comment formatting tests: 1. (abra->kadabra->alakazam) 2)...", PreRun: func(cmd *cobra.Command, args []string) { if CreateSessionFromFile == "" { } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if CreateSessionFromFile != "" { in, err = os.Open(CreateSessionFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &CreateSessionInput) if err != nil { return err } } else { CreateSessionInput.Session.Version = genprotopb.Session_Version(genprotopb.Session_Version_value[strings.ToUpper(CreateSessionInputSessionVersion)]) } if Verbose { printVerboseInput("Testing", "CreateSession", &CreateSessionInput) } resp, err := TestingClient.CreateSession(ctx, &CreateSessionInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/create-streaming-sequence.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var CreateStreamingSequenceInput genprotopb.CreateStreamingSequenceRequest var CreateStreamingSequenceFromFile string var CreateStreamingSequenceInputStreamingSequenceResponses []string func init() { SequenceServiceCmd.AddCommand(CreateStreamingSequenceCmd) CreateStreamingSequenceInput.StreamingSequence = new(genprotopb.StreamingSequence) CreateStreamingSequenceCmd.Flags().StringVar(&CreateStreamingSequenceInput.StreamingSequence.Content, "streaming_sequence.content", "", "The content that the stream will send this was...") CreateStreamingSequenceCmd.Flags().StringArrayVar(&CreateStreamingSequenceInputStreamingSequenceResponses, "streaming_sequence.responses", []string{}, "Sequence of responses to return in order for each...") CreateStreamingSequenceCmd.Flags().StringVar(&CreateStreamingSequenceFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var CreateStreamingSequenceCmd = &cobra.Command{ Use: "create-streaming-sequence", Short: "Creates a sequence of responses to be returned in...", Long: "Creates a sequence of responses to be returned in a server streaming call", PreRun: func(cmd *cobra.Command, args []string) { if CreateStreamingSequenceFromFile == "" { } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if CreateStreamingSequenceFromFile != "" { in, err = os.Open(CreateStreamingSequenceFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &CreateStreamingSequenceInput) if err != nil { return err } } // unmarshal JSON strings into slice of structs for _, item := range CreateStreamingSequenceInputStreamingSequenceResponses { tmp := genprotopb.StreamingSequence_Response{} err = jsonpb.UnmarshalString(item, &tmp) if err != nil { return } CreateStreamingSequenceInput.StreamingSequence.Responses = append(CreateStreamingSequenceInput.StreamingSequence.Responses, &tmp) } if Verbose { printVerboseInput("Sequence", "CreateStreamingSequence", &CreateStreamingSequenceInput) } resp, err := SequenceClient.CreateStreamingSequence(ctx, &CreateStreamingSequenceInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/create-user.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var CreateUserInput genprotopb.CreateUserRequest var CreateUserFromFile string var createUserInputUserAge int32 var createUserInputUserHeightFeet float64 var createUserInputUserNickname string var createUserInputUserEnableNotifications bool func init() { IdentityServiceCmd.AddCommand(CreateUserCmd) CreateUserInput.User = new(genprotopb.User) CreateUserCmd.Flags().StringVar(&CreateUserInput.User.Name, "user.name", "", "The resource name of the user.") CreateUserCmd.Flags().StringVar(&CreateUserInput.User.DisplayName, "user.display_name", "", "Required. The display_name of the user.") CreateUserCmd.Flags().StringVar(&CreateUserInput.User.Email, "user.email", "", "Required. The email address of the user.") CreateUserCmd.Flags().Int32Var(&createUserInputUserAge, "user.age", 0, "The age of the user in years.") CreateUserCmd.Flags().Float64Var(&createUserInputUserHeightFeet, "user.height_feet", 0.0, "The height of the user in feet.") CreateUserCmd.Flags().StringVar(&createUserInputUserNickname, "user.nickname", "", "The nickname of the user. (--...") CreateUserCmd.Flags().BoolVar(&createUserInputUserEnableNotifications, "user.enable_notifications", false, "Enables the receiving of notifications. The...") CreateUserCmd.Flags().StringVar(&CreateUserFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var CreateUserCmd = &cobra.Command{ Use: "create-user", Short: "Creates a user.", Long: "Creates a user.", PreRun: func(cmd *cobra.Command, args []string) { if CreateUserFromFile == "" { cmd.MarkFlagRequired("user.display_name") cmd.MarkFlagRequired("user.email") } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if CreateUserFromFile != "" { in, err = os.Open(CreateUserFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &CreateUserInput) if err != nil { return err } } else { if cmd.Flags().Changed("user.age") { CreateUserInput.User.Age = &createUserInputUserAge } if cmd.Flags().Changed("user.height_feet") { CreateUserInput.User.HeightFeet = &createUserInputUserHeightFeet } if cmd.Flags().Changed("user.nickname") { CreateUserInput.User.Nickname = &createUserInputUserNickname } if cmd.Flags().Changed("user.enable_notifications") { CreateUserInput.User.EnableNotifications = &createUserInputUserEnableNotifications } } if Verbose { printVerboseInput("Identity", "CreateUser", &CreateUserInput) } resp, err := IdentityClient.CreateUser(ctx, &CreateUserInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/defaults.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "fmt" "os" ) func init() { // Since the showcase server is locally ran, the default address needs to be set // since the go gapic assumes port :443. services := []string{"ECHO", "IDENTITY", "MESSAGING", "TESTING", "SEQUENCE"} envVars := map[string]string{ "ADDRESS": "localhost:7469", "INSECURE": "true", } for _, service := range services { for key, value := range envVars { envName := fmt.Sprintf("GAPIC-SHOWCASE_%s_%s", service, key) if os.Getenv(envName) == "" { os.Setenv(envName, value) } } } } ================================================ FILE: cmd/gapic-showcase/delete-blurb.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var DeleteBlurbInput genprotopb.DeleteBlurbRequest var DeleteBlurbFromFile string func init() { MessagingServiceCmd.AddCommand(DeleteBlurbCmd) DeleteBlurbCmd.Flags().StringVar(&DeleteBlurbInput.Name, "name", "", "Required. The resource name of the requested blurb.") DeleteBlurbCmd.Flags().StringVar(&DeleteBlurbFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var DeleteBlurbCmd = &cobra.Command{ Use: "delete-blurb", Short: "Deletes a blurb.", Long: "Deletes a blurb.", PreRun: func(cmd *cobra.Command, args []string) { if DeleteBlurbFromFile == "" { cmd.MarkFlagRequired("name") } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if DeleteBlurbFromFile != "" { in, err = os.Open(DeleteBlurbFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &DeleteBlurbInput) if err != nil { return err } } if Verbose { printVerboseInput("Messaging", "DeleteBlurb", &DeleteBlurbInput) } err = MessagingClient.DeleteBlurb(ctx, &DeleteBlurbInput) if err != nil { return err } return err }, } ================================================ FILE: cmd/gapic-showcase/delete-room.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var DeleteRoomInput genprotopb.DeleteRoomRequest var DeleteRoomFromFile string func init() { MessagingServiceCmd.AddCommand(DeleteRoomCmd) DeleteRoomCmd.Flags().StringVar(&DeleteRoomInput.Name, "name", "", "Required. The resource name of the requested room.") DeleteRoomCmd.Flags().StringVar(&DeleteRoomFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var DeleteRoomCmd = &cobra.Command{ Use: "delete-room", Short: "Deletes a room and all of its blurbs.", Long: "Deletes a room and all of its blurbs.", PreRun: func(cmd *cobra.Command, args []string) { if DeleteRoomFromFile == "" { cmd.MarkFlagRequired("name") } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if DeleteRoomFromFile != "" { in, err = os.Open(DeleteRoomFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &DeleteRoomInput) if err != nil { return err } } if Verbose { printVerboseInput("Messaging", "DeleteRoom", &DeleteRoomInput) } err = MessagingClient.DeleteRoom(ctx, &DeleteRoomInput) if err != nil { return err } return err }, } ================================================ FILE: cmd/gapic-showcase/delete-session.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var DeleteSessionInput genprotopb.DeleteSessionRequest var DeleteSessionFromFile string func init() { TestingServiceCmd.AddCommand(DeleteSessionCmd) DeleteSessionCmd.Flags().StringVar(&DeleteSessionInput.Name, "name", "", "The session to be deleted.") DeleteSessionCmd.Flags().StringVar(&DeleteSessionFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var DeleteSessionCmd = &cobra.Command{ Use: "delete-session", Short: "Delete a test session.", Long: "Delete a test session.", PreRun: func(cmd *cobra.Command, args []string) { if DeleteSessionFromFile == "" { } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if DeleteSessionFromFile != "" { in, err = os.Open(DeleteSessionFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &DeleteSessionInput) if err != nil { return err } } if Verbose { printVerboseInput("Testing", "DeleteSession", &DeleteSessionInput) } err = TestingClient.DeleteSession(ctx, &DeleteSessionInput) if err != nil { return err } return err }, } ================================================ FILE: cmd/gapic-showcase/delete-test.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var DeleteTestInput genprotopb.DeleteTestRequest var DeleteTestFromFile string func init() { TestingServiceCmd.AddCommand(DeleteTestCmd) DeleteTestCmd.Flags().StringVar(&DeleteTestInput.Name, "name", "", "The test to be deleted.") DeleteTestCmd.Flags().StringVar(&DeleteTestFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var DeleteTestCmd = &cobra.Command{ Use: "delete-test", Short: "Explicitly decline to implement a test. This...", Long: "Explicitly decline to implement a test. This removes the test from subsequent `ListTests` calls, and attempting to do the test will error. This...", PreRun: func(cmd *cobra.Command, args []string) { if DeleteTestFromFile == "" { } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if DeleteTestFromFile != "" { in, err = os.Open(DeleteTestFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &DeleteTestInput) if err != nil { return err } } if Verbose { printVerboseInput("Testing", "DeleteTest", &DeleteTestInput) } err = TestingClient.DeleteTest(ctx, &DeleteTestInput) if err != nil { return err } return err }, } ================================================ FILE: cmd/gapic-showcase/delete-user.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var DeleteUserInput genprotopb.DeleteUserRequest var DeleteUserFromFile string func init() { IdentityServiceCmd.AddCommand(DeleteUserCmd) DeleteUserCmd.Flags().StringVar(&DeleteUserInput.Name, "name", "", "Required. The resource name of the user to delete.") DeleteUserCmd.Flags().StringVar(&DeleteUserFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var DeleteUserCmd = &cobra.Command{ Use: "delete-user", Short: "Deletes a user, their profile, and all of their...", Long: "Deletes a user, their profile, and all of their authored messages.", PreRun: func(cmd *cobra.Command, args []string) { if DeleteUserFromFile == "" { cmd.MarkFlagRequired("name") } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if DeleteUserFromFile != "" { in, err = os.Open(DeleteUserFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &DeleteUserInput) if err != nil { return err } } if Verbose { printVerboseInput("Identity", "DeleteUser", &DeleteUserInput) } err = IdentityClient.DeleteUser(ctx, &DeleteUserInput) if err != nil { return err } return err }, } ================================================ FILE: cmd/gapic-showcase/echo-error-details.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var EchoErrorDetailsInput genprotopb.EchoErrorDetailsRequest var EchoErrorDetailsFromFile string func init() { EchoServiceCmd.AddCommand(EchoErrorDetailsCmd) EchoErrorDetailsCmd.Flags().StringVar(&EchoErrorDetailsInput.SingleDetailText, "single_detail_text", "", "Content to return in a singular `*.error.details`...") EchoErrorDetailsCmd.Flags().StringSliceVar(&EchoErrorDetailsInput.MultiDetailText, "multi_detail_text", []string{}, "Content to return in a repeated `*.error.details`...") EchoErrorDetailsCmd.Flags().StringVar(&EchoErrorDetailsFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var EchoErrorDetailsCmd = &cobra.Command{ Use: "echo-error-details", Short: "This method returns error details in a repeated...", Long: "This method returns error details in a repeated 'google.protobuf.Any' field. This method showcases handling errors thus encoded, particularly over...", PreRun: func(cmd *cobra.Command, args []string) { if EchoErrorDetailsFromFile == "" { } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if EchoErrorDetailsFromFile != "" { in, err = os.Open(EchoErrorDetailsFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &EchoErrorDetailsInput) if err != nil { return err } } if Verbose { printVerboseInput("Echo", "EchoErrorDetails", &EchoErrorDetailsInput) } resp, err := EchoClient.EchoErrorDetails(ctx, &EchoErrorDetailsInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/echo.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" anypb "google.golang.org/protobuf/types/known/anypb" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" statuspb "google.golang.org/genproto/googleapis/rpc/status" "strings" ) var EchoInput genprotopb.EchoRequest var EchoFromFile string var EchoInputResponse string var EchoInputResponseContent genprotopb.EchoRequest_Content var EchoInputResponseError genprotopb.EchoRequest_Error var EchoInputResponseErrorDetails []string var EchoInputSeverity string var echoInputOtherRequestId string func init() { EchoServiceCmd.AddCommand(EchoCmd) EchoInputResponseError.Error = new(statuspb.Status) EchoCmd.Flags().StringVar(&EchoInputResponseContent.Content, "response.content", "", "The content to be echoed by the server.") EchoCmd.Flags().Int32Var(&EchoInputResponseError.Error.Code, "response.error.code", 0, "The status code, which should be an enum value of...") EchoCmd.Flags().StringVar(&EchoInputResponseError.Error.Message, "response.error.message", "", "A developer-facing error message, which should be...") EchoCmd.Flags().StringArrayVar(&EchoInputResponseErrorDetails, "response.error.details", []string{}, "A list of messages that carry the error details. ...") EchoCmd.Flags().StringVar(&EchoInputSeverity, "severity", "", "The severity to be echoed by the server.") EchoCmd.Flags().StringVar(&EchoInput.Header, "header", "", "Optional. This field can be set to test the...") EchoCmd.Flags().StringVar(&EchoInput.OtherHeader, "other_header", "", "Optional. This field can be set to test the...") EchoCmd.Flags().StringVar(&EchoInput.RequestId, "request_id", "", "To facilitate testing of...") EchoCmd.Flags().StringVar(&echoInputOtherRequestId, "other_request_id", "", "To facilitate testing of...") EchoCmd.Flags().StringVar(&EchoInputResponse, "response", "", "Choices: content, error") EchoCmd.Flags().StringVar(&EchoFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var EchoCmd = &cobra.Command{ Use: "echo", Short: "This method simply echoes the request. This...", Long: "This method simply echoes the request. This method showcases unary RPCs.", PreRun: func(cmd *cobra.Command, args []string) { if EchoFromFile == "" { cmd.MarkFlagRequired("response") } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if EchoFromFile != "" { in, err = os.Open(EchoFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &EchoInput) if err != nil { return err } } else { switch EchoInputResponse { case "content": EchoInput.Response = &EchoInputResponseContent case "error": EchoInput.Response = &EchoInputResponseError default: return fmt.Errorf("Missing oneof choice for response") } EchoInput.Severity = genprotopb.Severity(genprotopb.Severity_value[strings.ToUpper(EchoInputSeverity)]) if cmd.Flags().Changed("other_request_id") { EchoInput.OtherRequestId = &echoInputOtherRequestId } } // unmarshal JSON strings into slice of structs for _, item := range EchoInputResponseErrorDetails { tmp := anypb.Any{} err = jsonpb.UnmarshalString(item, &tmp) if err != nil { return } EchoInputResponseError.Error.Details = append(EchoInputResponseError.Error.Details, &tmp) } if Verbose { printVerboseInput("Echo", "Echo", &EchoInput) } resp, err := EchoClient.Echo(ctx, &EchoInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/echo_service.go ================================================ // Code generated. DO NOT EDIT. package main import ( "fmt" "github.com/spf13/cobra" "github.com/spf13/viper" "golang.org/x/oauth2" "google.golang.org/api/option" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" gapic "github.com/googleapis/gapic-showcase/client" ) var EchoConfig *viper.Viper var EchoClient *gapic.EchoClient var EchoSubCommands []string = []string{ "echo", "echo-error-details", "fail-echo-with-details", "expand", "collect", "chat", "paged-expand", "paged-expand-legacy", "paged-expand-legacy-mapped", "wait", "poll-wait", "block", } func init() { rootCmd.AddCommand(EchoServiceCmd) EchoConfig = viper.New() EchoConfig.SetEnvPrefix("GAPIC-SHOWCASE_ECHO") EchoConfig.AutomaticEnv() EchoServiceCmd.PersistentFlags().Bool("insecure", false, "Make insecure client connection. Or use GAPIC-SHOWCASE_ECHO_INSECURE. Must be used with \"address\" option") EchoConfig.BindPFlag("insecure", EchoServiceCmd.PersistentFlags().Lookup("insecure")) EchoConfig.BindEnv("insecure") EchoServiceCmd.PersistentFlags().String("address", "", "Set API address used by client. Or use GAPIC-SHOWCASE_ECHO_ADDRESS.") EchoConfig.BindPFlag("address", EchoServiceCmd.PersistentFlags().Lookup("address")) EchoConfig.BindEnv("address") EchoServiceCmd.PersistentFlags().String("token", "", "Set Bearer token used by the client. Or use GAPIC-SHOWCASE_ECHO_TOKEN.") EchoConfig.BindPFlag("token", EchoServiceCmd.PersistentFlags().Lookup("token")) EchoConfig.BindEnv("token") EchoServiceCmd.PersistentFlags().String("api_key", "", "Set API Key used by the client. Or use GAPIC-SHOWCASE_ECHO_API_KEY.") EchoConfig.BindPFlag("api_key", EchoServiceCmd.PersistentFlags().Lookup("api_key")) EchoConfig.BindEnv("api_key") } var EchoServiceCmd = &cobra.Command{ Use: "echo", Short: "This service is used showcase the four main types...", Long: "This service is used showcase the four main types of rpcs - unary, server side streaming, client side streaming, and bidirectional streaming. This ...", ValidArgs: EchoSubCommands, PersistentPreRunE: func(cmd *cobra.Command, args []string) (err error) { var opts []option.ClientOption address := EchoConfig.GetString("address") if address != "" { opts = append(opts, option.WithEndpoint(address)) } if EchoConfig.GetBool("insecure") { if address == "" { return fmt.Errorf("Missing address to use with insecure connection") } conn, err := grpc.Dial(address, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { return err } opts = append(opts, option.WithGRPCConn(conn)) } if token := EchoConfig.GetString("token"); token != "" { opts = append(opts, option.WithTokenSource(oauth2.StaticTokenSource( &oauth2.Token{ AccessToken: token, TokenType: "Bearer", }))) } if key := EchoConfig.GetString("api_key"); key != "" { opts = append(opts, option.WithAPIKey(key)) } EchoClient, err = gapic.NewEchoClient(ctx, opts...) return }, } ================================================ FILE: cmd/gapic-showcase/endpoint.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "context" "crypto/tls" "crypto/x509" "fmt" "log" "net" "net/http" "os" "strings" "sync" iampb "cloud.google.com/go/iam/apiv1/iampb" lropb "cloud.google.com/go/longrunning/autogen/longrunningpb" "github.com/googleapis/gapic-showcase/server" pb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/googleapis/gapic-showcase/server/genrest" "github.com/googleapis/gapic-showcase/server/services" fallback "github.com/googleapis/grpc-fallback-go/server" gmux "github.com/gorilla/mux" "github.com/soheilhy/cmux" "golang.org/x/sync/errgroup" locpb "google.golang.org/genproto/googleapis/cloud/location" "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/reflection" ) // RuntimeConfig has the run-time settings necessary to run the // Showcase servers. type RuntimeConfig struct { port string fallbackPort string tlsCaCert string tlsCert string tlsKey string } // Endpoint defines common operations for any of the various types of // transport-specific network endpoints Showcase supports type Endpoint interface { // Serve beings the listen-and-serve loop for this // Endpoint. It typically blocks until the server is shut // down. The error it returns depends on the underlying // implementation. Serve() error // Shutdown causes the currently running Endpoint to // terminate. The error it returns depends on the underlying // implementation. Shutdown() error } // CreateAllEndpoints returns an Endpoint that can serve gRPC and // HTTP/REST connections (on config.port) and gRPC-fallback // connections (on config.fallbackPort) func CreateAllEndpoints(config RuntimeConfig) Endpoint { // Ensure port is of the right form. if !strings.HasPrefix(config.port, ":") { config.port = ":" + config.port } // Start listening. lis, err := net.Listen("tcp", config.port) if err != nil { log.Fatalf("Showcase failed to listen on port '%s': %v", config.port, err) } stdLog.Printf("Showcase listening on port: %s", config.port) m := cmux.New(lis) httpListener := m.Match(cmux.HTTP1()) // cmux.Any() is needed below to get mTLS to work for // gRPC, and that in turn means the order of the matchers matters. See // https://github.com/open-telemetry/opentelemetry-collector/issues/2732 grpcListener := m.Match(cmux.Any()) backend := createBackends() gRPCServer := newEndpointGRPC(grpcListener, config, backend) restServer := newEndpointREST(httpListener, backend) cmuxServer := newEndpointMux(m, gRPCServer, restServer) return cmuxServer } // endpointMux is an Endpoint for cmux, the connection multiplexer // allowing different types of connections on the same port. // // We choose not to use grpc.Server.ServeHTTP because it is // experimental and does not support some gRPC features available // through grpc.Server.Serve. (cf // https://godoc.org/google.golang.org/grpc#Server.ServeHTTP) type endpointMux struct { endpoints []Endpoint cmux cmux.CMux mux sync.Mutex } func newEndpointMux(cmuxEndpoint cmux.CMux, endpoints ...Endpoint) Endpoint { return &endpointMux{ endpoints: endpoints, cmux: cmuxEndpoint, } } func (em *endpointMux) String() string { return "endpoint multiplexer" } func (em *endpointMux) Serve() error { g := new(errgroup.Group) for idx, endpt := range em.endpoints { if endpt != nil { stdLog.Printf("Starting endpoint %d: %s", idx, endpt) endpoint := endpt g.Go(func() error { err := endpoint.Serve() err2 := em.Shutdown() if err != nil { return err } return err2 }) } } if em.cmux != nil { stdLog.Printf("Starting %s", em) g.Go(func() error { err := em.cmux.Serve() err2 := em.Shutdown() if err != nil { return err } return err2 }) } return g.Wait() } func (em *endpointMux) Shutdown() error { em.mux.Lock() defer em.mux.Unlock() var err error if em.cmux != nil { // TODO: Wait for https://github.com/soheilhy/cmux/pull/69 (due to // https://github.com/soheilhy/cmux/pull/69#issuecomment-712928041.) // // err = em.mux.Close() em.cmux = nil } for idx, endpt := range em.endpoints { if endpt != nil { // TODO: Wait for https://github.com/soheilhy/cmux/pull/69 // newErr := endpt.Shutdown() // if err==nil { // err = newErr // } em.endpoints[idx] = nil } } return err } // endpointGRPC is an Endpoint for gRPC connections to the Showcase // server. type endpointGRPC struct { server *grpc.Server fallbackServer *fallback.FallbackServer listener net.Listener mux sync.Mutex } // createBackends creates services used by both the gRPC and REST servers. func createBackends() *services.Backend { logger := &loggerObserver{} observerRegistry := server.ShowcaseObserverRegistry() observerRegistry.RegisterUnaryObserver(logger) observerRegistry.RegisterStreamRequestObserver(logger) observerRegistry.RegisterStreamResponseObserver(logger) identityServer := services.NewIdentityServer() messagingServer := services.NewMessagingServer(identityServer) return &services.Backend{ EchoServer: services.NewEchoServer(), SequenceServiceServer: services.NewSequenceServer(), IdentityServer: identityServer, MessagingServer: messagingServer, ComplianceServer: services.NewComplianceServer(), TestingServer: services.NewTestingServer(observerRegistry), OperationsServer: services.NewOperationsServer(messagingServer), LocationsServer: services.NewLocationsServer(), IAMPolicyServer: services.NewIAMPolicyServer(), StdLog: stdLog, ErrLog: errLog, ObserverRegistry: observerRegistry, } } func newEndpointGRPC(lis net.Listener, config RuntimeConfig, backend *services.Backend) Endpoint { opts := []grpc.ServerOption{ grpc.StreamInterceptor(backend.ObserverRegistry.StreamInterceptor), grpc.UnaryInterceptor(backend.ObserverRegistry.UnaryInterceptor), } // load mutual TLS cert/key and root CA cert if config.tlsCaCert != "" && config.tlsCert != "" && config.tlsKey != "" { keyPair, err := tls.LoadX509KeyPair(config.tlsCert, config.tlsKey) if err != nil { log.Fatalf("Failed to load server TLS cert/key with error:%v", err) } cert, err := os.ReadFile(config.tlsCaCert) if err != nil { log.Fatalf("Failed to load root CA cert file with error:%v", err) } pool := x509.NewCertPool() pool.AppendCertsFromPEM(cert) ta := credentials.NewTLS(&tls.Config{ Certificates: []tls.Certificate{keyPair}, ClientCAs: pool, ClientAuth: tls.RequireAndVerifyClientCert, }) opts = append(opts, grpc.Creds(ta)) } s := grpc.NewServer(opts...) // Register Services to the server. pb.RegisterEchoServer(s, backend.EchoServer) pb.RegisterSequenceServiceServer(s, backend.SequenceServiceServer) pb.RegisterIdentityServer(s, backend.IdentityServer) pb.RegisterMessagingServer(s, backend.MessagingServer) pb.RegisterComplianceServer(s, backend.ComplianceServer) pb.RegisterTestingServer(s, backend.TestingServer) lropb.RegisterOperationsServer(s, backend.OperationsServer) locpb.RegisterLocationsServer(s, backend.LocationsServer) iampb.RegisterIAMPolicyServer(s, backend.IAMPolicyServer) fb := fallback.NewServer(config.fallbackPort, "localhost"+config.port) // Register reflection service on gRPC server. reflection.Register(s) return &endpointGRPC{ server: s, fallbackServer: fb, listener: lis, } } func (eg *endpointGRPC) String() string { return "gRPC endpoint" } func (eg *endpointGRPC) Serve() error { defer eg.Shutdown() if eg.fallbackServer != nil { stdLog.Printf("Listening for gRPC-fallback connections") eg.fallbackServer.StartBackground() } if eg.server != nil { stdLog.Printf("Listening for gRPC connections") return eg.server.Serve(eg.listener) } return fmt.Errorf("gRPC server not set up") } func (eg *endpointGRPC) Shutdown() error { eg.mux.Lock() defer eg.mux.Unlock() if eg.fallbackServer != nil { stdLog.Printf("Stopping gRPC-fallback connections") eg.fallbackServer.Shutdown() eg.fallbackServer = nil } if eg.server != nil { stdLog.Printf("Stopping gRPC connections") eg.server.GracefulStop() eg.server = nil } stdLog.Printf("Stopped gRPC") return nil } // endpointREST is an Endpoint for HTTP/REST connections to the Showcase // server. type endpointREST struct { server *http.Server listener net.Listener mux sync.Mutex } func newEndpointREST(lis net.Listener, backend *services.Backend) *endpointREST { router := gmux.NewRouter() router.HandleFunc("/hello", func(w http.ResponseWriter, _ *http.Request) { w.Write([]byte("GAPIC Showcase: HTTP/REST endpoint using gorilla/mux\n")) }) genrest.RegisterHandlers(router, backend) return &endpointREST{ server: &http.Server{Handler: router}, listener: lis, } } func (er *endpointREST) String() string { return "HTTP/REST endpoint" } func (er *endpointREST) Serve() error { defer er.Shutdown() if er.server != nil { stdLog.Printf("Listening for REST connections") return er.server.Serve(er.listener) } return fmt.Errorf("REST server not set up") } func (er *endpointREST) Shutdown() error { er.mux.Lock() defer er.mux.Unlock() var err error if er.server != nil { stdLog.Printf("Stopping REST connections") err = er.server.Shutdown(context.Background()) er.server = nil } stdLog.Printf("Stopped REST") return err } ================================================ FILE: cmd/gapic-showcase/endpoint_test.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "io" "log" "net/http" "net/http/httptest" "strings" "testing" "github.com/googleapis/gapic-showcase/util/genrest/resttools" "google.golang.org/protobuf/encoding/protojson" ) // TestRESTCalls tests that arbitrary rest calls received by the Showcase REST server are handled // correctly. func TestRESTCalls(t *testing.T) { server := httptest.NewUnstartedServer(nil) backend := createBackends() restServer := newEndpointREST(nil, backend) server.Config = restServer.server server.Start() defer server.Close() for idx, testCase := range []struct { verb string path string body string fullJSON bool want string statusCode int // 0 taken to mean 200 for simplicity }{ { verb: "GET", path: "/hello", want: "GAPIC Showcase: HTTP/REST endpoint using gorilla/mux\n", }, { verb: "POST", path: "/v1beta1/repeat:body", body: `{"info":{"fString":"jonas^ mila"}}`, want: `{"request":{"info":{"fString":"jonas^ mila"}}, "bindingUri":"/v1beta1/repeat:body"}`, }, { verb: "GET", path: "/v1beta1/repeat:query?info.fString=jonas+mila", want: `{"request":{"info":{"fString":"jonas mila"}}, "bindingUri":"/v1beta1/repeat:query"}`, }, { verb: "GET", path: "/v1beta1/repeat:query?info.fString=jonas^mila", // TODO: Fix so that this returns an error, because `^` is not URL-escaped statusCode: 200, want: `{"request":{"info":{"fString":"jonas^mila"}}, "bindingUri":"/v1beta1/repeat:query"}`, }, { verb: "GET", path: "/v1beta1/repeat:query?info.fString=jonas mila", statusCode: 400, // unescaped space in query param }, { verb: "GET", path: "/v1beta1/repeat:query?info.p_kingdom=EXTRATERRESTRIAL", statusCode: 400, // unknown enum value symbol }, { verb: "GET", path: "/v1beta1/repeat:query?info.p_kingdom=ANIMALIA", statusCode: 400, // non-camel-cased field name }, { verb: "GET", path: "/v1beta1/repeat:query?info.PKingdom=ANIMALIA", statusCode: 400, // non-lower-camel-cased field name }, { // Test sending an enum as a number in the query parameter verb: "GET", path: "/v1beta1/repeat:query?info.pKingdom=1", want: `{ "request":{ "info":{ "pKingdom":"ARCHAEBACTERIA" } }, "bindingUri":"/v1beta1/repeat:query" }`, }, { // Test sending an enum as a number in the body verb: "POST", path: "/v1beta1/repeat:body", body: `{"info":{"pKingdom": 1}}`, want: `{ "request":{ "info":{ "pKingdom":"ARCHAEBACTERIA" } }, "bindingUri":"/v1beta1/repeat:body" }`, }, { // Test responses: // 1. unset optional field absent // 2. zero-set optional field present // 3. unset non-optional field present // 4. enum field is symbolic rather than numeric verb: "POST", path: "/v1beta1/repeat:body", body: `{"info":{"fString":"jonas^ mila", "pDouble": 0}}`, fullJSON: true, want: `{ "request": { "name": "", "info": { "fString": "jonas^ mila", "fInt32": 0, "fSint32": 0, "fSfixed32": 0, "fUint32": 0, "fFixed32": 0, "fInt64": "0", "fSint64": "0", "fSfixed64": "0", "fUint64": "0", "fFixed64": "0", "fDouble": 0, "fFloat": 0, "fBool": false, "fBytes": "", "fKingdom": "LIFE_KINGDOM_UNSPECIFIED", "fChild": null, "pDouble": 0 }, "serverVerify": false, "fInt32": 0, "fInt64": "0", "fDouble": 0 }, "bindingUri":"/v1beta1/repeat:body" } `, }, } { var jsonOptions *resttools.JSONMarshalOptions if testCase.fullJSON { jsonOptions = allowFullJSON() } else { jsonOptions = allowCompactJSON() } request, err := http.NewRequest(testCase.verb, server.URL+testCase.path, strings.NewReader(testCase.body)) if err != nil { jsonOptions.Restore() t.Fatal(err) } resttools.PopulateRequestHeaders(request) response, err := http.DefaultClient.Do(request) if err != nil { jsonOptions.Restore() t.Fatal(err) } want := testCase.statusCode if want == 0 { want = 200 } if got := response.StatusCode; got != want { t.Errorf("testcase %2d: status code: got %d, want %d", idx, got, want) t.Errorf(" request: %v", request) } else if want != 200 { // we got the expected error jsonOptions.Restore() continue } body, err := io.ReadAll(response.Body) response.Body.Close() if err != nil { jsonOptions.Restore() log.Fatal(err) } if got, want := string(body), testCase.want; noSpace(got) != noSpace(want) { t.Errorf("testcase %2d: body: got %q, want %q", idx, noSpace(got), noSpace(want)) t.Errorf(" request: %v", request) } jsonOptions.Restore() } } // allowCompactJSON ensures that resttools JSONMarshaler uses the compact representation until // explicitly restored; this makes some tests shorter to configure and easier to understand. func allowCompactJSON() *resttools.JSONMarshalOptions { resttools.JSONMarshaler.Replace(&protojson.MarshalOptions{ Multiline: false, AllowPartial: false, UseEnumNumbers: false, EmitUnpopulated: false, UseProtoNames: false, // we want lower-camel-cased field names }) return &resttools.JSONMarshaler } // allowFullJSON ensures that resttools JSONMarshaler uses the production configuration until // explicitly restored. func allowFullJSON() *resttools.JSONMarshalOptions { resttools.JSONMarshaler.Replace(nil) return &resttools.JSONMarshaler } // noSpace removes whitespace from src. This is useful for processing formatted responses or // expected values without having to worry about whitespace matches. func noSpace(src string) string { str := strings.ReplaceAll(src, "\n", "") return strings.ReplaceAll(str, " ", "") } ================================================ FILE: cmd/gapic-showcase/expand.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" anypb "google.golang.org/protobuf/types/known/anypb" durationpb "google.golang.org/protobuf/types/known/durationpb" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "io" "os" statuspb "google.golang.org/genproto/googleapis/rpc/status" ) var ExpandInput genprotopb.ExpandRequest var ExpandFromFile string var ExpandInputErrorDetails []string func init() { EchoServiceCmd.AddCommand(ExpandCmd) ExpandInput.Error = new(statuspb.Status) ExpandInput.StreamWaitTime = new(durationpb.Duration) ExpandCmd.Flags().StringVar(&ExpandInput.Content, "content", "", "The content that will be split into words and...") ExpandCmd.Flags().Int32Var(&ExpandInput.Error.Code, "error.code", 0, "The status code, which should be an enum value of...") ExpandCmd.Flags().StringVar(&ExpandInput.Error.Message, "error.message", "", "A developer-facing error message, which should be...") ExpandCmd.Flags().StringArrayVar(&ExpandInputErrorDetails, "error.details", []string{}, "A list of messages that carry the error details. ...") ExpandCmd.Flags().Int64Var(&ExpandInput.StreamWaitTime.Seconds, "stream_wait_time.seconds", 0, "Signed seconds of the span of time. Must be from...") ExpandCmd.Flags().Int32Var(&ExpandInput.StreamWaitTime.Nanos, "stream_wait_time.nanos", 0, "Signed fractions of a second at nanosecond...") ExpandCmd.Flags().StringVar(&ExpandFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var ExpandCmd = &cobra.Command{ Use: "expand", Short: "This method splits the given content into words...", Long: "This method splits the given content into words and will pass each word back through the stream. This method showcases server-side streaming RPCs.", PreRun: func(cmd *cobra.Command, args []string) { if ExpandFromFile == "" { } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if ExpandFromFile != "" { in, err = os.Open(ExpandFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &ExpandInput) if err != nil { return err } } // unmarshal JSON strings into slice of structs for _, item := range ExpandInputErrorDetails { tmp := anypb.Any{} err = jsonpb.UnmarshalString(item, &tmp) if err != nil { return } ExpandInput.Error.Details = append(ExpandInput.Error.Details, &tmp) } if Verbose { printVerboseInput("Echo", "Expand", &ExpandInput) } resp, err := EchoClient.Expand(ctx, &ExpandInput) if err != nil { return err } var item *genprotopb.EchoResponse for { item, err = resp.Recv() if err != nil { break } if Verbose { fmt.Print("Output: ") } printMessage(item) } if err == io.EOF { return nil } return err }, } ================================================ FILE: cmd/gapic-showcase/fail-echo-with-details.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var FailEchoWithDetailsInput genprotopb.FailEchoWithDetailsRequest var FailEchoWithDetailsFromFile string func init() { EchoServiceCmd.AddCommand(FailEchoWithDetailsCmd) FailEchoWithDetailsCmd.Flags().StringVar(&FailEchoWithDetailsInput.Message, "message", "", "Optional message to echo back in the PoetryError....") FailEchoWithDetailsCmd.Flags().StringVar(&FailEchoWithDetailsFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var FailEchoWithDetailsCmd = &cobra.Command{ Use: "fail-echo-with-details", Short: "This method always fails with a gRPC 'Aborted'...", Long: "This method always fails with a gRPC 'Aborted' error status that contains multiple error details. These include one instance of each of the...", PreRun: func(cmd *cobra.Command, args []string) { if FailEchoWithDetailsFromFile == "" { } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if FailEchoWithDetailsFromFile != "" { in, err = os.Open(FailEchoWithDetailsFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &FailEchoWithDetailsInput) if err != nil { return err } } if Verbose { printVerboseInput("Echo", "FailEchoWithDetails", &FailEchoWithDetailsInput) } resp, err := EchoClient.FailEchoWithDetails(ctx, &FailEchoWithDetailsInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/gapic-showcase.go ================================================ // Code generated. DO NOT EDIT. package main import ( "bytes" "context" "fmt" "os" "github.com/golang/protobuf/jsonpb" "github.com/golang/protobuf/proto" "github.com/spf13/cobra" ) var Verbose, OutputJSON bool var ctx = context.Background() var marshaler = &jsonpb.Marshaler{Indent: " "} func init() { rootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "Print verbose output") rootCmd.PersistentFlags().BoolVarP(&OutputJSON, "json", "j", false, "Print JSON output") } var rootCmd = &cobra.Command{ Use: "gapic-showcase", Short: "Root command of gapic-showcase", } func Execute() { if err := rootCmd.Execute(); err != nil { fmt.Println(err) os.Exit(1) } } func main() { Execute() } func printVerboseInput(srv, mthd string, data interface{}) { fmt.Println("Service:", srv) fmt.Println("Method:", mthd) fmt.Print("Input: ") printMessage(data) } func printMessage(data interface{}) { var s string if msg, ok := data.(proto.Message); ok { s = msg.String() if OutputJSON { var b bytes.Buffer marshaler.Marshal(&b, msg) s = b.String() } } fmt.Println(s) } ================================================ FILE: cmd/gapic-showcase/get-blurb.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var GetBlurbInput genprotopb.GetBlurbRequest var GetBlurbFromFile string func init() { MessagingServiceCmd.AddCommand(GetBlurbCmd) GetBlurbCmd.Flags().StringVar(&GetBlurbInput.Name, "name", "", "Required. The resource name of the requested blurb.") GetBlurbCmd.Flags().StringVar(&GetBlurbFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var GetBlurbCmd = &cobra.Command{ Use: "get-blurb", Short: "Retrieves the Blurb with the given resource name.", Long: "Retrieves the Blurb with the given resource name.", PreRun: func(cmd *cobra.Command, args []string) { if GetBlurbFromFile == "" { cmd.MarkFlagRequired("name") } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if GetBlurbFromFile != "" { in, err = os.Open(GetBlurbFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &GetBlurbInput) if err != nil { return err } } if Verbose { printVerboseInput("Messaging", "GetBlurb", &GetBlurbInput) } resp, err := MessagingClient.GetBlurb(ctx, &GetBlurbInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/get-enum.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var GetEnumInput genprotopb.EnumRequest var GetEnumFromFile string func init() { ComplianceServiceCmd.AddCommand(GetEnumCmd) GetEnumCmd.Flags().BoolVar(&GetEnumInput.UnknownEnum, "unknown_enum", false, "Whether the client is requesting a new, unknown...") GetEnumCmd.Flags().StringVar(&GetEnumFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var GetEnumCmd = &cobra.Command{ Use: "get-enum", Short: "This method requests an enum value from the...", Long: "This method requests an enum value from the server. Depending on the contents of EnumRequest, the enum value returned will be a known enum declared...", PreRun: func(cmd *cobra.Command, args []string) { if GetEnumFromFile == "" { } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if GetEnumFromFile != "" { in, err = os.Open(GetEnumFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &GetEnumInput) if err != nil { return err } } if Verbose { printVerboseInput("Compliance", "GetEnum", &GetEnumInput) } resp, err := ComplianceClient.GetEnum(ctx, &GetEnumInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/get-room.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var GetRoomInput genprotopb.GetRoomRequest var GetRoomFromFile string func init() { MessagingServiceCmd.AddCommand(GetRoomCmd) GetRoomCmd.Flags().StringVar(&GetRoomInput.Name, "name", "", "Required. The resource name of the requested room.") GetRoomCmd.Flags().StringVar(&GetRoomFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var GetRoomCmd = &cobra.Command{ Use: "get-room", Short: "Retrieves the Room with the given resource name.", Long: "Retrieves the Room with the given resource name.", PreRun: func(cmd *cobra.Command, args []string) { if GetRoomFromFile == "" { cmd.MarkFlagRequired("name") } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if GetRoomFromFile != "" { in, err = os.Open(GetRoomFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &GetRoomInput) if err != nil { return err } } if Verbose { printVerboseInput("Messaging", "GetRoom", &GetRoomInput) } resp, err := MessagingClient.GetRoom(ctx, &GetRoomInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/get-sequence-report.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var GetSequenceReportInput genprotopb.GetSequenceReportRequest var GetSequenceReportFromFile string func init() { SequenceServiceCmd.AddCommand(GetSequenceReportCmd) GetSequenceReportCmd.Flags().StringVar(&GetSequenceReportInput.Name, "name", "", "Required. ") GetSequenceReportCmd.Flags().StringVar(&GetSequenceReportFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var GetSequenceReportCmd = &cobra.Command{ Use: "get-sequence-report", Short: "Retrieves a sequence report which can be used to...", Long: "Retrieves a sequence report which can be used to retrieve information about a sequence of unary calls.", PreRun: func(cmd *cobra.Command, args []string) { if GetSequenceReportFromFile == "" { cmd.MarkFlagRequired("name") } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if GetSequenceReportFromFile != "" { in, err = os.Open(GetSequenceReportFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &GetSequenceReportInput) if err != nil { return err } } if Verbose { printVerboseInput("Sequence", "GetSequenceReport", &GetSequenceReportInput) } resp, err := SequenceClient.GetSequenceReport(ctx, &GetSequenceReportInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/get-session.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var GetSessionInput genprotopb.GetSessionRequest var GetSessionFromFile string func init() { TestingServiceCmd.AddCommand(GetSessionCmd) GetSessionCmd.Flags().StringVar(&GetSessionInput.Name, "name", "", "The session to be retrieved.") GetSessionCmd.Flags().StringVar(&GetSessionFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var GetSessionCmd = &cobra.Command{ Use: "get-session", Short: "Gets a testing session.", Long: "Gets a testing session.", PreRun: func(cmd *cobra.Command, args []string) { if GetSessionFromFile == "" { } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if GetSessionFromFile != "" { in, err = os.Open(GetSessionFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &GetSessionInput) if err != nil { return err } } if Verbose { printVerboseInput("Testing", "GetSession", &GetSessionInput) } resp, err := TestingClient.GetSession(ctx, &GetSessionInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/get-streaming-sequence-report.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var GetStreamingSequenceReportInput genprotopb.GetStreamingSequenceReportRequest var GetStreamingSequenceReportFromFile string func init() { SequenceServiceCmd.AddCommand(GetStreamingSequenceReportCmd) GetStreamingSequenceReportCmd.Flags().StringVar(&GetStreamingSequenceReportInput.Name, "name", "", "Required. ") GetStreamingSequenceReportCmd.Flags().StringVar(&GetStreamingSequenceReportFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var GetStreamingSequenceReportCmd = &cobra.Command{ Use: "get-streaming-sequence-report", Short: "Retrieves a sequence report which can be used to...", Long: "Retrieves a sequence report which can be used to retrieve information about a sequences of responses in a server streaming call.", PreRun: func(cmd *cobra.Command, args []string) { if GetStreamingSequenceReportFromFile == "" { cmd.MarkFlagRequired("name") } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if GetStreamingSequenceReportFromFile != "" { in, err = os.Open(GetStreamingSequenceReportFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &GetStreamingSequenceReportInput) if err != nil { return err } } if Verbose { printVerboseInput("Sequence", "GetStreamingSequenceReport", &GetStreamingSequenceReportInput) } resp, err := SequenceClient.GetStreamingSequenceReport(ctx, &GetStreamingSequenceReportInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/get-user.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var GetUserInput genprotopb.GetUserRequest var GetUserFromFile string func init() { IdentityServiceCmd.AddCommand(GetUserCmd) GetUserCmd.Flags().StringVar(&GetUserInput.Name, "name", "", "Required. The resource name of the requested user.") GetUserCmd.Flags().StringVar(&GetUserFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var GetUserCmd = &cobra.Command{ Use: "get-user", Short: "Retrieves the User with the given uri.", Long: "Retrieves the User with the given uri.", PreRun: func(cmd *cobra.Command, args []string) { if GetUserFromFile == "" { cmd.MarkFlagRequired("name") } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if GetUserFromFile != "" { in, err = os.Open(GetUserFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &GetUserInput) if err != nil { return err } } if Verbose { printVerboseInput("Identity", "GetUser", &GetUserInput) } resp, err := IdentityClient.GetUser(ctx, &GetUserInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/identity_service.go ================================================ // Code generated. DO NOT EDIT. package main import ( "fmt" "github.com/spf13/cobra" "github.com/spf13/viper" "golang.org/x/oauth2" "google.golang.org/api/option" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" gapic "github.com/googleapis/gapic-showcase/client" ) var IdentityConfig *viper.Viper var IdentityClient *gapic.IdentityClient var IdentitySubCommands []string = []string{ "create-user", "get-user", "update-user", "delete-user", "list-users", } func init() { rootCmd.AddCommand(IdentityServiceCmd) IdentityConfig = viper.New() IdentityConfig.SetEnvPrefix("GAPIC-SHOWCASE_IDENTITY") IdentityConfig.AutomaticEnv() IdentityServiceCmd.PersistentFlags().Bool("insecure", false, "Make insecure client connection. Or use GAPIC-SHOWCASE_IDENTITY_INSECURE. Must be used with \"address\" option") IdentityConfig.BindPFlag("insecure", IdentityServiceCmd.PersistentFlags().Lookup("insecure")) IdentityConfig.BindEnv("insecure") IdentityServiceCmd.PersistentFlags().String("address", "", "Set API address used by client. Or use GAPIC-SHOWCASE_IDENTITY_ADDRESS.") IdentityConfig.BindPFlag("address", IdentityServiceCmd.PersistentFlags().Lookup("address")) IdentityConfig.BindEnv("address") IdentityServiceCmd.PersistentFlags().String("token", "", "Set Bearer token used by the client. Or use GAPIC-SHOWCASE_IDENTITY_TOKEN.") IdentityConfig.BindPFlag("token", IdentityServiceCmd.PersistentFlags().Lookup("token")) IdentityConfig.BindEnv("token") IdentityServiceCmd.PersistentFlags().String("api_key", "", "Set API Key used by the client. Or use GAPIC-SHOWCASE_IDENTITY_API_KEY.") IdentityConfig.BindPFlag("api_key", IdentityServiceCmd.PersistentFlags().Lookup("api_key")) IdentityConfig.BindEnv("api_key") } var IdentityServiceCmd = &cobra.Command{ Use: "identity", Short: "A simple identity service.", Long: "A simple identity service.", ValidArgs: IdentitySubCommands, PersistentPreRunE: func(cmd *cobra.Command, args []string) (err error) { var opts []option.ClientOption address := IdentityConfig.GetString("address") if address != "" { opts = append(opts, option.WithEndpoint(address)) } if IdentityConfig.GetBool("insecure") { if address == "" { return fmt.Errorf("Missing address to use with insecure connection") } conn, err := grpc.Dial(address, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { return err } opts = append(opts, option.WithGRPCConn(conn)) } if token := IdentityConfig.GetString("token"); token != "" { opts = append(opts, option.WithTokenSource(oauth2.StaticTokenSource( &oauth2.Token{ AccessToken: token, TokenType: "Bearer", }))) } if key := IdentityConfig.GetString("api_key"); key != "" { opts = append(opts, option.WithAPIKey(key)) } IdentityClient, err = gapic.NewIdentityClient(ctx, opts...) return }, } ================================================ FILE: cmd/gapic-showcase/list-blurbs.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "google.golang.org/api/iterator" "os" ) var ListBlurbsInput genprotopb.ListBlurbsRequest var ListBlurbsFromFile string func init() { MessagingServiceCmd.AddCommand(ListBlurbsCmd) ListBlurbsCmd.Flags().StringVar(&ListBlurbsInput.Parent, "parent", "", "Required. The resource name of the requested room or...") ListBlurbsCmd.Flags().Int32Var(&ListBlurbsInput.PageSize, "page_size", 10, "Default is 10. The maximum number of blurbs to return. Server...") ListBlurbsCmd.Flags().StringVar(&ListBlurbsInput.PageToken, "page_token", "", "The value of...") ListBlurbsCmd.Flags().StringVar(&ListBlurbsFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var ListBlurbsCmd = &cobra.Command{ Use: "list-blurbs", Short: "Lists blurbs for a specific chat room or user...", Long: "Lists blurbs for a specific chat room or user profile depending on the parent resource name.", PreRun: func(cmd *cobra.Command, args []string) { if ListBlurbsFromFile == "" { cmd.MarkFlagRequired("parent") } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if ListBlurbsFromFile != "" { in, err = os.Open(ListBlurbsFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &ListBlurbsInput) if err != nil { return err } } if Verbose { printVerboseInput("Messaging", "ListBlurbs", &ListBlurbsInput) } iter := MessagingClient.ListBlurbs(ctx, &ListBlurbsInput) // populate iterator with a page _, err = iter.Next() if err != nil && err != iterator.Done { return err } if Verbose { fmt.Print("Output: ") } printMessage(iter.Response) if err == iterator.Done { return nil } return err }, } ================================================ FILE: cmd/gapic-showcase/list-rooms.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "google.golang.org/api/iterator" "os" ) var ListRoomsInput genprotopb.ListRoomsRequest var ListRoomsFromFile string func init() { MessagingServiceCmd.AddCommand(ListRoomsCmd) ListRoomsCmd.Flags().Int32Var(&ListRoomsInput.PageSize, "page_size", 10, "Default is 10. The maximum number of rooms return. Server may...") ListRoomsCmd.Flags().StringVar(&ListRoomsInput.PageToken, "page_token", "", "The value of...") ListRoomsCmd.Flags().StringVar(&ListRoomsFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var ListRoomsCmd = &cobra.Command{ Use: "list-rooms", Short: "Lists all chat rooms.", Long: "Lists all chat rooms.", PreRun: func(cmd *cobra.Command, args []string) { if ListRoomsFromFile == "" { } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if ListRoomsFromFile != "" { in, err = os.Open(ListRoomsFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &ListRoomsInput) if err != nil { return err } } if Verbose { printVerboseInput("Messaging", "ListRooms", &ListRoomsInput) } iter := MessagingClient.ListRooms(ctx, &ListRoomsInput) // populate iterator with a page _, err = iter.Next() if err != nil && err != iterator.Done { return err } if Verbose { fmt.Print("Output: ") } printMessage(iter.Response) if err == iterator.Done { return nil } return err }, } ================================================ FILE: cmd/gapic-showcase/list-sessions.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "google.golang.org/api/iterator" "os" ) var ListSessionsInput genprotopb.ListSessionsRequest var ListSessionsFromFile string func init() { TestingServiceCmd.AddCommand(ListSessionsCmd) ListSessionsCmd.Flags().Int32Var(&ListSessionsInput.PageSize, "page_size", 10, "Default is 10. The maximum number of sessions to return per page.") ListSessionsCmd.Flags().StringVar(&ListSessionsInput.PageToken, "page_token", "", "The page token, for retrieving subsequent pages.") ListSessionsCmd.Flags().StringVar(&ListSessionsFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var ListSessionsCmd = &cobra.Command{ Use: "list-sessions", Short: "Lists the current test sessions.", Long: "Lists the current test sessions.", PreRun: func(cmd *cobra.Command, args []string) { if ListSessionsFromFile == "" { } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if ListSessionsFromFile != "" { in, err = os.Open(ListSessionsFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &ListSessionsInput) if err != nil { return err } } if Verbose { printVerboseInput("Testing", "ListSessions", &ListSessionsInput) } iter := TestingClient.ListSessions(ctx, &ListSessionsInput) // populate iterator with a page _, err = iter.Next() if err != nil && err != iterator.Done { return err } if Verbose { fmt.Print("Output: ") } printMessage(iter.Response) if err == iterator.Done { return nil } return err }, } ================================================ FILE: cmd/gapic-showcase/list-tests.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "google.golang.org/api/iterator" "os" ) var ListTestsInput genprotopb.ListTestsRequest var ListTestsFromFile string func init() { TestingServiceCmd.AddCommand(ListTestsCmd) ListTestsCmd.Flags().StringVar(&ListTestsInput.Parent, "parent", "", "The session.") ListTestsCmd.Flags().Int32Var(&ListTestsInput.PageSize, "page_size", 10, "Default is 10. The maximum number of tests to return per page.") ListTestsCmd.Flags().StringVar(&ListTestsInput.PageToken, "page_token", "", "The page token, for retrieving subsequent pages.") ListTestsCmd.Flags().StringVar(&ListTestsFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var ListTestsCmd = &cobra.Command{ Use: "list-tests", Short: "List the tests of a sessesion.", Long: "List the tests of a sessesion.", PreRun: func(cmd *cobra.Command, args []string) { if ListTestsFromFile == "" { } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if ListTestsFromFile != "" { in, err = os.Open(ListTestsFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &ListTestsInput) if err != nil { return err } } if Verbose { printVerboseInput("Testing", "ListTests", &ListTestsInput) } iter := TestingClient.ListTests(ctx, &ListTestsInput) // populate iterator with a page _, err = iter.Next() if err != nil && err != iterator.Done { return err } if Verbose { fmt.Print("Output: ") } printMessage(iter.Response) if err == iterator.Done { return nil } return err }, } ================================================ FILE: cmd/gapic-showcase/list-users.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "google.golang.org/api/iterator" "os" ) var ListUsersInput genprotopb.ListUsersRequest var ListUsersFromFile string func init() { IdentityServiceCmd.AddCommand(ListUsersCmd) ListUsersCmd.Flags().Int32Var(&ListUsersInput.PageSize, "page_size", 10, "Default is 10. The maximum number of users to return. Server may...") ListUsersCmd.Flags().StringVar(&ListUsersInput.PageToken, "page_token", "", "The value of...") ListUsersCmd.Flags().StringVar(&ListUsersFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var ListUsersCmd = &cobra.Command{ Use: "list-users", Short: "Lists all users.", Long: "Lists all users.", PreRun: func(cmd *cobra.Command, args []string) { if ListUsersFromFile == "" { } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if ListUsersFromFile != "" { in, err = os.Open(ListUsersFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &ListUsersInput) if err != nil { return err } } if Verbose { printVerboseInput("Identity", "ListUsers", &ListUsersInput) } iter := IdentityClient.ListUsers(ctx, &ListUsersInput) // populate iterator with a page _, err = iter.Next() if err != nil && err != iterator.Done { return err } if Verbose { fmt.Print("Output: ") } printMessage(iter.Response) if err == iterator.Done { return nil } return err }, } ================================================ FILE: cmd/gapic-showcase/loggers.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "context" "log" "os" "google.golang.org/grpc" "google.golang.org/grpc/metadata" ) var stdLog, errLog *log.Logger func init() { stdLog = log.New(os.Stdout, "", log.Ldate|log.Ltime) errLog = log.New(os.Stderr, "", log.Ldate|log.Ltime) } type loggerObserver struct{} func (l *loggerObserver) GetName() string { return "loggerObserver" } func dumpIncomingHeaders(ctx context.Context) { md, ok := metadata.FromIncomingContext(ctx) if !ok { stdLog.Printf("Cannot get metadata from the context.") return } stdLog.Printf(" Request headers:") for key, values := range md { for _, value := range values { stdLog.Printf(" %s: %s\n", key, value) } } } func (l *loggerObserver) ObserveUnary( ctx context.Context, req interface{}, resp interface{}, info *grpc.UnaryServerInfo, err error) { stdLog.Printf("Received Unary Request for Method: %s\n", info.FullMethod) if Verbose { dumpIncomingHeaders(ctx) } stdLog.Printf(" Request: %+v\n", req) if err == nil { stdLog.Printf(" Returning Response: %+v\n", resp) } else { stdLog.Printf(" Returning Error: %+v\n", err) } stdLog.Println("") } func (l *loggerObserver) ObserveStreamRequest( ctx context.Context, req interface{}, info *grpc.StreamServerInfo, _ error) { stdLog.Printf("%s Stream for Method: %s\n", streamType(info), info.FullMethod) if Verbose { dumpIncomingHeaders(ctx) } stdLog.Printf(" Receiving Message: %v\n", req) stdLog.Println("") } func (l *loggerObserver) ObserveStreamResponse( _ context.Context, resp interface{}, info *grpc.StreamServerInfo, _ error) { stdLog.Printf("%s Stream for Method: %s\n", streamType(info), info.FullMethod) stdLog.Printf(" Sending Message: %+v\n", resp) stdLog.Println("") } func streamType(info *grpc.StreamServerInfo) string { if info.IsClientStream && info.IsServerStream { return "Bi-directional" } else if info.IsClientStream { return "Client" } return "Server" } ================================================ FILE: cmd/gapic-showcase/messaging_service.go ================================================ // Code generated. DO NOT EDIT. package main import ( "fmt" "github.com/spf13/cobra" "github.com/spf13/viper" "golang.org/x/oauth2" "google.golang.org/api/option" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" gapic "github.com/googleapis/gapic-showcase/client" ) var MessagingConfig *viper.Viper var MessagingClient *gapic.MessagingClient var MessagingSubCommands []string = []string{ "create-room", "get-room", "update-room", "delete-room", "list-rooms", "create-blurb", "get-blurb", "update-blurb", "delete-blurb", "list-blurbs", "search-blurbs", "poll-search-blurbs", "stream-blurbs", "send-blurbs", "connect", } func init() { rootCmd.AddCommand(MessagingServiceCmd) MessagingConfig = viper.New() MessagingConfig.SetEnvPrefix("GAPIC-SHOWCASE_MESSAGING") MessagingConfig.AutomaticEnv() MessagingServiceCmd.PersistentFlags().Bool("insecure", false, "Make insecure client connection. Or use GAPIC-SHOWCASE_MESSAGING_INSECURE. Must be used with \"address\" option") MessagingConfig.BindPFlag("insecure", MessagingServiceCmd.PersistentFlags().Lookup("insecure")) MessagingConfig.BindEnv("insecure") MessagingServiceCmd.PersistentFlags().String("address", "", "Set API address used by client. Or use GAPIC-SHOWCASE_MESSAGING_ADDRESS.") MessagingConfig.BindPFlag("address", MessagingServiceCmd.PersistentFlags().Lookup("address")) MessagingConfig.BindEnv("address") MessagingServiceCmd.PersistentFlags().String("token", "", "Set Bearer token used by the client. Or use GAPIC-SHOWCASE_MESSAGING_TOKEN.") MessagingConfig.BindPFlag("token", MessagingServiceCmd.PersistentFlags().Lookup("token")) MessagingConfig.BindEnv("token") MessagingServiceCmd.PersistentFlags().String("api_key", "", "Set API Key used by the client. Or use GAPIC-SHOWCASE_MESSAGING_API_KEY.") MessagingConfig.BindPFlag("api_key", MessagingServiceCmd.PersistentFlags().Lookup("api_key")) MessagingConfig.BindEnv("api_key") } var MessagingServiceCmd = &cobra.Command{ Use: "messaging", Short: "A simple messaging service that implements chat...", Long: "A simple messaging service that implements chat rooms and profile posts. This messaging service showcases the features that API clients generated...", ValidArgs: MessagingSubCommands, PersistentPreRunE: func(cmd *cobra.Command, args []string) (err error) { var opts []option.ClientOption address := MessagingConfig.GetString("address") if address != "" { opts = append(opts, option.WithEndpoint(address)) } if MessagingConfig.GetBool("insecure") { if address == "" { return fmt.Errorf("Missing address to use with insecure connection") } conn, err := grpc.Dial(address, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { return err } opts = append(opts, option.WithGRPCConn(conn)) } if token := MessagingConfig.GetString("token"); token != "" { opts = append(opts, option.WithTokenSource(oauth2.StaticTokenSource( &oauth2.Token{ AccessToken: token, TokenType: "Bearer", }))) } if key := MessagingConfig.GetString("api_key"); key != "" { opts = append(opts, option.WithAPIKey(key)) } MessagingClient, err = gapic.NewMessagingClient(ctx, opts...) return }, } ================================================ FILE: cmd/gapic-showcase/paged-expand-legacy-mapped.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "google.golang.org/api/iterator" "os" ) var PagedExpandLegacyMappedInput genprotopb.PagedExpandRequest var PagedExpandLegacyMappedFromFile string func init() { EchoServiceCmd.AddCommand(PagedExpandLegacyMappedCmd) PagedExpandLegacyMappedCmd.Flags().StringVar(&PagedExpandLegacyMappedInput.Content, "content", "", "Required. The string to expand.") PagedExpandLegacyMappedCmd.Flags().Int32Var(&PagedExpandLegacyMappedInput.PageSize, "page_size", 10, "Default is 10. The number of words to returned in each page.") PagedExpandLegacyMappedCmd.Flags().StringVar(&PagedExpandLegacyMappedInput.PageToken, "page_token", "", "The position of the page to be returned.") PagedExpandLegacyMappedCmd.Flags().StringVar(&PagedExpandLegacyMappedFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var PagedExpandLegacyMappedCmd = &cobra.Command{ Use: "paged-expand-legacy-mapped", Short: "This method returns a map containing lists of...", Long: "This method returns a map containing lists of words that appear in the input, keyed by their initial character. The only words returned are the ones...", PreRun: func(cmd *cobra.Command, args []string) { if PagedExpandLegacyMappedFromFile == "" { cmd.MarkFlagRequired("content") } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if PagedExpandLegacyMappedFromFile != "" { in, err = os.Open(PagedExpandLegacyMappedFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &PagedExpandLegacyMappedInput) if err != nil { return err } } if Verbose { printVerboseInput("Echo", "PagedExpandLegacyMapped", &PagedExpandLegacyMappedInput) } iter := EchoClient.PagedExpandLegacyMapped(ctx, &PagedExpandLegacyMappedInput) // populate iterator with a page _, err = iter.Next() if err != nil && err != iterator.Done { return err } if Verbose { fmt.Print("Output: ") } printMessage(iter.Response) if err == iterator.Done { return nil } return err }, } ================================================ FILE: cmd/gapic-showcase/paged-expand.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "google.golang.org/api/iterator" "os" ) var PagedExpandInput genprotopb.PagedExpandRequest var PagedExpandFromFile string func init() { EchoServiceCmd.AddCommand(PagedExpandCmd) PagedExpandCmd.Flags().StringVar(&PagedExpandInput.Content, "content", "", "Required. The string to expand.") PagedExpandCmd.Flags().Int32Var(&PagedExpandInput.PageSize, "page_size", 10, "Default is 10. The number of words to returned in each page.") PagedExpandCmd.Flags().StringVar(&PagedExpandInput.PageToken, "page_token", "", "The position of the page to be returned.") PagedExpandCmd.Flags().StringVar(&PagedExpandFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var PagedExpandCmd = &cobra.Command{ Use: "paged-expand", Short: "This is similar to the Expand method but instead...", Long: "This is similar to the Expand method but instead of returning a stream of expanded words, this method returns a paged list of expanded words.", PreRun: func(cmd *cobra.Command, args []string) { if PagedExpandFromFile == "" { cmd.MarkFlagRequired("content") } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if PagedExpandFromFile != "" { in, err = os.Open(PagedExpandFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &PagedExpandInput) if err != nil { return err } } if Verbose { printVerboseInput("Echo", "PagedExpand", &PagedExpandInput) } iter := EchoClient.PagedExpand(ctx, &PagedExpandInput) // populate iterator with a page _, err = iter.Next() if err != nil && err != iterator.Done { return err } if Verbose { fmt.Print("Output: ") } printMessage(iter.Response) if err == iterator.Done { return nil } return err }, } ================================================ FILE: cmd/gapic-showcase/repeat-data-body-info.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" "strings" ) var RepeatDataBodyInfoInput genprotopb.RepeatRequest var RepeatDataBodyInfoFromFile string var RepeatDataBodyInfoInputInfoFKingdom string var RepeatDataBodyInfoInputInfoFChildFContinent string var repeatDataBodyInfoInputInfoFChildPString string var repeatDataBodyInfoInputInfoFChildPFloat float32 var repeatDataBodyInfoInputInfoFChildPDouble float64 var repeatDataBodyInfoInputInfoFChildPBool bool var RepeatDataBodyInfoInputInfoFChildPContinent string var repeatDataBodyInfoInputInfoPString string var repeatDataBodyInfoInputInfoPInt32 int32 var repeatDataBodyInfoInputInfoPSint32 int32 var repeatDataBodyInfoInputInfoPSfixed32 int32 var repeatDataBodyInfoInputInfoPUint32 uint32 var repeatDataBodyInfoInputInfoPFixed32 uint32 var repeatDataBodyInfoInputInfoPInt64 int64 var repeatDataBodyInfoInputInfoPSint64 int64 var repeatDataBodyInfoInputInfoPSfixed64 int64 var repeatDataBodyInfoInputInfoPUint64 uint64 var repeatDataBodyInfoInputInfoPFixed64 uint64 var repeatDataBodyInfoInputInfoPFloat float32 var repeatDataBodyInfoInputInfoPDouble float64 var repeatDataBodyInfoInputInfoPBool bool var RepeatDataBodyInfoInputInfoPKingdom string var RepeatDataBodyInfoInputInfoPChildFContinent string var repeatDataBodyInfoInputInfoPChildPString string var repeatDataBodyInfoInputInfoPChildPFloat float32 var repeatDataBodyInfoInputInfoPChildPDouble float64 var repeatDataBodyInfoInputInfoPChildPBool bool var RepeatDataBodyInfoInputInfoPChildPContinent string var repeatDataBodyInfoInputIntendedBindingUri string var repeatDataBodyInfoInputPInt32 int32 var repeatDataBodyInfoInputPInt64 int64 var repeatDataBodyInfoInputPDouble float64 func init() { ComplianceServiceCmd.AddCommand(RepeatDataBodyInfoCmd) RepeatDataBodyInfoInput.Info = new(genprotopb.ComplianceData) RepeatDataBodyInfoInput.Info.FChild = new(genprotopb.ComplianceDataChild) RepeatDataBodyInfoInput.Info.FChild.FChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataBodyInfoInput.Info.FChild.PChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataBodyInfoInput.Info.PChild = new(genprotopb.ComplianceDataChild) RepeatDataBodyInfoInput.Info.PChild.FChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataBodyInfoInput.Info.PChild.PChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataBodyInfoCmd.Flags().StringVar(&RepeatDataBodyInfoInput.Name, "name", "", "") RepeatDataBodyInfoCmd.Flags().StringVar(&RepeatDataBodyInfoInput.Info.FString, "info.f_string", "", "") RepeatDataBodyInfoCmd.Flags().Int32Var(&RepeatDataBodyInfoInput.Info.FInt32, "info.f_int32", 0, "") RepeatDataBodyInfoCmd.Flags().Int32Var(&RepeatDataBodyInfoInput.Info.FSint32, "info.f_sint32", 0, "") RepeatDataBodyInfoCmd.Flags().Int32Var(&RepeatDataBodyInfoInput.Info.FSfixed32, "info.f_sfixed32", 0, "") RepeatDataBodyInfoCmd.Flags().Uint32Var(&RepeatDataBodyInfoInput.Info.FUint32, "info.f_uint32", 0, "") RepeatDataBodyInfoCmd.Flags().Uint32Var(&RepeatDataBodyInfoInput.Info.FFixed32, "info.f_fixed32", 0, "") RepeatDataBodyInfoCmd.Flags().Int64Var(&RepeatDataBodyInfoInput.Info.FInt64, "info.f_int64", 0, "") RepeatDataBodyInfoCmd.Flags().Int64Var(&RepeatDataBodyInfoInput.Info.FSint64, "info.f_sint64", 0, "") RepeatDataBodyInfoCmd.Flags().Int64Var(&RepeatDataBodyInfoInput.Info.FSfixed64, "info.f_sfixed64", 0, "") RepeatDataBodyInfoCmd.Flags().Uint64Var(&RepeatDataBodyInfoInput.Info.FUint64, "info.f_uint64", 0, "") RepeatDataBodyInfoCmd.Flags().Uint64Var(&RepeatDataBodyInfoInput.Info.FFixed64, "info.f_fixed64", 0, "") RepeatDataBodyInfoCmd.Flags().Float64Var(&RepeatDataBodyInfoInput.Info.FDouble, "info.f_double", 0.0, "") RepeatDataBodyInfoCmd.Flags().Float32Var(&RepeatDataBodyInfoInput.Info.FFloat, "info.f_float", 0.0, "") RepeatDataBodyInfoCmd.Flags().BoolVar(&RepeatDataBodyInfoInput.Info.FBool, "info.f_bool", false, "") RepeatDataBodyInfoCmd.Flags().BytesHexVar(&RepeatDataBodyInfoInput.Info.FBytes, "info.f_bytes", []byte{}, "") RepeatDataBodyInfoCmd.Flags().StringVar(&RepeatDataBodyInfoInputInfoFKingdom, "info.f_kingdom", "", "") RepeatDataBodyInfoCmd.Flags().StringVar(&RepeatDataBodyInfoInput.Info.FChild.FString, "info.f_child.f_string", "", "") RepeatDataBodyInfoCmd.Flags().Float32Var(&RepeatDataBodyInfoInput.Info.FChild.FFloat, "info.f_child.f_float", 0.0, "") RepeatDataBodyInfoCmd.Flags().Float64Var(&RepeatDataBodyInfoInput.Info.FChild.FDouble, "info.f_child.f_double", 0.0, "") RepeatDataBodyInfoCmd.Flags().BoolVar(&RepeatDataBodyInfoInput.Info.FChild.FBool, "info.f_child.f_bool", false, "") RepeatDataBodyInfoCmd.Flags().StringVar(&RepeatDataBodyInfoInputInfoFChildFContinent, "info.f_child.f_continent", "", "") RepeatDataBodyInfoCmd.Flags().StringVar(&RepeatDataBodyInfoInput.Info.FChild.FChild.FString, "info.f_child.f_child.f_string", "", "") RepeatDataBodyInfoCmd.Flags().Float64Var(&RepeatDataBodyInfoInput.Info.FChild.FChild.FDouble, "info.f_child.f_child.f_double", 0.0, "") RepeatDataBodyInfoCmd.Flags().BoolVar(&RepeatDataBodyInfoInput.Info.FChild.FChild.FBool, "info.f_child.f_child.f_bool", false, "") RepeatDataBodyInfoCmd.Flags().StringVar(&repeatDataBodyInfoInputInfoFChildPString, "info.f_child.p_string", "", "") RepeatDataBodyInfoCmd.Flags().Float32Var(&repeatDataBodyInfoInputInfoFChildPFloat, "info.f_child.p_float", 0.0, "") RepeatDataBodyInfoCmd.Flags().Float64Var(&repeatDataBodyInfoInputInfoFChildPDouble, "info.f_child.p_double", 0.0, "") RepeatDataBodyInfoCmd.Flags().BoolVar(&repeatDataBodyInfoInputInfoFChildPBool, "info.f_child.p_bool", false, "") RepeatDataBodyInfoCmd.Flags().StringVar(&RepeatDataBodyInfoInputInfoFChildPContinent, "info.f_child.p_continent", "", "") RepeatDataBodyInfoCmd.Flags().StringVar(&RepeatDataBodyInfoInput.Info.FChild.PChild.FString, "info.f_child.p_child.f_string", "", "") RepeatDataBodyInfoCmd.Flags().Float64Var(&RepeatDataBodyInfoInput.Info.FChild.PChild.FDouble, "info.f_child.p_child.f_double", 0.0, "") RepeatDataBodyInfoCmd.Flags().BoolVar(&RepeatDataBodyInfoInput.Info.FChild.PChild.FBool, "info.f_child.p_child.f_bool", false, "") RepeatDataBodyInfoCmd.Flags().StringVar(&repeatDataBodyInfoInputInfoPString, "info.p_string", "", "") RepeatDataBodyInfoCmd.Flags().Int32Var(&repeatDataBodyInfoInputInfoPInt32, "info.p_int32", 0, "") RepeatDataBodyInfoCmd.Flags().Int32Var(&repeatDataBodyInfoInputInfoPSint32, "info.p_sint32", 0, "") RepeatDataBodyInfoCmd.Flags().Int32Var(&repeatDataBodyInfoInputInfoPSfixed32, "info.p_sfixed32", 0, "") RepeatDataBodyInfoCmd.Flags().Uint32Var(&repeatDataBodyInfoInputInfoPUint32, "info.p_uint32", 0, "") RepeatDataBodyInfoCmd.Flags().Uint32Var(&repeatDataBodyInfoInputInfoPFixed32, "info.p_fixed32", 0, "") RepeatDataBodyInfoCmd.Flags().Int64Var(&repeatDataBodyInfoInputInfoPInt64, "info.p_int64", 0, "") RepeatDataBodyInfoCmd.Flags().Int64Var(&repeatDataBodyInfoInputInfoPSint64, "info.p_sint64", 0, "") RepeatDataBodyInfoCmd.Flags().Int64Var(&repeatDataBodyInfoInputInfoPSfixed64, "info.p_sfixed64", 0, "") RepeatDataBodyInfoCmd.Flags().Uint64Var(&repeatDataBodyInfoInputInfoPUint64, "info.p_uint64", 0, "") RepeatDataBodyInfoCmd.Flags().Uint64Var(&repeatDataBodyInfoInputInfoPFixed64, "info.p_fixed64", 0, "") RepeatDataBodyInfoCmd.Flags().Float32Var(&repeatDataBodyInfoInputInfoPFloat, "info.p_float", 0.0, "") RepeatDataBodyInfoCmd.Flags().Float64Var(&repeatDataBodyInfoInputInfoPDouble, "info.p_double", 0.0, "") RepeatDataBodyInfoCmd.Flags().BoolVar(&repeatDataBodyInfoInputInfoPBool, "info.p_bool", false, "") RepeatDataBodyInfoCmd.Flags().StringVar(&RepeatDataBodyInfoInputInfoPKingdom, "info.p_kingdom", "", "") RepeatDataBodyInfoCmd.Flags().StringVar(&RepeatDataBodyInfoInput.Info.PChild.FString, "info.p_child.f_string", "", "") RepeatDataBodyInfoCmd.Flags().Float32Var(&RepeatDataBodyInfoInput.Info.PChild.FFloat, "info.p_child.f_float", 0.0, "") RepeatDataBodyInfoCmd.Flags().Float64Var(&RepeatDataBodyInfoInput.Info.PChild.FDouble, "info.p_child.f_double", 0.0, "") RepeatDataBodyInfoCmd.Flags().BoolVar(&RepeatDataBodyInfoInput.Info.PChild.FBool, "info.p_child.f_bool", false, "") RepeatDataBodyInfoCmd.Flags().StringVar(&RepeatDataBodyInfoInputInfoPChildFContinent, "info.p_child.f_continent", "", "") RepeatDataBodyInfoCmd.Flags().StringVar(&RepeatDataBodyInfoInput.Info.PChild.FChild.FString, "info.p_child.f_child.f_string", "", "") RepeatDataBodyInfoCmd.Flags().Float64Var(&RepeatDataBodyInfoInput.Info.PChild.FChild.FDouble, "info.p_child.f_child.f_double", 0.0, "") RepeatDataBodyInfoCmd.Flags().BoolVar(&RepeatDataBodyInfoInput.Info.PChild.FChild.FBool, "info.p_child.f_child.f_bool", false, "") RepeatDataBodyInfoCmd.Flags().StringVar(&repeatDataBodyInfoInputInfoPChildPString, "info.p_child.p_string", "", "") RepeatDataBodyInfoCmd.Flags().Float32Var(&repeatDataBodyInfoInputInfoPChildPFloat, "info.p_child.p_float", 0.0, "") RepeatDataBodyInfoCmd.Flags().Float64Var(&repeatDataBodyInfoInputInfoPChildPDouble, "info.p_child.p_double", 0.0, "") RepeatDataBodyInfoCmd.Flags().BoolVar(&repeatDataBodyInfoInputInfoPChildPBool, "info.p_child.p_bool", false, "") RepeatDataBodyInfoCmd.Flags().StringVar(&RepeatDataBodyInfoInputInfoPChildPContinent, "info.p_child.p_continent", "", "") RepeatDataBodyInfoCmd.Flags().StringVar(&RepeatDataBodyInfoInput.Info.PChild.PChild.FString, "info.p_child.p_child.f_string", "", "") RepeatDataBodyInfoCmd.Flags().Float64Var(&RepeatDataBodyInfoInput.Info.PChild.PChild.FDouble, "info.p_child.p_child.f_double", 0.0, "") RepeatDataBodyInfoCmd.Flags().BoolVar(&RepeatDataBodyInfoInput.Info.PChild.PChild.FBool, "info.p_child.p_child.f_bool", false, "") RepeatDataBodyInfoCmd.Flags().BoolVar(&RepeatDataBodyInfoInput.ServerVerify, "server_verify", false, "If true, the server will verify that the received...") RepeatDataBodyInfoCmd.Flags().StringVar(&repeatDataBodyInfoInputIntendedBindingUri, "intended_binding_uri", "", "The URI template this request is expected to be...") RepeatDataBodyInfoCmd.Flags().Int32Var(&RepeatDataBodyInfoInput.FInt32, "f_int32", 0, "Some top level fields, to test that these are...") RepeatDataBodyInfoCmd.Flags().Int64Var(&RepeatDataBodyInfoInput.FInt64, "f_int64", 0, "") RepeatDataBodyInfoCmd.Flags().Float64Var(&RepeatDataBodyInfoInput.FDouble, "f_double", 0.0, "") RepeatDataBodyInfoCmd.Flags().Int32Var(&repeatDataBodyInfoInputPInt32, "p_int32", 0, "") RepeatDataBodyInfoCmd.Flags().Int64Var(&repeatDataBodyInfoInputPInt64, "p_int64", 0, "") RepeatDataBodyInfoCmd.Flags().Float64Var(&repeatDataBodyInfoInputPDouble, "p_double", 0.0, "") RepeatDataBodyInfoCmd.Flags().StringVar(&RepeatDataBodyInfoFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var RepeatDataBodyInfoCmd = &cobra.Command{ Use: "repeat-data-body-info", Short: "This method echoes the ComplianceData request....", Long: "This method echoes the ComplianceData request. This method exercises sending the a message-type field in the REST body. Per AIP-127, only ...", PreRun: func(cmd *cobra.Command, args []string) { if RepeatDataBodyInfoFromFile == "" { } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if RepeatDataBodyInfoFromFile != "" { in, err = os.Open(RepeatDataBodyInfoFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &RepeatDataBodyInfoInput) if err != nil { return err } } else { RepeatDataBodyInfoInput.Info.FKingdom = genprotopb.ComplianceData_LifeKingdom(genprotopb.ComplianceData_LifeKingdom_value[strings.ToUpper(RepeatDataBodyInfoInputInfoFKingdom)]) RepeatDataBodyInfoInput.Info.FChild.FContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataBodyInfoInputInfoFChildFContinent)]) RepeatDataBodyInfoInput.Info.FChild.PContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataBodyInfoInputInfoFChildPContinent)]) if cmd.Flags().Changed("info.p_kingdom") { e := genprotopb.ComplianceData_LifeKingdom(genprotopb.ComplianceData_LifeKingdom_value[strings.ToUpper(RepeatDataBodyInfoInputInfoPKingdom)]) RepeatDataBodyInfoInput.Info.PKingdom = &e } RepeatDataBodyInfoInput.Info.PChild.FContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataBodyInfoInputInfoPChildFContinent)]) RepeatDataBodyInfoInput.Info.PChild.PContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataBodyInfoInputInfoPChildPContinent)]) if cmd.Flags().Changed("info.f_child.p_string") { RepeatDataBodyInfoInput.Info.FChild.PString = &repeatDataBodyInfoInputInfoFChildPString } if cmd.Flags().Changed("info.f_child.p_float") { RepeatDataBodyInfoInput.Info.FChild.PFloat = &repeatDataBodyInfoInputInfoFChildPFloat } if cmd.Flags().Changed("info.f_child.p_double") { RepeatDataBodyInfoInput.Info.FChild.PDouble = &repeatDataBodyInfoInputInfoFChildPDouble } if cmd.Flags().Changed("info.f_child.p_bool") { RepeatDataBodyInfoInput.Info.FChild.PBool = &repeatDataBodyInfoInputInfoFChildPBool } if cmd.Flags().Changed("info.p_string") { RepeatDataBodyInfoInput.Info.PString = &repeatDataBodyInfoInputInfoPString } if cmd.Flags().Changed("info.p_int32") { RepeatDataBodyInfoInput.Info.PInt32 = &repeatDataBodyInfoInputInfoPInt32 } if cmd.Flags().Changed("info.p_sint32") { RepeatDataBodyInfoInput.Info.PSint32 = &repeatDataBodyInfoInputInfoPSint32 } if cmd.Flags().Changed("info.p_sfixed32") { RepeatDataBodyInfoInput.Info.PSfixed32 = &repeatDataBodyInfoInputInfoPSfixed32 } if cmd.Flags().Changed("info.p_uint32") { RepeatDataBodyInfoInput.Info.PUint32 = &repeatDataBodyInfoInputInfoPUint32 } if cmd.Flags().Changed("info.p_fixed32") { RepeatDataBodyInfoInput.Info.PFixed32 = &repeatDataBodyInfoInputInfoPFixed32 } if cmd.Flags().Changed("info.p_int64") { RepeatDataBodyInfoInput.Info.PInt64 = &repeatDataBodyInfoInputInfoPInt64 } if cmd.Flags().Changed("info.p_sint64") { RepeatDataBodyInfoInput.Info.PSint64 = &repeatDataBodyInfoInputInfoPSint64 } if cmd.Flags().Changed("info.p_sfixed64") { RepeatDataBodyInfoInput.Info.PSfixed64 = &repeatDataBodyInfoInputInfoPSfixed64 } if cmd.Flags().Changed("info.p_uint64") { RepeatDataBodyInfoInput.Info.PUint64 = &repeatDataBodyInfoInputInfoPUint64 } if cmd.Flags().Changed("info.p_fixed64") { RepeatDataBodyInfoInput.Info.PFixed64 = &repeatDataBodyInfoInputInfoPFixed64 } if cmd.Flags().Changed("info.p_float") { RepeatDataBodyInfoInput.Info.PFloat = &repeatDataBodyInfoInputInfoPFloat } if cmd.Flags().Changed("info.p_double") { RepeatDataBodyInfoInput.Info.PDouble = &repeatDataBodyInfoInputInfoPDouble } if cmd.Flags().Changed("info.p_bool") { RepeatDataBodyInfoInput.Info.PBool = &repeatDataBodyInfoInputInfoPBool } if cmd.Flags().Changed("info.p_child.p_string") { RepeatDataBodyInfoInput.Info.PChild.PString = &repeatDataBodyInfoInputInfoPChildPString } if cmd.Flags().Changed("info.p_child.p_float") { RepeatDataBodyInfoInput.Info.PChild.PFloat = &repeatDataBodyInfoInputInfoPChildPFloat } if cmd.Flags().Changed("info.p_child.p_double") { RepeatDataBodyInfoInput.Info.PChild.PDouble = &repeatDataBodyInfoInputInfoPChildPDouble } if cmd.Flags().Changed("info.p_child.p_bool") { RepeatDataBodyInfoInput.Info.PChild.PBool = &repeatDataBodyInfoInputInfoPChildPBool } if cmd.Flags().Changed("intended_binding_uri") { RepeatDataBodyInfoInput.IntendedBindingUri = &repeatDataBodyInfoInputIntendedBindingUri } if cmd.Flags().Changed("p_int32") { RepeatDataBodyInfoInput.PInt32 = &repeatDataBodyInfoInputPInt32 } if cmd.Flags().Changed("p_int64") { RepeatDataBodyInfoInput.PInt64 = &repeatDataBodyInfoInputPInt64 } if cmd.Flags().Changed("p_double") { RepeatDataBodyInfoInput.PDouble = &repeatDataBodyInfoInputPDouble } } if Verbose { printVerboseInput("Compliance", "RepeatDataBodyInfo", &RepeatDataBodyInfoInput) } resp, err := ComplianceClient.RepeatDataBodyInfo(ctx, &RepeatDataBodyInfoInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/repeat-data-body-patch.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" "strings" ) var RepeatDataBodyPatchInput genprotopb.RepeatRequest var RepeatDataBodyPatchFromFile string var RepeatDataBodyPatchInputInfoFKingdom string var RepeatDataBodyPatchInputInfoFChildFContinent string var repeatDataBodyPatchInputInfoFChildPString string var repeatDataBodyPatchInputInfoFChildPFloat float32 var repeatDataBodyPatchInputInfoFChildPDouble float64 var repeatDataBodyPatchInputInfoFChildPBool bool var RepeatDataBodyPatchInputInfoFChildPContinent string var repeatDataBodyPatchInputInfoPString string var repeatDataBodyPatchInputInfoPInt32 int32 var repeatDataBodyPatchInputInfoPSint32 int32 var repeatDataBodyPatchInputInfoPSfixed32 int32 var repeatDataBodyPatchInputInfoPUint32 uint32 var repeatDataBodyPatchInputInfoPFixed32 uint32 var repeatDataBodyPatchInputInfoPInt64 int64 var repeatDataBodyPatchInputInfoPSint64 int64 var repeatDataBodyPatchInputInfoPSfixed64 int64 var repeatDataBodyPatchInputInfoPUint64 uint64 var repeatDataBodyPatchInputInfoPFixed64 uint64 var repeatDataBodyPatchInputInfoPFloat float32 var repeatDataBodyPatchInputInfoPDouble float64 var repeatDataBodyPatchInputInfoPBool bool var RepeatDataBodyPatchInputInfoPKingdom string var RepeatDataBodyPatchInputInfoPChildFContinent string var repeatDataBodyPatchInputInfoPChildPString string var repeatDataBodyPatchInputInfoPChildPFloat float32 var repeatDataBodyPatchInputInfoPChildPDouble float64 var repeatDataBodyPatchInputInfoPChildPBool bool var RepeatDataBodyPatchInputInfoPChildPContinent string var repeatDataBodyPatchInputIntendedBindingUri string var repeatDataBodyPatchInputPInt32 int32 var repeatDataBodyPatchInputPInt64 int64 var repeatDataBodyPatchInputPDouble float64 func init() { ComplianceServiceCmd.AddCommand(RepeatDataBodyPatchCmd) RepeatDataBodyPatchInput.Info = new(genprotopb.ComplianceData) RepeatDataBodyPatchInput.Info.FChild = new(genprotopb.ComplianceDataChild) RepeatDataBodyPatchInput.Info.FChild.FChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataBodyPatchInput.Info.FChild.PChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataBodyPatchInput.Info.PChild = new(genprotopb.ComplianceDataChild) RepeatDataBodyPatchInput.Info.PChild.FChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataBodyPatchInput.Info.PChild.PChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataBodyPatchCmd.Flags().StringVar(&RepeatDataBodyPatchInput.Name, "name", "", "") RepeatDataBodyPatchCmd.Flags().StringVar(&RepeatDataBodyPatchInput.Info.FString, "info.f_string", "", "") RepeatDataBodyPatchCmd.Flags().Int32Var(&RepeatDataBodyPatchInput.Info.FInt32, "info.f_int32", 0, "") RepeatDataBodyPatchCmd.Flags().Int32Var(&RepeatDataBodyPatchInput.Info.FSint32, "info.f_sint32", 0, "") RepeatDataBodyPatchCmd.Flags().Int32Var(&RepeatDataBodyPatchInput.Info.FSfixed32, "info.f_sfixed32", 0, "") RepeatDataBodyPatchCmd.Flags().Uint32Var(&RepeatDataBodyPatchInput.Info.FUint32, "info.f_uint32", 0, "") RepeatDataBodyPatchCmd.Flags().Uint32Var(&RepeatDataBodyPatchInput.Info.FFixed32, "info.f_fixed32", 0, "") RepeatDataBodyPatchCmd.Flags().Int64Var(&RepeatDataBodyPatchInput.Info.FInt64, "info.f_int64", 0, "") RepeatDataBodyPatchCmd.Flags().Int64Var(&RepeatDataBodyPatchInput.Info.FSint64, "info.f_sint64", 0, "") RepeatDataBodyPatchCmd.Flags().Int64Var(&RepeatDataBodyPatchInput.Info.FSfixed64, "info.f_sfixed64", 0, "") RepeatDataBodyPatchCmd.Flags().Uint64Var(&RepeatDataBodyPatchInput.Info.FUint64, "info.f_uint64", 0, "") RepeatDataBodyPatchCmd.Flags().Uint64Var(&RepeatDataBodyPatchInput.Info.FFixed64, "info.f_fixed64", 0, "") RepeatDataBodyPatchCmd.Flags().Float64Var(&RepeatDataBodyPatchInput.Info.FDouble, "info.f_double", 0.0, "") RepeatDataBodyPatchCmd.Flags().Float32Var(&RepeatDataBodyPatchInput.Info.FFloat, "info.f_float", 0.0, "") RepeatDataBodyPatchCmd.Flags().BoolVar(&RepeatDataBodyPatchInput.Info.FBool, "info.f_bool", false, "") RepeatDataBodyPatchCmd.Flags().BytesHexVar(&RepeatDataBodyPatchInput.Info.FBytes, "info.f_bytes", []byte{}, "") RepeatDataBodyPatchCmd.Flags().StringVar(&RepeatDataBodyPatchInputInfoFKingdom, "info.f_kingdom", "", "") RepeatDataBodyPatchCmd.Flags().StringVar(&RepeatDataBodyPatchInput.Info.FChild.FString, "info.f_child.f_string", "", "") RepeatDataBodyPatchCmd.Flags().Float32Var(&RepeatDataBodyPatchInput.Info.FChild.FFloat, "info.f_child.f_float", 0.0, "") RepeatDataBodyPatchCmd.Flags().Float64Var(&RepeatDataBodyPatchInput.Info.FChild.FDouble, "info.f_child.f_double", 0.0, "") RepeatDataBodyPatchCmd.Flags().BoolVar(&RepeatDataBodyPatchInput.Info.FChild.FBool, "info.f_child.f_bool", false, "") RepeatDataBodyPatchCmd.Flags().StringVar(&RepeatDataBodyPatchInputInfoFChildFContinent, "info.f_child.f_continent", "", "") RepeatDataBodyPatchCmd.Flags().StringVar(&RepeatDataBodyPatchInput.Info.FChild.FChild.FString, "info.f_child.f_child.f_string", "", "") RepeatDataBodyPatchCmd.Flags().Float64Var(&RepeatDataBodyPatchInput.Info.FChild.FChild.FDouble, "info.f_child.f_child.f_double", 0.0, "") RepeatDataBodyPatchCmd.Flags().BoolVar(&RepeatDataBodyPatchInput.Info.FChild.FChild.FBool, "info.f_child.f_child.f_bool", false, "") RepeatDataBodyPatchCmd.Flags().StringVar(&repeatDataBodyPatchInputInfoFChildPString, "info.f_child.p_string", "", "") RepeatDataBodyPatchCmd.Flags().Float32Var(&repeatDataBodyPatchInputInfoFChildPFloat, "info.f_child.p_float", 0.0, "") RepeatDataBodyPatchCmd.Flags().Float64Var(&repeatDataBodyPatchInputInfoFChildPDouble, "info.f_child.p_double", 0.0, "") RepeatDataBodyPatchCmd.Flags().BoolVar(&repeatDataBodyPatchInputInfoFChildPBool, "info.f_child.p_bool", false, "") RepeatDataBodyPatchCmd.Flags().StringVar(&RepeatDataBodyPatchInputInfoFChildPContinent, "info.f_child.p_continent", "", "") RepeatDataBodyPatchCmd.Flags().StringVar(&RepeatDataBodyPatchInput.Info.FChild.PChild.FString, "info.f_child.p_child.f_string", "", "") RepeatDataBodyPatchCmd.Flags().Float64Var(&RepeatDataBodyPatchInput.Info.FChild.PChild.FDouble, "info.f_child.p_child.f_double", 0.0, "") RepeatDataBodyPatchCmd.Flags().BoolVar(&RepeatDataBodyPatchInput.Info.FChild.PChild.FBool, "info.f_child.p_child.f_bool", false, "") RepeatDataBodyPatchCmd.Flags().StringVar(&repeatDataBodyPatchInputInfoPString, "info.p_string", "", "") RepeatDataBodyPatchCmd.Flags().Int32Var(&repeatDataBodyPatchInputInfoPInt32, "info.p_int32", 0, "") RepeatDataBodyPatchCmd.Flags().Int32Var(&repeatDataBodyPatchInputInfoPSint32, "info.p_sint32", 0, "") RepeatDataBodyPatchCmd.Flags().Int32Var(&repeatDataBodyPatchInputInfoPSfixed32, "info.p_sfixed32", 0, "") RepeatDataBodyPatchCmd.Flags().Uint32Var(&repeatDataBodyPatchInputInfoPUint32, "info.p_uint32", 0, "") RepeatDataBodyPatchCmd.Flags().Uint32Var(&repeatDataBodyPatchInputInfoPFixed32, "info.p_fixed32", 0, "") RepeatDataBodyPatchCmd.Flags().Int64Var(&repeatDataBodyPatchInputInfoPInt64, "info.p_int64", 0, "") RepeatDataBodyPatchCmd.Flags().Int64Var(&repeatDataBodyPatchInputInfoPSint64, "info.p_sint64", 0, "") RepeatDataBodyPatchCmd.Flags().Int64Var(&repeatDataBodyPatchInputInfoPSfixed64, "info.p_sfixed64", 0, "") RepeatDataBodyPatchCmd.Flags().Uint64Var(&repeatDataBodyPatchInputInfoPUint64, "info.p_uint64", 0, "") RepeatDataBodyPatchCmd.Flags().Uint64Var(&repeatDataBodyPatchInputInfoPFixed64, "info.p_fixed64", 0, "") RepeatDataBodyPatchCmd.Flags().Float32Var(&repeatDataBodyPatchInputInfoPFloat, "info.p_float", 0.0, "") RepeatDataBodyPatchCmd.Flags().Float64Var(&repeatDataBodyPatchInputInfoPDouble, "info.p_double", 0.0, "") RepeatDataBodyPatchCmd.Flags().BoolVar(&repeatDataBodyPatchInputInfoPBool, "info.p_bool", false, "") RepeatDataBodyPatchCmd.Flags().StringVar(&RepeatDataBodyPatchInputInfoPKingdom, "info.p_kingdom", "", "") RepeatDataBodyPatchCmd.Flags().StringVar(&RepeatDataBodyPatchInput.Info.PChild.FString, "info.p_child.f_string", "", "") RepeatDataBodyPatchCmd.Flags().Float32Var(&RepeatDataBodyPatchInput.Info.PChild.FFloat, "info.p_child.f_float", 0.0, "") RepeatDataBodyPatchCmd.Flags().Float64Var(&RepeatDataBodyPatchInput.Info.PChild.FDouble, "info.p_child.f_double", 0.0, "") RepeatDataBodyPatchCmd.Flags().BoolVar(&RepeatDataBodyPatchInput.Info.PChild.FBool, "info.p_child.f_bool", false, "") RepeatDataBodyPatchCmd.Flags().StringVar(&RepeatDataBodyPatchInputInfoPChildFContinent, "info.p_child.f_continent", "", "") RepeatDataBodyPatchCmd.Flags().StringVar(&RepeatDataBodyPatchInput.Info.PChild.FChild.FString, "info.p_child.f_child.f_string", "", "") RepeatDataBodyPatchCmd.Flags().Float64Var(&RepeatDataBodyPatchInput.Info.PChild.FChild.FDouble, "info.p_child.f_child.f_double", 0.0, "") RepeatDataBodyPatchCmd.Flags().BoolVar(&RepeatDataBodyPatchInput.Info.PChild.FChild.FBool, "info.p_child.f_child.f_bool", false, "") RepeatDataBodyPatchCmd.Flags().StringVar(&repeatDataBodyPatchInputInfoPChildPString, "info.p_child.p_string", "", "") RepeatDataBodyPatchCmd.Flags().Float32Var(&repeatDataBodyPatchInputInfoPChildPFloat, "info.p_child.p_float", 0.0, "") RepeatDataBodyPatchCmd.Flags().Float64Var(&repeatDataBodyPatchInputInfoPChildPDouble, "info.p_child.p_double", 0.0, "") RepeatDataBodyPatchCmd.Flags().BoolVar(&repeatDataBodyPatchInputInfoPChildPBool, "info.p_child.p_bool", false, "") RepeatDataBodyPatchCmd.Flags().StringVar(&RepeatDataBodyPatchInputInfoPChildPContinent, "info.p_child.p_continent", "", "") RepeatDataBodyPatchCmd.Flags().StringVar(&RepeatDataBodyPatchInput.Info.PChild.PChild.FString, "info.p_child.p_child.f_string", "", "") RepeatDataBodyPatchCmd.Flags().Float64Var(&RepeatDataBodyPatchInput.Info.PChild.PChild.FDouble, "info.p_child.p_child.f_double", 0.0, "") RepeatDataBodyPatchCmd.Flags().BoolVar(&RepeatDataBodyPatchInput.Info.PChild.PChild.FBool, "info.p_child.p_child.f_bool", false, "") RepeatDataBodyPatchCmd.Flags().BoolVar(&RepeatDataBodyPatchInput.ServerVerify, "server_verify", false, "If true, the server will verify that the received...") RepeatDataBodyPatchCmd.Flags().StringVar(&repeatDataBodyPatchInputIntendedBindingUri, "intended_binding_uri", "", "The URI template this request is expected to be...") RepeatDataBodyPatchCmd.Flags().Int32Var(&RepeatDataBodyPatchInput.FInt32, "f_int32", 0, "Some top level fields, to test that these are...") RepeatDataBodyPatchCmd.Flags().Int64Var(&RepeatDataBodyPatchInput.FInt64, "f_int64", 0, "") RepeatDataBodyPatchCmd.Flags().Float64Var(&RepeatDataBodyPatchInput.FDouble, "f_double", 0.0, "") RepeatDataBodyPatchCmd.Flags().Int32Var(&repeatDataBodyPatchInputPInt32, "p_int32", 0, "") RepeatDataBodyPatchCmd.Flags().Int64Var(&repeatDataBodyPatchInputPInt64, "p_int64", 0, "") RepeatDataBodyPatchCmd.Flags().Float64Var(&repeatDataBodyPatchInputPDouble, "p_double", 0.0, "") RepeatDataBodyPatchCmd.Flags().StringVar(&RepeatDataBodyPatchFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var RepeatDataBodyPatchCmd = &cobra.Command{ Use: "repeat-data-body-patch", Short: "This method echoes the ComplianceData request,...", Long: "This method echoes the ComplianceData request, using the HTTP PATCH method.", PreRun: func(cmd *cobra.Command, args []string) { if RepeatDataBodyPatchFromFile == "" { } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if RepeatDataBodyPatchFromFile != "" { in, err = os.Open(RepeatDataBodyPatchFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &RepeatDataBodyPatchInput) if err != nil { return err } } else { RepeatDataBodyPatchInput.Info.FKingdom = genprotopb.ComplianceData_LifeKingdom(genprotopb.ComplianceData_LifeKingdom_value[strings.ToUpper(RepeatDataBodyPatchInputInfoFKingdom)]) RepeatDataBodyPatchInput.Info.FChild.FContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataBodyPatchInputInfoFChildFContinent)]) RepeatDataBodyPatchInput.Info.FChild.PContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataBodyPatchInputInfoFChildPContinent)]) if cmd.Flags().Changed("info.p_kingdom") { e := genprotopb.ComplianceData_LifeKingdom(genprotopb.ComplianceData_LifeKingdom_value[strings.ToUpper(RepeatDataBodyPatchInputInfoPKingdom)]) RepeatDataBodyPatchInput.Info.PKingdom = &e } RepeatDataBodyPatchInput.Info.PChild.FContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataBodyPatchInputInfoPChildFContinent)]) RepeatDataBodyPatchInput.Info.PChild.PContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataBodyPatchInputInfoPChildPContinent)]) if cmd.Flags().Changed("info.f_child.p_string") { RepeatDataBodyPatchInput.Info.FChild.PString = &repeatDataBodyPatchInputInfoFChildPString } if cmd.Flags().Changed("info.f_child.p_float") { RepeatDataBodyPatchInput.Info.FChild.PFloat = &repeatDataBodyPatchInputInfoFChildPFloat } if cmd.Flags().Changed("info.f_child.p_double") { RepeatDataBodyPatchInput.Info.FChild.PDouble = &repeatDataBodyPatchInputInfoFChildPDouble } if cmd.Flags().Changed("info.f_child.p_bool") { RepeatDataBodyPatchInput.Info.FChild.PBool = &repeatDataBodyPatchInputInfoFChildPBool } if cmd.Flags().Changed("info.p_string") { RepeatDataBodyPatchInput.Info.PString = &repeatDataBodyPatchInputInfoPString } if cmd.Flags().Changed("info.p_int32") { RepeatDataBodyPatchInput.Info.PInt32 = &repeatDataBodyPatchInputInfoPInt32 } if cmd.Flags().Changed("info.p_sint32") { RepeatDataBodyPatchInput.Info.PSint32 = &repeatDataBodyPatchInputInfoPSint32 } if cmd.Flags().Changed("info.p_sfixed32") { RepeatDataBodyPatchInput.Info.PSfixed32 = &repeatDataBodyPatchInputInfoPSfixed32 } if cmd.Flags().Changed("info.p_uint32") { RepeatDataBodyPatchInput.Info.PUint32 = &repeatDataBodyPatchInputInfoPUint32 } if cmd.Flags().Changed("info.p_fixed32") { RepeatDataBodyPatchInput.Info.PFixed32 = &repeatDataBodyPatchInputInfoPFixed32 } if cmd.Flags().Changed("info.p_int64") { RepeatDataBodyPatchInput.Info.PInt64 = &repeatDataBodyPatchInputInfoPInt64 } if cmd.Flags().Changed("info.p_sint64") { RepeatDataBodyPatchInput.Info.PSint64 = &repeatDataBodyPatchInputInfoPSint64 } if cmd.Flags().Changed("info.p_sfixed64") { RepeatDataBodyPatchInput.Info.PSfixed64 = &repeatDataBodyPatchInputInfoPSfixed64 } if cmd.Flags().Changed("info.p_uint64") { RepeatDataBodyPatchInput.Info.PUint64 = &repeatDataBodyPatchInputInfoPUint64 } if cmd.Flags().Changed("info.p_fixed64") { RepeatDataBodyPatchInput.Info.PFixed64 = &repeatDataBodyPatchInputInfoPFixed64 } if cmd.Flags().Changed("info.p_float") { RepeatDataBodyPatchInput.Info.PFloat = &repeatDataBodyPatchInputInfoPFloat } if cmd.Flags().Changed("info.p_double") { RepeatDataBodyPatchInput.Info.PDouble = &repeatDataBodyPatchInputInfoPDouble } if cmd.Flags().Changed("info.p_bool") { RepeatDataBodyPatchInput.Info.PBool = &repeatDataBodyPatchInputInfoPBool } if cmd.Flags().Changed("info.p_child.p_string") { RepeatDataBodyPatchInput.Info.PChild.PString = &repeatDataBodyPatchInputInfoPChildPString } if cmd.Flags().Changed("info.p_child.p_float") { RepeatDataBodyPatchInput.Info.PChild.PFloat = &repeatDataBodyPatchInputInfoPChildPFloat } if cmd.Flags().Changed("info.p_child.p_double") { RepeatDataBodyPatchInput.Info.PChild.PDouble = &repeatDataBodyPatchInputInfoPChildPDouble } if cmd.Flags().Changed("info.p_child.p_bool") { RepeatDataBodyPatchInput.Info.PChild.PBool = &repeatDataBodyPatchInputInfoPChildPBool } if cmd.Flags().Changed("intended_binding_uri") { RepeatDataBodyPatchInput.IntendedBindingUri = &repeatDataBodyPatchInputIntendedBindingUri } if cmd.Flags().Changed("p_int32") { RepeatDataBodyPatchInput.PInt32 = &repeatDataBodyPatchInputPInt32 } if cmd.Flags().Changed("p_int64") { RepeatDataBodyPatchInput.PInt64 = &repeatDataBodyPatchInputPInt64 } if cmd.Flags().Changed("p_double") { RepeatDataBodyPatchInput.PDouble = &repeatDataBodyPatchInputPDouble } } if Verbose { printVerboseInput("Compliance", "RepeatDataBodyPatch", &RepeatDataBodyPatchInput) } resp, err := ComplianceClient.RepeatDataBodyPatch(ctx, &RepeatDataBodyPatchInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/repeat-data-body-put.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" "strings" ) var RepeatDataBodyPutInput genprotopb.RepeatRequest var RepeatDataBodyPutFromFile string var RepeatDataBodyPutInputInfoFKingdom string var RepeatDataBodyPutInputInfoFChildFContinent string var repeatDataBodyPutInputInfoFChildPString string var repeatDataBodyPutInputInfoFChildPFloat float32 var repeatDataBodyPutInputInfoFChildPDouble float64 var repeatDataBodyPutInputInfoFChildPBool bool var RepeatDataBodyPutInputInfoFChildPContinent string var repeatDataBodyPutInputInfoPString string var repeatDataBodyPutInputInfoPInt32 int32 var repeatDataBodyPutInputInfoPSint32 int32 var repeatDataBodyPutInputInfoPSfixed32 int32 var repeatDataBodyPutInputInfoPUint32 uint32 var repeatDataBodyPutInputInfoPFixed32 uint32 var repeatDataBodyPutInputInfoPInt64 int64 var repeatDataBodyPutInputInfoPSint64 int64 var repeatDataBodyPutInputInfoPSfixed64 int64 var repeatDataBodyPutInputInfoPUint64 uint64 var repeatDataBodyPutInputInfoPFixed64 uint64 var repeatDataBodyPutInputInfoPFloat float32 var repeatDataBodyPutInputInfoPDouble float64 var repeatDataBodyPutInputInfoPBool bool var RepeatDataBodyPutInputInfoPKingdom string var RepeatDataBodyPutInputInfoPChildFContinent string var repeatDataBodyPutInputInfoPChildPString string var repeatDataBodyPutInputInfoPChildPFloat float32 var repeatDataBodyPutInputInfoPChildPDouble float64 var repeatDataBodyPutInputInfoPChildPBool bool var RepeatDataBodyPutInputInfoPChildPContinent string var repeatDataBodyPutInputIntendedBindingUri string var repeatDataBodyPutInputPInt32 int32 var repeatDataBodyPutInputPInt64 int64 var repeatDataBodyPutInputPDouble float64 func init() { ComplianceServiceCmd.AddCommand(RepeatDataBodyPutCmd) RepeatDataBodyPutInput.Info = new(genprotopb.ComplianceData) RepeatDataBodyPutInput.Info.FChild = new(genprotopb.ComplianceDataChild) RepeatDataBodyPutInput.Info.FChild.FChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataBodyPutInput.Info.FChild.PChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataBodyPutInput.Info.PChild = new(genprotopb.ComplianceDataChild) RepeatDataBodyPutInput.Info.PChild.FChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataBodyPutInput.Info.PChild.PChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataBodyPutCmd.Flags().StringVar(&RepeatDataBodyPutInput.Name, "name", "", "") RepeatDataBodyPutCmd.Flags().StringVar(&RepeatDataBodyPutInput.Info.FString, "info.f_string", "", "") RepeatDataBodyPutCmd.Flags().Int32Var(&RepeatDataBodyPutInput.Info.FInt32, "info.f_int32", 0, "") RepeatDataBodyPutCmd.Flags().Int32Var(&RepeatDataBodyPutInput.Info.FSint32, "info.f_sint32", 0, "") RepeatDataBodyPutCmd.Flags().Int32Var(&RepeatDataBodyPutInput.Info.FSfixed32, "info.f_sfixed32", 0, "") RepeatDataBodyPutCmd.Flags().Uint32Var(&RepeatDataBodyPutInput.Info.FUint32, "info.f_uint32", 0, "") RepeatDataBodyPutCmd.Flags().Uint32Var(&RepeatDataBodyPutInput.Info.FFixed32, "info.f_fixed32", 0, "") RepeatDataBodyPutCmd.Flags().Int64Var(&RepeatDataBodyPutInput.Info.FInt64, "info.f_int64", 0, "") RepeatDataBodyPutCmd.Flags().Int64Var(&RepeatDataBodyPutInput.Info.FSint64, "info.f_sint64", 0, "") RepeatDataBodyPutCmd.Flags().Int64Var(&RepeatDataBodyPutInput.Info.FSfixed64, "info.f_sfixed64", 0, "") RepeatDataBodyPutCmd.Flags().Uint64Var(&RepeatDataBodyPutInput.Info.FUint64, "info.f_uint64", 0, "") RepeatDataBodyPutCmd.Flags().Uint64Var(&RepeatDataBodyPutInput.Info.FFixed64, "info.f_fixed64", 0, "") RepeatDataBodyPutCmd.Flags().Float64Var(&RepeatDataBodyPutInput.Info.FDouble, "info.f_double", 0.0, "") RepeatDataBodyPutCmd.Flags().Float32Var(&RepeatDataBodyPutInput.Info.FFloat, "info.f_float", 0.0, "") RepeatDataBodyPutCmd.Flags().BoolVar(&RepeatDataBodyPutInput.Info.FBool, "info.f_bool", false, "") RepeatDataBodyPutCmd.Flags().BytesHexVar(&RepeatDataBodyPutInput.Info.FBytes, "info.f_bytes", []byte{}, "") RepeatDataBodyPutCmd.Flags().StringVar(&RepeatDataBodyPutInputInfoFKingdom, "info.f_kingdom", "", "") RepeatDataBodyPutCmd.Flags().StringVar(&RepeatDataBodyPutInput.Info.FChild.FString, "info.f_child.f_string", "", "") RepeatDataBodyPutCmd.Flags().Float32Var(&RepeatDataBodyPutInput.Info.FChild.FFloat, "info.f_child.f_float", 0.0, "") RepeatDataBodyPutCmd.Flags().Float64Var(&RepeatDataBodyPutInput.Info.FChild.FDouble, "info.f_child.f_double", 0.0, "") RepeatDataBodyPutCmd.Flags().BoolVar(&RepeatDataBodyPutInput.Info.FChild.FBool, "info.f_child.f_bool", false, "") RepeatDataBodyPutCmd.Flags().StringVar(&RepeatDataBodyPutInputInfoFChildFContinent, "info.f_child.f_continent", "", "") RepeatDataBodyPutCmd.Flags().StringVar(&RepeatDataBodyPutInput.Info.FChild.FChild.FString, "info.f_child.f_child.f_string", "", "") RepeatDataBodyPutCmd.Flags().Float64Var(&RepeatDataBodyPutInput.Info.FChild.FChild.FDouble, "info.f_child.f_child.f_double", 0.0, "") RepeatDataBodyPutCmd.Flags().BoolVar(&RepeatDataBodyPutInput.Info.FChild.FChild.FBool, "info.f_child.f_child.f_bool", false, "") RepeatDataBodyPutCmd.Flags().StringVar(&repeatDataBodyPutInputInfoFChildPString, "info.f_child.p_string", "", "") RepeatDataBodyPutCmd.Flags().Float32Var(&repeatDataBodyPutInputInfoFChildPFloat, "info.f_child.p_float", 0.0, "") RepeatDataBodyPutCmd.Flags().Float64Var(&repeatDataBodyPutInputInfoFChildPDouble, "info.f_child.p_double", 0.0, "") RepeatDataBodyPutCmd.Flags().BoolVar(&repeatDataBodyPutInputInfoFChildPBool, "info.f_child.p_bool", false, "") RepeatDataBodyPutCmd.Flags().StringVar(&RepeatDataBodyPutInputInfoFChildPContinent, "info.f_child.p_continent", "", "") RepeatDataBodyPutCmd.Flags().StringVar(&RepeatDataBodyPutInput.Info.FChild.PChild.FString, "info.f_child.p_child.f_string", "", "") RepeatDataBodyPutCmd.Flags().Float64Var(&RepeatDataBodyPutInput.Info.FChild.PChild.FDouble, "info.f_child.p_child.f_double", 0.0, "") RepeatDataBodyPutCmd.Flags().BoolVar(&RepeatDataBodyPutInput.Info.FChild.PChild.FBool, "info.f_child.p_child.f_bool", false, "") RepeatDataBodyPutCmd.Flags().StringVar(&repeatDataBodyPutInputInfoPString, "info.p_string", "", "") RepeatDataBodyPutCmd.Flags().Int32Var(&repeatDataBodyPutInputInfoPInt32, "info.p_int32", 0, "") RepeatDataBodyPutCmd.Flags().Int32Var(&repeatDataBodyPutInputInfoPSint32, "info.p_sint32", 0, "") RepeatDataBodyPutCmd.Flags().Int32Var(&repeatDataBodyPutInputInfoPSfixed32, "info.p_sfixed32", 0, "") RepeatDataBodyPutCmd.Flags().Uint32Var(&repeatDataBodyPutInputInfoPUint32, "info.p_uint32", 0, "") RepeatDataBodyPutCmd.Flags().Uint32Var(&repeatDataBodyPutInputInfoPFixed32, "info.p_fixed32", 0, "") RepeatDataBodyPutCmd.Flags().Int64Var(&repeatDataBodyPutInputInfoPInt64, "info.p_int64", 0, "") RepeatDataBodyPutCmd.Flags().Int64Var(&repeatDataBodyPutInputInfoPSint64, "info.p_sint64", 0, "") RepeatDataBodyPutCmd.Flags().Int64Var(&repeatDataBodyPutInputInfoPSfixed64, "info.p_sfixed64", 0, "") RepeatDataBodyPutCmd.Flags().Uint64Var(&repeatDataBodyPutInputInfoPUint64, "info.p_uint64", 0, "") RepeatDataBodyPutCmd.Flags().Uint64Var(&repeatDataBodyPutInputInfoPFixed64, "info.p_fixed64", 0, "") RepeatDataBodyPutCmd.Flags().Float32Var(&repeatDataBodyPutInputInfoPFloat, "info.p_float", 0.0, "") RepeatDataBodyPutCmd.Flags().Float64Var(&repeatDataBodyPutInputInfoPDouble, "info.p_double", 0.0, "") RepeatDataBodyPutCmd.Flags().BoolVar(&repeatDataBodyPutInputInfoPBool, "info.p_bool", false, "") RepeatDataBodyPutCmd.Flags().StringVar(&RepeatDataBodyPutInputInfoPKingdom, "info.p_kingdom", "", "") RepeatDataBodyPutCmd.Flags().StringVar(&RepeatDataBodyPutInput.Info.PChild.FString, "info.p_child.f_string", "", "") RepeatDataBodyPutCmd.Flags().Float32Var(&RepeatDataBodyPutInput.Info.PChild.FFloat, "info.p_child.f_float", 0.0, "") RepeatDataBodyPutCmd.Flags().Float64Var(&RepeatDataBodyPutInput.Info.PChild.FDouble, "info.p_child.f_double", 0.0, "") RepeatDataBodyPutCmd.Flags().BoolVar(&RepeatDataBodyPutInput.Info.PChild.FBool, "info.p_child.f_bool", false, "") RepeatDataBodyPutCmd.Flags().StringVar(&RepeatDataBodyPutInputInfoPChildFContinent, "info.p_child.f_continent", "", "") RepeatDataBodyPutCmd.Flags().StringVar(&RepeatDataBodyPutInput.Info.PChild.FChild.FString, "info.p_child.f_child.f_string", "", "") RepeatDataBodyPutCmd.Flags().Float64Var(&RepeatDataBodyPutInput.Info.PChild.FChild.FDouble, "info.p_child.f_child.f_double", 0.0, "") RepeatDataBodyPutCmd.Flags().BoolVar(&RepeatDataBodyPutInput.Info.PChild.FChild.FBool, "info.p_child.f_child.f_bool", false, "") RepeatDataBodyPutCmd.Flags().StringVar(&repeatDataBodyPutInputInfoPChildPString, "info.p_child.p_string", "", "") RepeatDataBodyPutCmd.Flags().Float32Var(&repeatDataBodyPutInputInfoPChildPFloat, "info.p_child.p_float", 0.0, "") RepeatDataBodyPutCmd.Flags().Float64Var(&repeatDataBodyPutInputInfoPChildPDouble, "info.p_child.p_double", 0.0, "") RepeatDataBodyPutCmd.Flags().BoolVar(&repeatDataBodyPutInputInfoPChildPBool, "info.p_child.p_bool", false, "") RepeatDataBodyPutCmd.Flags().StringVar(&RepeatDataBodyPutInputInfoPChildPContinent, "info.p_child.p_continent", "", "") RepeatDataBodyPutCmd.Flags().StringVar(&RepeatDataBodyPutInput.Info.PChild.PChild.FString, "info.p_child.p_child.f_string", "", "") RepeatDataBodyPutCmd.Flags().Float64Var(&RepeatDataBodyPutInput.Info.PChild.PChild.FDouble, "info.p_child.p_child.f_double", 0.0, "") RepeatDataBodyPutCmd.Flags().BoolVar(&RepeatDataBodyPutInput.Info.PChild.PChild.FBool, "info.p_child.p_child.f_bool", false, "") RepeatDataBodyPutCmd.Flags().BoolVar(&RepeatDataBodyPutInput.ServerVerify, "server_verify", false, "If true, the server will verify that the received...") RepeatDataBodyPutCmd.Flags().StringVar(&repeatDataBodyPutInputIntendedBindingUri, "intended_binding_uri", "", "The URI template this request is expected to be...") RepeatDataBodyPutCmd.Flags().Int32Var(&RepeatDataBodyPutInput.FInt32, "f_int32", 0, "Some top level fields, to test that these are...") RepeatDataBodyPutCmd.Flags().Int64Var(&RepeatDataBodyPutInput.FInt64, "f_int64", 0, "") RepeatDataBodyPutCmd.Flags().Float64Var(&RepeatDataBodyPutInput.FDouble, "f_double", 0.0, "") RepeatDataBodyPutCmd.Flags().Int32Var(&repeatDataBodyPutInputPInt32, "p_int32", 0, "") RepeatDataBodyPutCmd.Flags().Int64Var(&repeatDataBodyPutInputPInt64, "p_int64", 0, "") RepeatDataBodyPutCmd.Flags().Float64Var(&repeatDataBodyPutInputPDouble, "p_double", 0.0, "") RepeatDataBodyPutCmd.Flags().StringVar(&RepeatDataBodyPutFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var RepeatDataBodyPutCmd = &cobra.Command{ Use: "repeat-data-body-put", Short: "This method echoes the ComplianceData request,...", Long: "This method echoes the ComplianceData request, using the HTTP PUT method.", PreRun: func(cmd *cobra.Command, args []string) { if RepeatDataBodyPutFromFile == "" { } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if RepeatDataBodyPutFromFile != "" { in, err = os.Open(RepeatDataBodyPutFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &RepeatDataBodyPutInput) if err != nil { return err } } else { RepeatDataBodyPutInput.Info.FKingdom = genprotopb.ComplianceData_LifeKingdom(genprotopb.ComplianceData_LifeKingdom_value[strings.ToUpper(RepeatDataBodyPutInputInfoFKingdom)]) RepeatDataBodyPutInput.Info.FChild.FContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataBodyPutInputInfoFChildFContinent)]) RepeatDataBodyPutInput.Info.FChild.PContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataBodyPutInputInfoFChildPContinent)]) if cmd.Flags().Changed("info.p_kingdom") { e := genprotopb.ComplianceData_LifeKingdom(genprotopb.ComplianceData_LifeKingdom_value[strings.ToUpper(RepeatDataBodyPutInputInfoPKingdom)]) RepeatDataBodyPutInput.Info.PKingdom = &e } RepeatDataBodyPutInput.Info.PChild.FContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataBodyPutInputInfoPChildFContinent)]) RepeatDataBodyPutInput.Info.PChild.PContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataBodyPutInputInfoPChildPContinent)]) if cmd.Flags().Changed("info.f_child.p_string") { RepeatDataBodyPutInput.Info.FChild.PString = &repeatDataBodyPutInputInfoFChildPString } if cmd.Flags().Changed("info.f_child.p_float") { RepeatDataBodyPutInput.Info.FChild.PFloat = &repeatDataBodyPutInputInfoFChildPFloat } if cmd.Flags().Changed("info.f_child.p_double") { RepeatDataBodyPutInput.Info.FChild.PDouble = &repeatDataBodyPutInputInfoFChildPDouble } if cmd.Flags().Changed("info.f_child.p_bool") { RepeatDataBodyPutInput.Info.FChild.PBool = &repeatDataBodyPutInputInfoFChildPBool } if cmd.Flags().Changed("info.p_string") { RepeatDataBodyPutInput.Info.PString = &repeatDataBodyPutInputInfoPString } if cmd.Flags().Changed("info.p_int32") { RepeatDataBodyPutInput.Info.PInt32 = &repeatDataBodyPutInputInfoPInt32 } if cmd.Flags().Changed("info.p_sint32") { RepeatDataBodyPutInput.Info.PSint32 = &repeatDataBodyPutInputInfoPSint32 } if cmd.Flags().Changed("info.p_sfixed32") { RepeatDataBodyPutInput.Info.PSfixed32 = &repeatDataBodyPutInputInfoPSfixed32 } if cmd.Flags().Changed("info.p_uint32") { RepeatDataBodyPutInput.Info.PUint32 = &repeatDataBodyPutInputInfoPUint32 } if cmd.Flags().Changed("info.p_fixed32") { RepeatDataBodyPutInput.Info.PFixed32 = &repeatDataBodyPutInputInfoPFixed32 } if cmd.Flags().Changed("info.p_int64") { RepeatDataBodyPutInput.Info.PInt64 = &repeatDataBodyPutInputInfoPInt64 } if cmd.Flags().Changed("info.p_sint64") { RepeatDataBodyPutInput.Info.PSint64 = &repeatDataBodyPutInputInfoPSint64 } if cmd.Flags().Changed("info.p_sfixed64") { RepeatDataBodyPutInput.Info.PSfixed64 = &repeatDataBodyPutInputInfoPSfixed64 } if cmd.Flags().Changed("info.p_uint64") { RepeatDataBodyPutInput.Info.PUint64 = &repeatDataBodyPutInputInfoPUint64 } if cmd.Flags().Changed("info.p_fixed64") { RepeatDataBodyPutInput.Info.PFixed64 = &repeatDataBodyPutInputInfoPFixed64 } if cmd.Flags().Changed("info.p_float") { RepeatDataBodyPutInput.Info.PFloat = &repeatDataBodyPutInputInfoPFloat } if cmd.Flags().Changed("info.p_double") { RepeatDataBodyPutInput.Info.PDouble = &repeatDataBodyPutInputInfoPDouble } if cmd.Flags().Changed("info.p_bool") { RepeatDataBodyPutInput.Info.PBool = &repeatDataBodyPutInputInfoPBool } if cmd.Flags().Changed("info.p_child.p_string") { RepeatDataBodyPutInput.Info.PChild.PString = &repeatDataBodyPutInputInfoPChildPString } if cmd.Flags().Changed("info.p_child.p_float") { RepeatDataBodyPutInput.Info.PChild.PFloat = &repeatDataBodyPutInputInfoPChildPFloat } if cmd.Flags().Changed("info.p_child.p_double") { RepeatDataBodyPutInput.Info.PChild.PDouble = &repeatDataBodyPutInputInfoPChildPDouble } if cmd.Flags().Changed("info.p_child.p_bool") { RepeatDataBodyPutInput.Info.PChild.PBool = &repeatDataBodyPutInputInfoPChildPBool } if cmd.Flags().Changed("intended_binding_uri") { RepeatDataBodyPutInput.IntendedBindingUri = &repeatDataBodyPutInputIntendedBindingUri } if cmd.Flags().Changed("p_int32") { RepeatDataBodyPutInput.PInt32 = &repeatDataBodyPutInputPInt32 } if cmd.Flags().Changed("p_int64") { RepeatDataBodyPutInput.PInt64 = &repeatDataBodyPutInputPInt64 } if cmd.Flags().Changed("p_double") { RepeatDataBodyPutInput.PDouble = &repeatDataBodyPutInputPDouble } } if Verbose { printVerboseInput("Compliance", "RepeatDataBodyPut", &RepeatDataBodyPutInput) } resp, err := ComplianceClient.RepeatDataBodyPut(ctx, &RepeatDataBodyPutInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/repeat-data-body.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" "strings" ) var RepeatDataBodyInput genprotopb.RepeatRequest var RepeatDataBodyFromFile string var RepeatDataBodyInputInfoFKingdom string var RepeatDataBodyInputInfoFChildFContinent string var repeatDataBodyInputInfoFChildPString string var repeatDataBodyInputInfoFChildPFloat float32 var repeatDataBodyInputInfoFChildPDouble float64 var repeatDataBodyInputInfoFChildPBool bool var RepeatDataBodyInputInfoFChildPContinent string var repeatDataBodyInputInfoPString string var repeatDataBodyInputInfoPInt32 int32 var repeatDataBodyInputInfoPSint32 int32 var repeatDataBodyInputInfoPSfixed32 int32 var repeatDataBodyInputInfoPUint32 uint32 var repeatDataBodyInputInfoPFixed32 uint32 var repeatDataBodyInputInfoPInt64 int64 var repeatDataBodyInputInfoPSint64 int64 var repeatDataBodyInputInfoPSfixed64 int64 var repeatDataBodyInputInfoPUint64 uint64 var repeatDataBodyInputInfoPFixed64 uint64 var repeatDataBodyInputInfoPFloat float32 var repeatDataBodyInputInfoPDouble float64 var repeatDataBodyInputInfoPBool bool var RepeatDataBodyInputInfoPKingdom string var RepeatDataBodyInputInfoPChildFContinent string var repeatDataBodyInputInfoPChildPString string var repeatDataBodyInputInfoPChildPFloat float32 var repeatDataBodyInputInfoPChildPDouble float64 var repeatDataBodyInputInfoPChildPBool bool var RepeatDataBodyInputInfoPChildPContinent string var repeatDataBodyInputIntendedBindingUri string var repeatDataBodyInputPInt32 int32 var repeatDataBodyInputPInt64 int64 var repeatDataBodyInputPDouble float64 func init() { ComplianceServiceCmd.AddCommand(RepeatDataBodyCmd) RepeatDataBodyInput.Info = new(genprotopb.ComplianceData) RepeatDataBodyInput.Info.FChild = new(genprotopb.ComplianceDataChild) RepeatDataBodyInput.Info.FChild.FChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataBodyInput.Info.FChild.PChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataBodyInput.Info.PChild = new(genprotopb.ComplianceDataChild) RepeatDataBodyInput.Info.PChild.FChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataBodyInput.Info.PChild.PChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataBodyCmd.Flags().StringVar(&RepeatDataBodyInput.Name, "name", "", "") RepeatDataBodyCmd.Flags().StringVar(&RepeatDataBodyInput.Info.FString, "info.f_string", "", "") RepeatDataBodyCmd.Flags().Int32Var(&RepeatDataBodyInput.Info.FInt32, "info.f_int32", 0, "") RepeatDataBodyCmd.Flags().Int32Var(&RepeatDataBodyInput.Info.FSint32, "info.f_sint32", 0, "") RepeatDataBodyCmd.Flags().Int32Var(&RepeatDataBodyInput.Info.FSfixed32, "info.f_sfixed32", 0, "") RepeatDataBodyCmd.Flags().Uint32Var(&RepeatDataBodyInput.Info.FUint32, "info.f_uint32", 0, "") RepeatDataBodyCmd.Flags().Uint32Var(&RepeatDataBodyInput.Info.FFixed32, "info.f_fixed32", 0, "") RepeatDataBodyCmd.Flags().Int64Var(&RepeatDataBodyInput.Info.FInt64, "info.f_int64", 0, "") RepeatDataBodyCmd.Flags().Int64Var(&RepeatDataBodyInput.Info.FSint64, "info.f_sint64", 0, "") RepeatDataBodyCmd.Flags().Int64Var(&RepeatDataBodyInput.Info.FSfixed64, "info.f_sfixed64", 0, "") RepeatDataBodyCmd.Flags().Uint64Var(&RepeatDataBodyInput.Info.FUint64, "info.f_uint64", 0, "") RepeatDataBodyCmd.Flags().Uint64Var(&RepeatDataBodyInput.Info.FFixed64, "info.f_fixed64", 0, "") RepeatDataBodyCmd.Flags().Float64Var(&RepeatDataBodyInput.Info.FDouble, "info.f_double", 0.0, "") RepeatDataBodyCmd.Flags().Float32Var(&RepeatDataBodyInput.Info.FFloat, "info.f_float", 0.0, "") RepeatDataBodyCmd.Flags().BoolVar(&RepeatDataBodyInput.Info.FBool, "info.f_bool", false, "") RepeatDataBodyCmd.Flags().BytesHexVar(&RepeatDataBodyInput.Info.FBytes, "info.f_bytes", []byte{}, "") RepeatDataBodyCmd.Flags().StringVar(&RepeatDataBodyInputInfoFKingdom, "info.f_kingdom", "", "") RepeatDataBodyCmd.Flags().StringVar(&RepeatDataBodyInput.Info.FChild.FString, "info.f_child.f_string", "", "") RepeatDataBodyCmd.Flags().Float32Var(&RepeatDataBodyInput.Info.FChild.FFloat, "info.f_child.f_float", 0.0, "") RepeatDataBodyCmd.Flags().Float64Var(&RepeatDataBodyInput.Info.FChild.FDouble, "info.f_child.f_double", 0.0, "") RepeatDataBodyCmd.Flags().BoolVar(&RepeatDataBodyInput.Info.FChild.FBool, "info.f_child.f_bool", false, "") RepeatDataBodyCmd.Flags().StringVar(&RepeatDataBodyInputInfoFChildFContinent, "info.f_child.f_continent", "", "") RepeatDataBodyCmd.Flags().StringVar(&RepeatDataBodyInput.Info.FChild.FChild.FString, "info.f_child.f_child.f_string", "", "") RepeatDataBodyCmd.Flags().Float64Var(&RepeatDataBodyInput.Info.FChild.FChild.FDouble, "info.f_child.f_child.f_double", 0.0, "") RepeatDataBodyCmd.Flags().BoolVar(&RepeatDataBodyInput.Info.FChild.FChild.FBool, "info.f_child.f_child.f_bool", false, "") RepeatDataBodyCmd.Flags().StringVar(&repeatDataBodyInputInfoFChildPString, "info.f_child.p_string", "", "") RepeatDataBodyCmd.Flags().Float32Var(&repeatDataBodyInputInfoFChildPFloat, "info.f_child.p_float", 0.0, "") RepeatDataBodyCmd.Flags().Float64Var(&repeatDataBodyInputInfoFChildPDouble, "info.f_child.p_double", 0.0, "") RepeatDataBodyCmd.Flags().BoolVar(&repeatDataBodyInputInfoFChildPBool, "info.f_child.p_bool", false, "") RepeatDataBodyCmd.Flags().StringVar(&RepeatDataBodyInputInfoFChildPContinent, "info.f_child.p_continent", "", "") RepeatDataBodyCmd.Flags().StringVar(&RepeatDataBodyInput.Info.FChild.PChild.FString, "info.f_child.p_child.f_string", "", "") RepeatDataBodyCmd.Flags().Float64Var(&RepeatDataBodyInput.Info.FChild.PChild.FDouble, "info.f_child.p_child.f_double", 0.0, "") RepeatDataBodyCmd.Flags().BoolVar(&RepeatDataBodyInput.Info.FChild.PChild.FBool, "info.f_child.p_child.f_bool", false, "") RepeatDataBodyCmd.Flags().StringVar(&repeatDataBodyInputInfoPString, "info.p_string", "", "") RepeatDataBodyCmd.Flags().Int32Var(&repeatDataBodyInputInfoPInt32, "info.p_int32", 0, "") RepeatDataBodyCmd.Flags().Int32Var(&repeatDataBodyInputInfoPSint32, "info.p_sint32", 0, "") RepeatDataBodyCmd.Flags().Int32Var(&repeatDataBodyInputInfoPSfixed32, "info.p_sfixed32", 0, "") RepeatDataBodyCmd.Flags().Uint32Var(&repeatDataBodyInputInfoPUint32, "info.p_uint32", 0, "") RepeatDataBodyCmd.Flags().Uint32Var(&repeatDataBodyInputInfoPFixed32, "info.p_fixed32", 0, "") RepeatDataBodyCmd.Flags().Int64Var(&repeatDataBodyInputInfoPInt64, "info.p_int64", 0, "") RepeatDataBodyCmd.Flags().Int64Var(&repeatDataBodyInputInfoPSint64, "info.p_sint64", 0, "") RepeatDataBodyCmd.Flags().Int64Var(&repeatDataBodyInputInfoPSfixed64, "info.p_sfixed64", 0, "") RepeatDataBodyCmd.Flags().Uint64Var(&repeatDataBodyInputInfoPUint64, "info.p_uint64", 0, "") RepeatDataBodyCmd.Flags().Uint64Var(&repeatDataBodyInputInfoPFixed64, "info.p_fixed64", 0, "") RepeatDataBodyCmd.Flags().Float32Var(&repeatDataBodyInputInfoPFloat, "info.p_float", 0.0, "") RepeatDataBodyCmd.Flags().Float64Var(&repeatDataBodyInputInfoPDouble, "info.p_double", 0.0, "") RepeatDataBodyCmd.Flags().BoolVar(&repeatDataBodyInputInfoPBool, "info.p_bool", false, "") RepeatDataBodyCmd.Flags().StringVar(&RepeatDataBodyInputInfoPKingdom, "info.p_kingdom", "", "") RepeatDataBodyCmd.Flags().StringVar(&RepeatDataBodyInput.Info.PChild.FString, "info.p_child.f_string", "", "") RepeatDataBodyCmd.Flags().Float32Var(&RepeatDataBodyInput.Info.PChild.FFloat, "info.p_child.f_float", 0.0, "") RepeatDataBodyCmd.Flags().Float64Var(&RepeatDataBodyInput.Info.PChild.FDouble, "info.p_child.f_double", 0.0, "") RepeatDataBodyCmd.Flags().BoolVar(&RepeatDataBodyInput.Info.PChild.FBool, "info.p_child.f_bool", false, "") RepeatDataBodyCmd.Flags().StringVar(&RepeatDataBodyInputInfoPChildFContinent, "info.p_child.f_continent", "", "") RepeatDataBodyCmd.Flags().StringVar(&RepeatDataBodyInput.Info.PChild.FChild.FString, "info.p_child.f_child.f_string", "", "") RepeatDataBodyCmd.Flags().Float64Var(&RepeatDataBodyInput.Info.PChild.FChild.FDouble, "info.p_child.f_child.f_double", 0.0, "") RepeatDataBodyCmd.Flags().BoolVar(&RepeatDataBodyInput.Info.PChild.FChild.FBool, "info.p_child.f_child.f_bool", false, "") RepeatDataBodyCmd.Flags().StringVar(&repeatDataBodyInputInfoPChildPString, "info.p_child.p_string", "", "") RepeatDataBodyCmd.Flags().Float32Var(&repeatDataBodyInputInfoPChildPFloat, "info.p_child.p_float", 0.0, "") RepeatDataBodyCmd.Flags().Float64Var(&repeatDataBodyInputInfoPChildPDouble, "info.p_child.p_double", 0.0, "") RepeatDataBodyCmd.Flags().BoolVar(&repeatDataBodyInputInfoPChildPBool, "info.p_child.p_bool", false, "") RepeatDataBodyCmd.Flags().StringVar(&RepeatDataBodyInputInfoPChildPContinent, "info.p_child.p_continent", "", "") RepeatDataBodyCmd.Flags().StringVar(&RepeatDataBodyInput.Info.PChild.PChild.FString, "info.p_child.p_child.f_string", "", "") RepeatDataBodyCmd.Flags().Float64Var(&RepeatDataBodyInput.Info.PChild.PChild.FDouble, "info.p_child.p_child.f_double", 0.0, "") RepeatDataBodyCmd.Flags().BoolVar(&RepeatDataBodyInput.Info.PChild.PChild.FBool, "info.p_child.p_child.f_bool", false, "") RepeatDataBodyCmd.Flags().BoolVar(&RepeatDataBodyInput.ServerVerify, "server_verify", false, "If true, the server will verify that the received...") RepeatDataBodyCmd.Flags().StringVar(&repeatDataBodyInputIntendedBindingUri, "intended_binding_uri", "", "The URI template this request is expected to be...") RepeatDataBodyCmd.Flags().Int32Var(&RepeatDataBodyInput.FInt32, "f_int32", 0, "Some top level fields, to test that these are...") RepeatDataBodyCmd.Flags().Int64Var(&RepeatDataBodyInput.FInt64, "f_int64", 0, "") RepeatDataBodyCmd.Flags().Float64Var(&RepeatDataBodyInput.FDouble, "f_double", 0.0, "") RepeatDataBodyCmd.Flags().Int32Var(&repeatDataBodyInputPInt32, "p_int32", 0, "") RepeatDataBodyCmd.Flags().Int64Var(&repeatDataBodyInputPInt64, "p_int64", 0, "") RepeatDataBodyCmd.Flags().Float64Var(&repeatDataBodyInputPDouble, "p_double", 0.0, "") RepeatDataBodyCmd.Flags().StringVar(&RepeatDataBodyFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var RepeatDataBodyCmd = &cobra.Command{ Use: "repeat-data-body", Short: "This method echoes the ComplianceData request....", Long: "This method echoes the ComplianceData request. This method exercises sending the entire request object in the REST body.", PreRun: func(cmd *cobra.Command, args []string) { if RepeatDataBodyFromFile == "" { } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if RepeatDataBodyFromFile != "" { in, err = os.Open(RepeatDataBodyFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &RepeatDataBodyInput) if err != nil { return err } } else { RepeatDataBodyInput.Info.FKingdom = genprotopb.ComplianceData_LifeKingdom(genprotopb.ComplianceData_LifeKingdom_value[strings.ToUpper(RepeatDataBodyInputInfoFKingdom)]) RepeatDataBodyInput.Info.FChild.FContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataBodyInputInfoFChildFContinent)]) RepeatDataBodyInput.Info.FChild.PContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataBodyInputInfoFChildPContinent)]) if cmd.Flags().Changed("info.p_kingdom") { e := genprotopb.ComplianceData_LifeKingdom(genprotopb.ComplianceData_LifeKingdom_value[strings.ToUpper(RepeatDataBodyInputInfoPKingdom)]) RepeatDataBodyInput.Info.PKingdom = &e } RepeatDataBodyInput.Info.PChild.FContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataBodyInputInfoPChildFContinent)]) RepeatDataBodyInput.Info.PChild.PContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataBodyInputInfoPChildPContinent)]) if cmd.Flags().Changed("info.f_child.p_string") { RepeatDataBodyInput.Info.FChild.PString = &repeatDataBodyInputInfoFChildPString } if cmd.Flags().Changed("info.f_child.p_float") { RepeatDataBodyInput.Info.FChild.PFloat = &repeatDataBodyInputInfoFChildPFloat } if cmd.Flags().Changed("info.f_child.p_double") { RepeatDataBodyInput.Info.FChild.PDouble = &repeatDataBodyInputInfoFChildPDouble } if cmd.Flags().Changed("info.f_child.p_bool") { RepeatDataBodyInput.Info.FChild.PBool = &repeatDataBodyInputInfoFChildPBool } if cmd.Flags().Changed("info.p_string") { RepeatDataBodyInput.Info.PString = &repeatDataBodyInputInfoPString } if cmd.Flags().Changed("info.p_int32") { RepeatDataBodyInput.Info.PInt32 = &repeatDataBodyInputInfoPInt32 } if cmd.Flags().Changed("info.p_sint32") { RepeatDataBodyInput.Info.PSint32 = &repeatDataBodyInputInfoPSint32 } if cmd.Flags().Changed("info.p_sfixed32") { RepeatDataBodyInput.Info.PSfixed32 = &repeatDataBodyInputInfoPSfixed32 } if cmd.Flags().Changed("info.p_uint32") { RepeatDataBodyInput.Info.PUint32 = &repeatDataBodyInputInfoPUint32 } if cmd.Flags().Changed("info.p_fixed32") { RepeatDataBodyInput.Info.PFixed32 = &repeatDataBodyInputInfoPFixed32 } if cmd.Flags().Changed("info.p_int64") { RepeatDataBodyInput.Info.PInt64 = &repeatDataBodyInputInfoPInt64 } if cmd.Flags().Changed("info.p_sint64") { RepeatDataBodyInput.Info.PSint64 = &repeatDataBodyInputInfoPSint64 } if cmd.Flags().Changed("info.p_sfixed64") { RepeatDataBodyInput.Info.PSfixed64 = &repeatDataBodyInputInfoPSfixed64 } if cmd.Flags().Changed("info.p_uint64") { RepeatDataBodyInput.Info.PUint64 = &repeatDataBodyInputInfoPUint64 } if cmd.Flags().Changed("info.p_fixed64") { RepeatDataBodyInput.Info.PFixed64 = &repeatDataBodyInputInfoPFixed64 } if cmd.Flags().Changed("info.p_float") { RepeatDataBodyInput.Info.PFloat = &repeatDataBodyInputInfoPFloat } if cmd.Flags().Changed("info.p_double") { RepeatDataBodyInput.Info.PDouble = &repeatDataBodyInputInfoPDouble } if cmd.Flags().Changed("info.p_bool") { RepeatDataBodyInput.Info.PBool = &repeatDataBodyInputInfoPBool } if cmd.Flags().Changed("info.p_child.p_string") { RepeatDataBodyInput.Info.PChild.PString = &repeatDataBodyInputInfoPChildPString } if cmd.Flags().Changed("info.p_child.p_float") { RepeatDataBodyInput.Info.PChild.PFloat = &repeatDataBodyInputInfoPChildPFloat } if cmd.Flags().Changed("info.p_child.p_double") { RepeatDataBodyInput.Info.PChild.PDouble = &repeatDataBodyInputInfoPChildPDouble } if cmd.Flags().Changed("info.p_child.p_bool") { RepeatDataBodyInput.Info.PChild.PBool = &repeatDataBodyInputInfoPChildPBool } if cmd.Flags().Changed("intended_binding_uri") { RepeatDataBodyInput.IntendedBindingUri = &repeatDataBodyInputIntendedBindingUri } if cmd.Flags().Changed("p_int32") { RepeatDataBodyInput.PInt32 = &repeatDataBodyInputPInt32 } if cmd.Flags().Changed("p_int64") { RepeatDataBodyInput.PInt64 = &repeatDataBodyInputPInt64 } if cmd.Flags().Changed("p_double") { RepeatDataBodyInput.PDouble = &repeatDataBodyInputPDouble } } if Verbose { printVerboseInput("Compliance", "RepeatDataBody", &RepeatDataBodyInput) } resp, err := ComplianceClient.RepeatDataBody(ctx, &RepeatDataBodyInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/repeat-data-path-resource.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" "strings" ) var RepeatDataPathResourceInput genprotopb.RepeatRequest var RepeatDataPathResourceFromFile string var RepeatDataPathResourceInputInfoFKingdom string var RepeatDataPathResourceInputInfoFChildFContinent string var repeatDataPathResourceInputInfoFChildPString string var repeatDataPathResourceInputInfoFChildPFloat float32 var repeatDataPathResourceInputInfoFChildPDouble float64 var repeatDataPathResourceInputInfoFChildPBool bool var RepeatDataPathResourceInputInfoFChildPContinent string var repeatDataPathResourceInputInfoPString string var repeatDataPathResourceInputInfoPInt32 int32 var repeatDataPathResourceInputInfoPSint32 int32 var repeatDataPathResourceInputInfoPSfixed32 int32 var repeatDataPathResourceInputInfoPUint32 uint32 var repeatDataPathResourceInputInfoPFixed32 uint32 var repeatDataPathResourceInputInfoPInt64 int64 var repeatDataPathResourceInputInfoPSint64 int64 var repeatDataPathResourceInputInfoPSfixed64 int64 var repeatDataPathResourceInputInfoPUint64 uint64 var repeatDataPathResourceInputInfoPFixed64 uint64 var repeatDataPathResourceInputInfoPFloat float32 var repeatDataPathResourceInputInfoPDouble float64 var repeatDataPathResourceInputInfoPBool bool var RepeatDataPathResourceInputInfoPKingdom string var RepeatDataPathResourceInputInfoPChildFContinent string var repeatDataPathResourceInputInfoPChildPString string var repeatDataPathResourceInputInfoPChildPFloat float32 var repeatDataPathResourceInputInfoPChildPDouble float64 var repeatDataPathResourceInputInfoPChildPBool bool var RepeatDataPathResourceInputInfoPChildPContinent string var repeatDataPathResourceInputIntendedBindingUri string var repeatDataPathResourceInputPInt32 int32 var repeatDataPathResourceInputPInt64 int64 var repeatDataPathResourceInputPDouble float64 func init() { ComplianceServiceCmd.AddCommand(RepeatDataPathResourceCmd) RepeatDataPathResourceInput.Info = new(genprotopb.ComplianceData) RepeatDataPathResourceInput.Info.FChild = new(genprotopb.ComplianceDataChild) RepeatDataPathResourceInput.Info.FChild.FChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataPathResourceInput.Info.FChild.PChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataPathResourceInput.Info.PChild = new(genprotopb.ComplianceDataChild) RepeatDataPathResourceInput.Info.PChild.FChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataPathResourceInput.Info.PChild.PChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataPathResourceCmd.Flags().StringVar(&RepeatDataPathResourceInput.Name, "name", "", "") RepeatDataPathResourceCmd.Flags().StringVar(&RepeatDataPathResourceInput.Info.FString, "info.f_string", "", "") RepeatDataPathResourceCmd.Flags().Int32Var(&RepeatDataPathResourceInput.Info.FInt32, "info.f_int32", 0, "") RepeatDataPathResourceCmd.Flags().Int32Var(&RepeatDataPathResourceInput.Info.FSint32, "info.f_sint32", 0, "") RepeatDataPathResourceCmd.Flags().Int32Var(&RepeatDataPathResourceInput.Info.FSfixed32, "info.f_sfixed32", 0, "") RepeatDataPathResourceCmd.Flags().Uint32Var(&RepeatDataPathResourceInput.Info.FUint32, "info.f_uint32", 0, "") RepeatDataPathResourceCmd.Flags().Uint32Var(&RepeatDataPathResourceInput.Info.FFixed32, "info.f_fixed32", 0, "") RepeatDataPathResourceCmd.Flags().Int64Var(&RepeatDataPathResourceInput.Info.FInt64, "info.f_int64", 0, "") RepeatDataPathResourceCmd.Flags().Int64Var(&RepeatDataPathResourceInput.Info.FSint64, "info.f_sint64", 0, "") RepeatDataPathResourceCmd.Flags().Int64Var(&RepeatDataPathResourceInput.Info.FSfixed64, "info.f_sfixed64", 0, "") RepeatDataPathResourceCmd.Flags().Uint64Var(&RepeatDataPathResourceInput.Info.FUint64, "info.f_uint64", 0, "") RepeatDataPathResourceCmd.Flags().Uint64Var(&RepeatDataPathResourceInput.Info.FFixed64, "info.f_fixed64", 0, "") RepeatDataPathResourceCmd.Flags().Float64Var(&RepeatDataPathResourceInput.Info.FDouble, "info.f_double", 0.0, "") RepeatDataPathResourceCmd.Flags().Float32Var(&RepeatDataPathResourceInput.Info.FFloat, "info.f_float", 0.0, "") RepeatDataPathResourceCmd.Flags().BoolVar(&RepeatDataPathResourceInput.Info.FBool, "info.f_bool", false, "") RepeatDataPathResourceCmd.Flags().BytesHexVar(&RepeatDataPathResourceInput.Info.FBytes, "info.f_bytes", []byte{}, "") RepeatDataPathResourceCmd.Flags().StringVar(&RepeatDataPathResourceInputInfoFKingdom, "info.f_kingdom", "", "") RepeatDataPathResourceCmd.Flags().StringVar(&RepeatDataPathResourceInput.Info.FChild.FString, "info.f_child.f_string", "", "") RepeatDataPathResourceCmd.Flags().Float32Var(&RepeatDataPathResourceInput.Info.FChild.FFloat, "info.f_child.f_float", 0.0, "") RepeatDataPathResourceCmd.Flags().Float64Var(&RepeatDataPathResourceInput.Info.FChild.FDouble, "info.f_child.f_double", 0.0, "") RepeatDataPathResourceCmd.Flags().BoolVar(&RepeatDataPathResourceInput.Info.FChild.FBool, "info.f_child.f_bool", false, "") RepeatDataPathResourceCmd.Flags().StringVar(&RepeatDataPathResourceInputInfoFChildFContinent, "info.f_child.f_continent", "", "") RepeatDataPathResourceCmd.Flags().StringVar(&RepeatDataPathResourceInput.Info.FChild.FChild.FString, "info.f_child.f_child.f_string", "", "") RepeatDataPathResourceCmd.Flags().Float64Var(&RepeatDataPathResourceInput.Info.FChild.FChild.FDouble, "info.f_child.f_child.f_double", 0.0, "") RepeatDataPathResourceCmd.Flags().BoolVar(&RepeatDataPathResourceInput.Info.FChild.FChild.FBool, "info.f_child.f_child.f_bool", false, "") RepeatDataPathResourceCmd.Flags().StringVar(&repeatDataPathResourceInputInfoFChildPString, "info.f_child.p_string", "", "") RepeatDataPathResourceCmd.Flags().Float32Var(&repeatDataPathResourceInputInfoFChildPFloat, "info.f_child.p_float", 0.0, "") RepeatDataPathResourceCmd.Flags().Float64Var(&repeatDataPathResourceInputInfoFChildPDouble, "info.f_child.p_double", 0.0, "") RepeatDataPathResourceCmd.Flags().BoolVar(&repeatDataPathResourceInputInfoFChildPBool, "info.f_child.p_bool", false, "") RepeatDataPathResourceCmd.Flags().StringVar(&RepeatDataPathResourceInputInfoFChildPContinent, "info.f_child.p_continent", "", "") RepeatDataPathResourceCmd.Flags().StringVar(&RepeatDataPathResourceInput.Info.FChild.PChild.FString, "info.f_child.p_child.f_string", "", "") RepeatDataPathResourceCmd.Flags().Float64Var(&RepeatDataPathResourceInput.Info.FChild.PChild.FDouble, "info.f_child.p_child.f_double", 0.0, "") RepeatDataPathResourceCmd.Flags().BoolVar(&RepeatDataPathResourceInput.Info.FChild.PChild.FBool, "info.f_child.p_child.f_bool", false, "") RepeatDataPathResourceCmd.Flags().StringVar(&repeatDataPathResourceInputInfoPString, "info.p_string", "", "") RepeatDataPathResourceCmd.Flags().Int32Var(&repeatDataPathResourceInputInfoPInt32, "info.p_int32", 0, "") RepeatDataPathResourceCmd.Flags().Int32Var(&repeatDataPathResourceInputInfoPSint32, "info.p_sint32", 0, "") RepeatDataPathResourceCmd.Flags().Int32Var(&repeatDataPathResourceInputInfoPSfixed32, "info.p_sfixed32", 0, "") RepeatDataPathResourceCmd.Flags().Uint32Var(&repeatDataPathResourceInputInfoPUint32, "info.p_uint32", 0, "") RepeatDataPathResourceCmd.Flags().Uint32Var(&repeatDataPathResourceInputInfoPFixed32, "info.p_fixed32", 0, "") RepeatDataPathResourceCmd.Flags().Int64Var(&repeatDataPathResourceInputInfoPInt64, "info.p_int64", 0, "") RepeatDataPathResourceCmd.Flags().Int64Var(&repeatDataPathResourceInputInfoPSint64, "info.p_sint64", 0, "") RepeatDataPathResourceCmd.Flags().Int64Var(&repeatDataPathResourceInputInfoPSfixed64, "info.p_sfixed64", 0, "") RepeatDataPathResourceCmd.Flags().Uint64Var(&repeatDataPathResourceInputInfoPUint64, "info.p_uint64", 0, "") RepeatDataPathResourceCmd.Flags().Uint64Var(&repeatDataPathResourceInputInfoPFixed64, "info.p_fixed64", 0, "") RepeatDataPathResourceCmd.Flags().Float32Var(&repeatDataPathResourceInputInfoPFloat, "info.p_float", 0.0, "") RepeatDataPathResourceCmd.Flags().Float64Var(&repeatDataPathResourceInputInfoPDouble, "info.p_double", 0.0, "") RepeatDataPathResourceCmd.Flags().BoolVar(&repeatDataPathResourceInputInfoPBool, "info.p_bool", false, "") RepeatDataPathResourceCmd.Flags().StringVar(&RepeatDataPathResourceInputInfoPKingdom, "info.p_kingdom", "", "") RepeatDataPathResourceCmd.Flags().StringVar(&RepeatDataPathResourceInput.Info.PChild.FString, "info.p_child.f_string", "", "") RepeatDataPathResourceCmd.Flags().Float32Var(&RepeatDataPathResourceInput.Info.PChild.FFloat, "info.p_child.f_float", 0.0, "") RepeatDataPathResourceCmd.Flags().Float64Var(&RepeatDataPathResourceInput.Info.PChild.FDouble, "info.p_child.f_double", 0.0, "") RepeatDataPathResourceCmd.Flags().BoolVar(&RepeatDataPathResourceInput.Info.PChild.FBool, "info.p_child.f_bool", false, "") RepeatDataPathResourceCmd.Flags().StringVar(&RepeatDataPathResourceInputInfoPChildFContinent, "info.p_child.f_continent", "", "") RepeatDataPathResourceCmd.Flags().StringVar(&RepeatDataPathResourceInput.Info.PChild.FChild.FString, "info.p_child.f_child.f_string", "", "") RepeatDataPathResourceCmd.Flags().Float64Var(&RepeatDataPathResourceInput.Info.PChild.FChild.FDouble, "info.p_child.f_child.f_double", 0.0, "") RepeatDataPathResourceCmd.Flags().BoolVar(&RepeatDataPathResourceInput.Info.PChild.FChild.FBool, "info.p_child.f_child.f_bool", false, "") RepeatDataPathResourceCmd.Flags().StringVar(&repeatDataPathResourceInputInfoPChildPString, "info.p_child.p_string", "", "") RepeatDataPathResourceCmd.Flags().Float32Var(&repeatDataPathResourceInputInfoPChildPFloat, "info.p_child.p_float", 0.0, "") RepeatDataPathResourceCmd.Flags().Float64Var(&repeatDataPathResourceInputInfoPChildPDouble, "info.p_child.p_double", 0.0, "") RepeatDataPathResourceCmd.Flags().BoolVar(&repeatDataPathResourceInputInfoPChildPBool, "info.p_child.p_bool", false, "") RepeatDataPathResourceCmd.Flags().StringVar(&RepeatDataPathResourceInputInfoPChildPContinent, "info.p_child.p_continent", "", "") RepeatDataPathResourceCmd.Flags().StringVar(&RepeatDataPathResourceInput.Info.PChild.PChild.FString, "info.p_child.p_child.f_string", "", "") RepeatDataPathResourceCmd.Flags().Float64Var(&RepeatDataPathResourceInput.Info.PChild.PChild.FDouble, "info.p_child.p_child.f_double", 0.0, "") RepeatDataPathResourceCmd.Flags().BoolVar(&RepeatDataPathResourceInput.Info.PChild.PChild.FBool, "info.p_child.p_child.f_bool", false, "") RepeatDataPathResourceCmd.Flags().BoolVar(&RepeatDataPathResourceInput.ServerVerify, "server_verify", false, "If true, the server will verify that the received...") RepeatDataPathResourceCmd.Flags().StringVar(&repeatDataPathResourceInputIntendedBindingUri, "intended_binding_uri", "", "The URI template this request is expected to be...") RepeatDataPathResourceCmd.Flags().Int32Var(&RepeatDataPathResourceInput.FInt32, "f_int32", 0, "Some top level fields, to test that these are...") RepeatDataPathResourceCmd.Flags().Int64Var(&RepeatDataPathResourceInput.FInt64, "f_int64", 0, "") RepeatDataPathResourceCmd.Flags().Float64Var(&RepeatDataPathResourceInput.FDouble, "f_double", 0.0, "") RepeatDataPathResourceCmd.Flags().Int32Var(&repeatDataPathResourceInputPInt32, "p_int32", 0, "") RepeatDataPathResourceCmd.Flags().Int64Var(&repeatDataPathResourceInputPInt64, "p_int64", 0, "") RepeatDataPathResourceCmd.Flags().Float64Var(&repeatDataPathResourceInputPDouble, "p_double", 0.0, "") RepeatDataPathResourceCmd.Flags().StringVar(&RepeatDataPathResourceFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var RepeatDataPathResourceCmd = &cobra.Command{ Use: "repeat-data-path-resource", Short: "Same as RepeatDataSimplePath, but with a path...", Long: "Same as RepeatDataSimplePath, but with a path resource.", PreRun: func(cmd *cobra.Command, args []string) { if RepeatDataPathResourceFromFile == "" { } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if RepeatDataPathResourceFromFile != "" { in, err = os.Open(RepeatDataPathResourceFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &RepeatDataPathResourceInput) if err != nil { return err } } else { RepeatDataPathResourceInput.Info.FKingdom = genprotopb.ComplianceData_LifeKingdom(genprotopb.ComplianceData_LifeKingdom_value[strings.ToUpper(RepeatDataPathResourceInputInfoFKingdom)]) RepeatDataPathResourceInput.Info.FChild.FContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataPathResourceInputInfoFChildFContinent)]) RepeatDataPathResourceInput.Info.FChild.PContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataPathResourceInputInfoFChildPContinent)]) if cmd.Flags().Changed("info.p_kingdom") { e := genprotopb.ComplianceData_LifeKingdom(genprotopb.ComplianceData_LifeKingdom_value[strings.ToUpper(RepeatDataPathResourceInputInfoPKingdom)]) RepeatDataPathResourceInput.Info.PKingdom = &e } RepeatDataPathResourceInput.Info.PChild.FContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataPathResourceInputInfoPChildFContinent)]) RepeatDataPathResourceInput.Info.PChild.PContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataPathResourceInputInfoPChildPContinent)]) if cmd.Flags().Changed("info.f_child.p_string") { RepeatDataPathResourceInput.Info.FChild.PString = &repeatDataPathResourceInputInfoFChildPString } if cmd.Flags().Changed("info.f_child.p_float") { RepeatDataPathResourceInput.Info.FChild.PFloat = &repeatDataPathResourceInputInfoFChildPFloat } if cmd.Flags().Changed("info.f_child.p_double") { RepeatDataPathResourceInput.Info.FChild.PDouble = &repeatDataPathResourceInputInfoFChildPDouble } if cmd.Flags().Changed("info.f_child.p_bool") { RepeatDataPathResourceInput.Info.FChild.PBool = &repeatDataPathResourceInputInfoFChildPBool } if cmd.Flags().Changed("info.p_string") { RepeatDataPathResourceInput.Info.PString = &repeatDataPathResourceInputInfoPString } if cmd.Flags().Changed("info.p_int32") { RepeatDataPathResourceInput.Info.PInt32 = &repeatDataPathResourceInputInfoPInt32 } if cmd.Flags().Changed("info.p_sint32") { RepeatDataPathResourceInput.Info.PSint32 = &repeatDataPathResourceInputInfoPSint32 } if cmd.Flags().Changed("info.p_sfixed32") { RepeatDataPathResourceInput.Info.PSfixed32 = &repeatDataPathResourceInputInfoPSfixed32 } if cmd.Flags().Changed("info.p_uint32") { RepeatDataPathResourceInput.Info.PUint32 = &repeatDataPathResourceInputInfoPUint32 } if cmd.Flags().Changed("info.p_fixed32") { RepeatDataPathResourceInput.Info.PFixed32 = &repeatDataPathResourceInputInfoPFixed32 } if cmd.Flags().Changed("info.p_int64") { RepeatDataPathResourceInput.Info.PInt64 = &repeatDataPathResourceInputInfoPInt64 } if cmd.Flags().Changed("info.p_sint64") { RepeatDataPathResourceInput.Info.PSint64 = &repeatDataPathResourceInputInfoPSint64 } if cmd.Flags().Changed("info.p_sfixed64") { RepeatDataPathResourceInput.Info.PSfixed64 = &repeatDataPathResourceInputInfoPSfixed64 } if cmd.Flags().Changed("info.p_uint64") { RepeatDataPathResourceInput.Info.PUint64 = &repeatDataPathResourceInputInfoPUint64 } if cmd.Flags().Changed("info.p_fixed64") { RepeatDataPathResourceInput.Info.PFixed64 = &repeatDataPathResourceInputInfoPFixed64 } if cmd.Flags().Changed("info.p_float") { RepeatDataPathResourceInput.Info.PFloat = &repeatDataPathResourceInputInfoPFloat } if cmd.Flags().Changed("info.p_double") { RepeatDataPathResourceInput.Info.PDouble = &repeatDataPathResourceInputInfoPDouble } if cmd.Flags().Changed("info.p_bool") { RepeatDataPathResourceInput.Info.PBool = &repeatDataPathResourceInputInfoPBool } if cmd.Flags().Changed("info.p_child.p_string") { RepeatDataPathResourceInput.Info.PChild.PString = &repeatDataPathResourceInputInfoPChildPString } if cmd.Flags().Changed("info.p_child.p_float") { RepeatDataPathResourceInput.Info.PChild.PFloat = &repeatDataPathResourceInputInfoPChildPFloat } if cmd.Flags().Changed("info.p_child.p_double") { RepeatDataPathResourceInput.Info.PChild.PDouble = &repeatDataPathResourceInputInfoPChildPDouble } if cmd.Flags().Changed("info.p_child.p_bool") { RepeatDataPathResourceInput.Info.PChild.PBool = &repeatDataPathResourceInputInfoPChildPBool } if cmd.Flags().Changed("intended_binding_uri") { RepeatDataPathResourceInput.IntendedBindingUri = &repeatDataPathResourceInputIntendedBindingUri } if cmd.Flags().Changed("p_int32") { RepeatDataPathResourceInput.PInt32 = &repeatDataPathResourceInputPInt32 } if cmd.Flags().Changed("p_int64") { RepeatDataPathResourceInput.PInt64 = &repeatDataPathResourceInputPInt64 } if cmd.Flags().Changed("p_double") { RepeatDataPathResourceInput.PDouble = &repeatDataPathResourceInputPDouble } } if Verbose { printVerboseInput("Compliance", "RepeatDataPathResource", &RepeatDataPathResourceInput) } resp, err := ComplianceClient.RepeatDataPathResource(ctx, &RepeatDataPathResourceInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/repeat-data-path-trailing-resource.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" "strings" ) var RepeatDataPathTrailingResourceInput genprotopb.RepeatRequest var RepeatDataPathTrailingResourceFromFile string var RepeatDataPathTrailingResourceInputInfoFKingdom string var RepeatDataPathTrailingResourceInputInfoFChildFContinent string var repeatDataPathTrailingResourceInputInfoFChildPString string var repeatDataPathTrailingResourceInputInfoFChildPFloat float32 var repeatDataPathTrailingResourceInputInfoFChildPDouble float64 var repeatDataPathTrailingResourceInputInfoFChildPBool bool var RepeatDataPathTrailingResourceInputInfoFChildPContinent string var repeatDataPathTrailingResourceInputInfoPString string var repeatDataPathTrailingResourceInputInfoPInt32 int32 var repeatDataPathTrailingResourceInputInfoPSint32 int32 var repeatDataPathTrailingResourceInputInfoPSfixed32 int32 var repeatDataPathTrailingResourceInputInfoPUint32 uint32 var repeatDataPathTrailingResourceInputInfoPFixed32 uint32 var repeatDataPathTrailingResourceInputInfoPInt64 int64 var repeatDataPathTrailingResourceInputInfoPSint64 int64 var repeatDataPathTrailingResourceInputInfoPSfixed64 int64 var repeatDataPathTrailingResourceInputInfoPUint64 uint64 var repeatDataPathTrailingResourceInputInfoPFixed64 uint64 var repeatDataPathTrailingResourceInputInfoPFloat float32 var repeatDataPathTrailingResourceInputInfoPDouble float64 var repeatDataPathTrailingResourceInputInfoPBool bool var RepeatDataPathTrailingResourceInputInfoPKingdom string var RepeatDataPathTrailingResourceInputInfoPChildFContinent string var repeatDataPathTrailingResourceInputInfoPChildPString string var repeatDataPathTrailingResourceInputInfoPChildPFloat float32 var repeatDataPathTrailingResourceInputInfoPChildPDouble float64 var repeatDataPathTrailingResourceInputInfoPChildPBool bool var RepeatDataPathTrailingResourceInputInfoPChildPContinent string var repeatDataPathTrailingResourceInputIntendedBindingUri string var repeatDataPathTrailingResourceInputPInt32 int32 var repeatDataPathTrailingResourceInputPInt64 int64 var repeatDataPathTrailingResourceInputPDouble float64 func init() { ComplianceServiceCmd.AddCommand(RepeatDataPathTrailingResourceCmd) RepeatDataPathTrailingResourceInput.Info = new(genprotopb.ComplianceData) RepeatDataPathTrailingResourceInput.Info.FChild = new(genprotopb.ComplianceDataChild) RepeatDataPathTrailingResourceInput.Info.FChild.FChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataPathTrailingResourceInput.Info.FChild.PChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataPathTrailingResourceInput.Info.PChild = new(genprotopb.ComplianceDataChild) RepeatDataPathTrailingResourceInput.Info.PChild.FChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataPathTrailingResourceInput.Info.PChild.PChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataPathTrailingResourceCmd.Flags().StringVar(&RepeatDataPathTrailingResourceInput.Name, "name", "", "") RepeatDataPathTrailingResourceCmd.Flags().StringVar(&RepeatDataPathTrailingResourceInput.Info.FString, "info.f_string", "", "") RepeatDataPathTrailingResourceCmd.Flags().Int32Var(&RepeatDataPathTrailingResourceInput.Info.FInt32, "info.f_int32", 0, "") RepeatDataPathTrailingResourceCmd.Flags().Int32Var(&RepeatDataPathTrailingResourceInput.Info.FSint32, "info.f_sint32", 0, "") RepeatDataPathTrailingResourceCmd.Flags().Int32Var(&RepeatDataPathTrailingResourceInput.Info.FSfixed32, "info.f_sfixed32", 0, "") RepeatDataPathTrailingResourceCmd.Flags().Uint32Var(&RepeatDataPathTrailingResourceInput.Info.FUint32, "info.f_uint32", 0, "") RepeatDataPathTrailingResourceCmd.Flags().Uint32Var(&RepeatDataPathTrailingResourceInput.Info.FFixed32, "info.f_fixed32", 0, "") RepeatDataPathTrailingResourceCmd.Flags().Int64Var(&RepeatDataPathTrailingResourceInput.Info.FInt64, "info.f_int64", 0, "") RepeatDataPathTrailingResourceCmd.Flags().Int64Var(&RepeatDataPathTrailingResourceInput.Info.FSint64, "info.f_sint64", 0, "") RepeatDataPathTrailingResourceCmd.Flags().Int64Var(&RepeatDataPathTrailingResourceInput.Info.FSfixed64, "info.f_sfixed64", 0, "") RepeatDataPathTrailingResourceCmd.Flags().Uint64Var(&RepeatDataPathTrailingResourceInput.Info.FUint64, "info.f_uint64", 0, "") RepeatDataPathTrailingResourceCmd.Flags().Uint64Var(&RepeatDataPathTrailingResourceInput.Info.FFixed64, "info.f_fixed64", 0, "") RepeatDataPathTrailingResourceCmd.Flags().Float64Var(&RepeatDataPathTrailingResourceInput.Info.FDouble, "info.f_double", 0.0, "") RepeatDataPathTrailingResourceCmd.Flags().Float32Var(&RepeatDataPathTrailingResourceInput.Info.FFloat, "info.f_float", 0.0, "") RepeatDataPathTrailingResourceCmd.Flags().BoolVar(&RepeatDataPathTrailingResourceInput.Info.FBool, "info.f_bool", false, "") RepeatDataPathTrailingResourceCmd.Flags().BytesHexVar(&RepeatDataPathTrailingResourceInput.Info.FBytes, "info.f_bytes", []byte{}, "") RepeatDataPathTrailingResourceCmd.Flags().StringVar(&RepeatDataPathTrailingResourceInputInfoFKingdom, "info.f_kingdom", "", "") RepeatDataPathTrailingResourceCmd.Flags().StringVar(&RepeatDataPathTrailingResourceInput.Info.FChild.FString, "info.f_child.f_string", "", "") RepeatDataPathTrailingResourceCmd.Flags().Float32Var(&RepeatDataPathTrailingResourceInput.Info.FChild.FFloat, "info.f_child.f_float", 0.0, "") RepeatDataPathTrailingResourceCmd.Flags().Float64Var(&RepeatDataPathTrailingResourceInput.Info.FChild.FDouble, "info.f_child.f_double", 0.0, "") RepeatDataPathTrailingResourceCmd.Flags().BoolVar(&RepeatDataPathTrailingResourceInput.Info.FChild.FBool, "info.f_child.f_bool", false, "") RepeatDataPathTrailingResourceCmd.Flags().StringVar(&RepeatDataPathTrailingResourceInputInfoFChildFContinent, "info.f_child.f_continent", "", "") RepeatDataPathTrailingResourceCmd.Flags().StringVar(&RepeatDataPathTrailingResourceInput.Info.FChild.FChild.FString, "info.f_child.f_child.f_string", "", "") RepeatDataPathTrailingResourceCmd.Flags().Float64Var(&RepeatDataPathTrailingResourceInput.Info.FChild.FChild.FDouble, "info.f_child.f_child.f_double", 0.0, "") RepeatDataPathTrailingResourceCmd.Flags().BoolVar(&RepeatDataPathTrailingResourceInput.Info.FChild.FChild.FBool, "info.f_child.f_child.f_bool", false, "") RepeatDataPathTrailingResourceCmd.Flags().StringVar(&repeatDataPathTrailingResourceInputInfoFChildPString, "info.f_child.p_string", "", "") RepeatDataPathTrailingResourceCmd.Flags().Float32Var(&repeatDataPathTrailingResourceInputInfoFChildPFloat, "info.f_child.p_float", 0.0, "") RepeatDataPathTrailingResourceCmd.Flags().Float64Var(&repeatDataPathTrailingResourceInputInfoFChildPDouble, "info.f_child.p_double", 0.0, "") RepeatDataPathTrailingResourceCmd.Flags().BoolVar(&repeatDataPathTrailingResourceInputInfoFChildPBool, "info.f_child.p_bool", false, "") RepeatDataPathTrailingResourceCmd.Flags().StringVar(&RepeatDataPathTrailingResourceInputInfoFChildPContinent, "info.f_child.p_continent", "", "") RepeatDataPathTrailingResourceCmd.Flags().StringVar(&RepeatDataPathTrailingResourceInput.Info.FChild.PChild.FString, "info.f_child.p_child.f_string", "", "") RepeatDataPathTrailingResourceCmd.Flags().Float64Var(&RepeatDataPathTrailingResourceInput.Info.FChild.PChild.FDouble, "info.f_child.p_child.f_double", 0.0, "") RepeatDataPathTrailingResourceCmd.Flags().BoolVar(&RepeatDataPathTrailingResourceInput.Info.FChild.PChild.FBool, "info.f_child.p_child.f_bool", false, "") RepeatDataPathTrailingResourceCmd.Flags().StringVar(&repeatDataPathTrailingResourceInputInfoPString, "info.p_string", "", "") RepeatDataPathTrailingResourceCmd.Flags().Int32Var(&repeatDataPathTrailingResourceInputInfoPInt32, "info.p_int32", 0, "") RepeatDataPathTrailingResourceCmd.Flags().Int32Var(&repeatDataPathTrailingResourceInputInfoPSint32, "info.p_sint32", 0, "") RepeatDataPathTrailingResourceCmd.Flags().Int32Var(&repeatDataPathTrailingResourceInputInfoPSfixed32, "info.p_sfixed32", 0, "") RepeatDataPathTrailingResourceCmd.Flags().Uint32Var(&repeatDataPathTrailingResourceInputInfoPUint32, "info.p_uint32", 0, "") RepeatDataPathTrailingResourceCmd.Flags().Uint32Var(&repeatDataPathTrailingResourceInputInfoPFixed32, "info.p_fixed32", 0, "") RepeatDataPathTrailingResourceCmd.Flags().Int64Var(&repeatDataPathTrailingResourceInputInfoPInt64, "info.p_int64", 0, "") RepeatDataPathTrailingResourceCmd.Flags().Int64Var(&repeatDataPathTrailingResourceInputInfoPSint64, "info.p_sint64", 0, "") RepeatDataPathTrailingResourceCmd.Flags().Int64Var(&repeatDataPathTrailingResourceInputInfoPSfixed64, "info.p_sfixed64", 0, "") RepeatDataPathTrailingResourceCmd.Flags().Uint64Var(&repeatDataPathTrailingResourceInputInfoPUint64, "info.p_uint64", 0, "") RepeatDataPathTrailingResourceCmd.Flags().Uint64Var(&repeatDataPathTrailingResourceInputInfoPFixed64, "info.p_fixed64", 0, "") RepeatDataPathTrailingResourceCmd.Flags().Float32Var(&repeatDataPathTrailingResourceInputInfoPFloat, "info.p_float", 0.0, "") RepeatDataPathTrailingResourceCmd.Flags().Float64Var(&repeatDataPathTrailingResourceInputInfoPDouble, "info.p_double", 0.0, "") RepeatDataPathTrailingResourceCmd.Flags().BoolVar(&repeatDataPathTrailingResourceInputInfoPBool, "info.p_bool", false, "") RepeatDataPathTrailingResourceCmd.Flags().StringVar(&RepeatDataPathTrailingResourceInputInfoPKingdom, "info.p_kingdom", "", "") RepeatDataPathTrailingResourceCmd.Flags().StringVar(&RepeatDataPathTrailingResourceInput.Info.PChild.FString, "info.p_child.f_string", "", "") RepeatDataPathTrailingResourceCmd.Flags().Float32Var(&RepeatDataPathTrailingResourceInput.Info.PChild.FFloat, "info.p_child.f_float", 0.0, "") RepeatDataPathTrailingResourceCmd.Flags().Float64Var(&RepeatDataPathTrailingResourceInput.Info.PChild.FDouble, "info.p_child.f_double", 0.0, "") RepeatDataPathTrailingResourceCmd.Flags().BoolVar(&RepeatDataPathTrailingResourceInput.Info.PChild.FBool, "info.p_child.f_bool", false, "") RepeatDataPathTrailingResourceCmd.Flags().StringVar(&RepeatDataPathTrailingResourceInputInfoPChildFContinent, "info.p_child.f_continent", "", "") RepeatDataPathTrailingResourceCmd.Flags().StringVar(&RepeatDataPathTrailingResourceInput.Info.PChild.FChild.FString, "info.p_child.f_child.f_string", "", "") RepeatDataPathTrailingResourceCmd.Flags().Float64Var(&RepeatDataPathTrailingResourceInput.Info.PChild.FChild.FDouble, "info.p_child.f_child.f_double", 0.0, "") RepeatDataPathTrailingResourceCmd.Flags().BoolVar(&RepeatDataPathTrailingResourceInput.Info.PChild.FChild.FBool, "info.p_child.f_child.f_bool", false, "") RepeatDataPathTrailingResourceCmd.Flags().StringVar(&repeatDataPathTrailingResourceInputInfoPChildPString, "info.p_child.p_string", "", "") RepeatDataPathTrailingResourceCmd.Flags().Float32Var(&repeatDataPathTrailingResourceInputInfoPChildPFloat, "info.p_child.p_float", 0.0, "") RepeatDataPathTrailingResourceCmd.Flags().Float64Var(&repeatDataPathTrailingResourceInputInfoPChildPDouble, "info.p_child.p_double", 0.0, "") RepeatDataPathTrailingResourceCmd.Flags().BoolVar(&repeatDataPathTrailingResourceInputInfoPChildPBool, "info.p_child.p_bool", false, "") RepeatDataPathTrailingResourceCmd.Flags().StringVar(&RepeatDataPathTrailingResourceInputInfoPChildPContinent, "info.p_child.p_continent", "", "") RepeatDataPathTrailingResourceCmd.Flags().StringVar(&RepeatDataPathTrailingResourceInput.Info.PChild.PChild.FString, "info.p_child.p_child.f_string", "", "") RepeatDataPathTrailingResourceCmd.Flags().Float64Var(&RepeatDataPathTrailingResourceInput.Info.PChild.PChild.FDouble, "info.p_child.p_child.f_double", 0.0, "") RepeatDataPathTrailingResourceCmd.Flags().BoolVar(&RepeatDataPathTrailingResourceInput.Info.PChild.PChild.FBool, "info.p_child.p_child.f_bool", false, "") RepeatDataPathTrailingResourceCmd.Flags().BoolVar(&RepeatDataPathTrailingResourceInput.ServerVerify, "server_verify", false, "If true, the server will verify that the received...") RepeatDataPathTrailingResourceCmd.Flags().StringVar(&repeatDataPathTrailingResourceInputIntendedBindingUri, "intended_binding_uri", "", "The URI template this request is expected to be...") RepeatDataPathTrailingResourceCmd.Flags().Int32Var(&RepeatDataPathTrailingResourceInput.FInt32, "f_int32", 0, "Some top level fields, to test that these are...") RepeatDataPathTrailingResourceCmd.Flags().Int64Var(&RepeatDataPathTrailingResourceInput.FInt64, "f_int64", 0, "") RepeatDataPathTrailingResourceCmd.Flags().Float64Var(&RepeatDataPathTrailingResourceInput.FDouble, "f_double", 0.0, "") RepeatDataPathTrailingResourceCmd.Flags().Int32Var(&repeatDataPathTrailingResourceInputPInt32, "p_int32", 0, "") RepeatDataPathTrailingResourceCmd.Flags().Int64Var(&repeatDataPathTrailingResourceInputPInt64, "p_int64", 0, "") RepeatDataPathTrailingResourceCmd.Flags().Float64Var(&repeatDataPathTrailingResourceInputPDouble, "p_double", 0.0, "") RepeatDataPathTrailingResourceCmd.Flags().StringVar(&RepeatDataPathTrailingResourceFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var RepeatDataPathTrailingResourceCmd = &cobra.Command{ Use: "repeat-data-path-trailing-resource", Short: "Same as RepeatDataSimplePath, but with a trailing...", Long: "Same as RepeatDataSimplePath, but with a trailing resource.", PreRun: func(cmd *cobra.Command, args []string) { if RepeatDataPathTrailingResourceFromFile == "" { } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if RepeatDataPathTrailingResourceFromFile != "" { in, err = os.Open(RepeatDataPathTrailingResourceFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &RepeatDataPathTrailingResourceInput) if err != nil { return err } } else { RepeatDataPathTrailingResourceInput.Info.FKingdom = genprotopb.ComplianceData_LifeKingdom(genprotopb.ComplianceData_LifeKingdom_value[strings.ToUpper(RepeatDataPathTrailingResourceInputInfoFKingdom)]) RepeatDataPathTrailingResourceInput.Info.FChild.FContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataPathTrailingResourceInputInfoFChildFContinent)]) RepeatDataPathTrailingResourceInput.Info.FChild.PContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataPathTrailingResourceInputInfoFChildPContinent)]) if cmd.Flags().Changed("info.p_kingdom") { e := genprotopb.ComplianceData_LifeKingdom(genprotopb.ComplianceData_LifeKingdom_value[strings.ToUpper(RepeatDataPathTrailingResourceInputInfoPKingdom)]) RepeatDataPathTrailingResourceInput.Info.PKingdom = &e } RepeatDataPathTrailingResourceInput.Info.PChild.FContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataPathTrailingResourceInputInfoPChildFContinent)]) RepeatDataPathTrailingResourceInput.Info.PChild.PContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataPathTrailingResourceInputInfoPChildPContinent)]) if cmd.Flags().Changed("info.f_child.p_string") { RepeatDataPathTrailingResourceInput.Info.FChild.PString = &repeatDataPathTrailingResourceInputInfoFChildPString } if cmd.Flags().Changed("info.f_child.p_float") { RepeatDataPathTrailingResourceInput.Info.FChild.PFloat = &repeatDataPathTrailingResourceInputInfoFChildPFloat } if cmd.Flags().Changed("info.f_child.p_double") { RepeatDataPathTrailingResourceInput.Info.FChild.PDouble = &repeatDataPathTrailingResourceInputInfoFChildPDouble } if cmd.Flags().Changed("info.f_child.p_bool") { RepeatDataPathTrailingResourceInput.Info.FChild.PBool = &repeatDataPathTrailingResourceInputInfoFChildPBool } if cmd.Flags().Changed("info.p_string") { RepeatDataPathTrailingResourceInput.Info.PString = &repeatDataPathTrailingResourceInputInfoPString } if cmd.Flags().Changed("info.p_int32") { RepeatDataPathTrailingResourceInput.Info.PInt32 = &repeatDataPathTrailingResourceInputInfoPInt32 } if cmd.Flags().Changed("info.p_sint32") { RepeatDataPathTrailingResourceInput.Info.PSint32 = &repeatDataPathTrailingResourceInputInfoPSint32 } if cmd.Flags().Changed("info.p_sfixed32") { RepeatDataPathTrailingResourceInput.Info.PSfixed32 = &repeatDataPathTrailingResourceInputInfoPSfixed32 } if cmd.Flags().Changed("info.p_uint32") { RepeatDataPathTrailingResourceInput.Info.PUint32 = &repeatDataPathTrailingResourceInputInfoPUint32 } if cmd.Flags().Changed("info.p_fixed32") { RepeatDataPathTrailingResourceInput.Info.PFixed32 = &repeatDataPathTrailingResourceInputInfoPFixed32 } if cmd.Flags().Changed("info.p_int64") { RepeatDataPathTrailingResourceInput.Info.PInt64 = &repeatDataPathTrailingResourceInputInfoPInt64 } if cmd.Flags().Changed("info.p_sint64") { RepeatDataPathTrailingResourceInput.Info.PSint64 = &repeatDataPathTrailingResourceInputInfoPSint64 } if cmd.Flags().Changed("info.p_sfixed64") { RepeatDataPathTrailingResourceInput.Info.PSfixed64 = &repeatDataPathTrailingResourceInputInfoPSfixed64 } if cmd.Flags().Changed("info.p_uint64") { RepeatDataPathTrailingResourceInput.Info.PUint64 = &repeatDataPathTrailingResourceInputInfoPUint64 } if cmd.Flags().Changed("info.p_fixed64") { RepeatDataPathTrailingResourceInput.Info.PFixed64 = &repeatDataPathTrailingResourceInputInfoPFixed64 } if cmd.Flags().Changed("info.p_float") { RepeatDataPathTrailingResourceInput.Info.PFloat = &repeatDataPathTrailingResourceInputInfoPFloat } if cmd.Flags().Changed("info.p_double") { RepeatDataPathTrailingResourceInput.Info.PDouble = &repeatDataPathTrailingResourceInputInfoPDouble } if cmd.Flags().Changed("info.p_bool") { RepeatDataPathTrailingResourceInput.Info.PBool = &repeatDataPathTrailingResourceInputInfoPBool } if cmd.Flags().Changed("info.p_child.p_string") { RepeatDataPathTrailingResourceInput.Info.PChild.PString = &repeatDataPathTrailingResourceInputInfoPChildPString } if cmd.Flags().Changed("info.p_child.p_float") { RepeatDataPathTrailingResourceInput.Info.PChild.PFloat = &repeatDataPathTrailingResourceInputInfoPChildPFloat } if cmd.Flags().Changed("info.p_child.p_double") { RepeatDataPathTrailingResourceInput.Info.PChild.PDouble = &repeatDataPathTrailingResourceInputInfoPChildPDouble } if cmd.Flags().Changed("info.p_child.p_bool") { RepeatDataPathTrailingResourceInput.Info.PChild.PBool = &repeatDataPathTrailingResourceInputInfoPChildPBool } if cmd.Flags().Changed("intended_binding_uri") { RepeatDataPathTrailingResourceInput.IntendedBindingUri = &repeatDataPathTrailingResourceInputIntendedBindingUri } if cmd.Flags().Changed("p_int32") { RepeatDataPathTrailingResourceInput.PInt32 = &repeatDataPathTrailingResourceInputPInt32 } if cmd.Flags().Changed("p_int64") { RepeatDataPathTrailingResourceInput.PInt64 = &repeatDataPathTrailingResourceInputPInt64 } if cmd.Flags().Changed("p_double") { RepeatDataPathTrailingResourceInput.PDouble = &repeatDataPathTrailingResourceInputPDouble } } if Verbose { printVerboseInput("Compliance", "RepeatDataPathTrailingResource", &RepeatDataPathTrailingResourceInput) } resp, err := ComplianceClient.RepeatDataPathTrailingResource(ctx, &RepeatDataPathTrailingResourceInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/repeat-data-query.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" "strings" ) var RepeatDataQueryInput genprotopb.RepeatRequest var RepeatDataQueryFromFile string var RepeatDataQueryInputInfoFKingdom string var RepeatDataQueryInputInfoFChildFContinent string var repeatDataQueryInputInfoFChildPString string var repeatDataQueryInputInfoFChildPFloat float32 var repeatDataQueryInputInfoFChildPDouble float64 var repeatDataQueryInputInfoFChildPBool bool var RepeatDataQueryInputInfoFChildPContinent string var repeatDataQueryInputInfoPString string var repeatDataQueryInputInfoPInt32 int32 var repeatDataQueryInputInfoPSint32 int32 var repeatDataQueryInputInfoPSfixed32 int32 var repeatDataQueryInputInfoPUint32 uint32 var repeatDataQueryInputInfoPFixed32 uint32 var repeatDataQueryInputInfoPInt64 int64 var repeatDataQueryInputInfoPSint64 int64 var repeatDataQueryInputInfoPSfixed64 int64 var repeatDataQueryInputInfoPUint64 uint64 var repeatDataQueryInputInfoPFixed64 uint64 var repeatDataQueryInputInfoPFloat float32 var repeatDataQueryInputInfoPDouble float64 var repeatDataQueryInputInfoPBool bool var RepeatDataQueryInputInfoPKingdom string var RepeatDataQueryInputInfoPChildFContinent string var repeatDataQueryInputInfoPChildPString string var repeatDataQueryInputInfoPChildPFloat float32 var repeatDataQueryInputInfoPChildPDouble float64 var repeatDataQueryInputInfoPChildPBool bool var RepeatDataQueryInputInfoPChildPContinent string var repeatDataQueryInputIntendedBindingUri string var repeatDataQueryInputPInt32 int32 var repeatDataQueryInputPInt64 int64 var repeatDataQueryInputPDouble float64 func init() { ComplianceServiceCmd.AddCommand(RepeatDataQueryCmd) RepeatDataQueryInput.Info = new(genprotopb.ComplianceData) RepeatDataQueryInput.Info.FChild = new(genprotopb.ComplianceDataChild) RepeatDataQueryInput.Info.FChild.FChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataQueryInput.Info.FChild.PChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataQueryInput.Info.PChild = new(genprotopb.ComplianceDataChild) RepeatDataQueryInput.Info.PChild.FChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataQueryInput.Info.PChild.PChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataQueryCmd.Flags().StringVar(&RepeatDataQueryInput.Name, "name", "", "") RepeatDataQueryCmd.Flags().StringVar(&RepeatDataQueryInput.Info.FString, "info.f_string", "", "") RepeatDataQueryCmd.Flags().Int32Var(&RepeatDataQueryInput.Info.FInt32, "info.f_int32", 0, "") RepeatDataQueryCmd.Flags().Int32Var(&RepeatDataQueryInput.Info.FSint32, "info.f_sint32", 0, "") RepeatDataQueryCmd.Flags().Int32Var(&RepeatDataQueryInput.Info.FSfixed32, "info.f_sfixed32", 0, "") RepeatDataQueryCmd.Flags().Uint32Var(&RepeatDataQueryInput.Info.FUint32, "info.f_uint32", 0, "") RepeatDataQueryCmd.Flags().Uint32Var(&RepeatDataQueryInput.Info.FFixed32, "info.f_fixed32", 0, "") RepeatDataQueryCmd.Flags().Int64Var(&RepeatDataQueryInput.Info.FInt64, "info.f_int64", 0, "") RepeatDataQueryCmd.Flags().Int64Var(&RepeatDataQueryInput.Info.FSint64, "info.f_sint64", 0, "") RepeatDataQueryCmd.Flags().Int64Var(&RepeatDataQueryInput.Info.FSfixed64, "info.f_sfixed64", 0, "") RepeatDataQueryCmd.Flags().Uint64Var(&RepeatDataQueryInput.Info.FUint64, "info.f_uint64", 0, "") RepeatDataQueryCmd.Flags().Uint64Var(&RepeatDataQueryInput.Info.FFixed64, "info.f_fixed64", 0, "") RepeatDataQueryCmd.Flags().Float64Var(&RepeatDataQueryInput.Info.FDouble, "info.f_double", 0.0, "") RepeatDataQueryCmd.Flags().Float32Var(&RepeatDataQueryInput.Info.FFloat, "info.f_float", 0.0, "") RepeatDataQueryCmd.Flags().BoolVar(&RepeatDataQueryInput.Info.FBool, "info.f_bool", false, "") RepeatDataQueryCmd.Flags().BytesHexVar(&RepeatDataQueryInput.Info.FBytes, "info.f_bytes", []byte{}, "") RepeatDataQueryCmd.Flags().StringVar(&RepeatDataQueryInputInfoFKingdom, "info.f_kingdom", "", "") RepeatDataQueryCmd.Flags().StringVar(&RepeatDataQueryInput.Info.FChild.FString, "info.f_child.f_string", "", "") RepeatDataQueryCmd.Flags().Float32Var(&RepeatDataQueryInput.Info.FChild.FFloat, "info.f_child.f_float", 0.0, "") RepeatDataQueryCmd.Flags().Float64Var(&RepeatDataQueryInput.Info.FChild.FDouble, "info.f_child.f_double", 0.0, "") RepeatDataQueryCmd.Flags().BoolVar(&RepeatDataQueryInput.Info.FChild.FBool, "info.f_child.f_bool", false, "") RepeatDataQueryCmd.Flags().StringVar(&RepeatDataQueryInputInfoFChildFContinent, "info.f_child.f_continent", "", "") RepeatDataQueryCmd.Flags().StringVar(&RepeatDataQueryInput.Info.FChild.FChild.FString, "info.f_child.f_child.f_string", "", "") RepeatDataQueryCmd.Flags().Float64Var(&RepeatDataQueryInput.Info.FChild.FChild.FDouble, "info.f_child.f_child.f_double", 0.0, "") RepeatDataQueryCmd.Flags().BoolVar(&RepeatDataQueryInput.Info.FChild.FChild.FBool, "info.f_child.f_child.f_bool", false, "") RepeatDataQueryCmd.Flags().StringVar(&repeatDataQueryInputInfoFChildPString, "info.f_child.p_string", "", "") RepeatDataQueryCmd.Flags().Float32Var(&repeatDataQueryInputInfoFChildPFloat, "info.f_child.p_float", 0.0, "") RepeatDataQueryCmd.Flags().Float64Var(&repeatDataQueryInputInfoFChildPDouble, "info.f_child.p_double", 0.0, "") RepeatDataQueryCmd.Flags().BoolVar(&repeatDataQueryInputInfoFChildPBool, "info.f_child.p_bool", false, "") RepeatDataQueryCmd.Flags().StringVar(&RepeatDataQueryInputInfoFChildPContinent, "info.f_child.p_continent", "", "") RepeatDataQueryCmd.Flags().StringVar(&RepeatDataQueryInput.Info.FChild.PChild.FString, "info.f_child.p_child.f_string", "", "") RepeatDataQueryCmd.Flags().Float64Var(&RepeatDataQueryInput.Info.FChild.PChild.FDouble, "info.f_child.p_child.f_double", 0.0, "") RepeatDataQueryCmd.Flags().BoolVar(&RepeatDataQueryInput.Info.FChild.PChild.FBool, "info.f_child.p_child.f_bool", false, "") RepeatDataQueryCmd.Flags().StringVar(&repeatDataQueryInputInfoPString, "info.p_string", "", "") RepeatDataQueryCmd.Flags().Int32Var(&repeatDataQueryInputInfoPInt32, "info.p_int32", 0, "") RepeatDataQueryCmd.Flags().Int32Var(&repeatDataQueryInputInfoPSint32, "info.p_sint32", 0, "") RepeatDataQueryCmd.Flags().Int32Var(&repeatDataQueryInputInfoPSfixed32, "info.p_sfixed32", 0, "") RepeatDataQueryCmd.Flags().Uint32Var(&repeatDataQueryInputInfoPUint32, "info.p_uint32", 0, "") RepeatDataQueryCmd.Flags().Uint32Var(&repeatDataQueryInputInfoPFixed32, "info.p_fixed32", 0, "") RepeatDataQueryCmd.Flags().Int64Var(&repeatDataQueryInputInfoPInt64, "info.p_int64", 0, "") RepeatDataQueryCmd.Flags().Int64Var(&repeatDataQueryInputInfoPSint64, "info.p_sint64", 0, "") RepeatDataQueryCmd.Flags().Int64Var(&repeatDataQueryInputInfoPSfixed64, "info.p_sfixed64", 0, "") RepeatDataQueryCmd.Flags().Uint64Var(&repeatDataQueryInputInfoPUint64, "info.p_uint64", 0, "") RepeatDataQueryCmd.Flags().Uint64Var(&repeatDataQueryInputInfoPFixed64, "info.p_fixed64", 0, "") RepeatDataQueryCmd.Flags().Float32Var(&repeatDataQueryInputInfoPFloat, "info.p_float", 0.0, "") RepeatDataQueryCmd.Flags().Float64Var(&repeatDataQueryInputInfoPDouble, "info.p_double", 0.0, "") RepeatDataQueryCmd.Flags().BoolVar(&repeatDataQueryInputInfoPBool, "info.p_bool", false, "") RepeatDataQueryCmd.Flags().StringVar(&RepeatDataQueryInputInfoPKingdom, "info.p_kingdom", "", "") RepeatDataQueryCmd.Flags().StringVar(&RepeatDataQueryInput.Info.PChild.FString, "info.p_child.f_string", "", "") RepeatDataQueryCmd.Flags().Float32Var(&RepeatDataQueryInput.Info.PChild.FFloat, "info.p_child.f_float", 0.0, "") RepeatDataQueryCmd.Flags().Float64Var(&RepeatDataQueryInput.Info.PChild.FDouble, "info.p_child.f_double", 0.0, "") RepeatDataQueryCmd.Flags().BoolVar(&RepeatDataQueryInput.Info.PChild.FBool, "info.p_child.f_bool", false, "") RepeatDataQueryCmd.Flags().StringVar(&RepeatDataQueryInputInfoPChildFContinent, "info.p_child.f_continent", "", "") RepeatDataQueryCmd.Flags().StringVar(&RepeatDataQueryInput.Info.PChild.FChild.FString, "info.p_child.f_child.f_string", "", "") RepeatDataQueryCmd.Flags().Float64Var(&RepeatDataQueryInput.Info.PChild.FChild.FDouble, "info.p_child.f_child.f_double", 0.0, "") RepeatDataQueryCmd.Flags().BoolVar(&RepeatDataQueryInput.Info.PChild.FChild.FBool, "info.p_child.f_child.f_bool", false, "") RepeatDataQueryCmd.Flags().StringVar(&repeatDataQueryInputInfoPChildPString, "info.p_child.p_string", "", "") RepeatDataQueryCmd.Flags().Float32Var(&repeatDataQueryInputInfoPChildPFloat, "info.p_child.p_float", 0.0, "") RepeatDataQueryCmd.Flags().Float64Var(&repeatDataQueryInputInfoPChildPDouble, "info.p_child.p_double", 0.0, "") RepeatDataQueryCmd.Flags().BoolVar(&repeatDataQueryInputInfoPChildPBool, "info.p_child.p_bool", false, "") RepeatDataQueryCmd.Flags().StringVar(&RepeatDataQueryInputInfoPChildPContinent, "info.p_child.p_continent", "", "") RepeatDataQueryCmd.Flags().StringVar(&RepeatDataQueryInput.Info.PChild.PChild.FString, "info.p_child.p_child.f_string", "", "") RepeatDataQueryCmd.Flags().Float64Var(&RepeatDataQueryInput.Info.PChild.PChild.FDouble, "info.p_child.p_child.f_double", 0.0, "") RepeatDataQueryCmd.Flags().BoolVar(&RepeatDataQueryInput.Info.PChild.PChild.FBool, "info.p_child.p_child.f_bool", false, "") RepeatDataQueryCmd.Flags().BoolVar(&RepeatDataQueryInput.ServerVerify, "server_verify", false, "If true, the server will verify that the received...") RepeatDataQueryCmd.Flags().StringVar(&repeatDataQueryInputIntendedBindingUri, "intended_binding_uri", "", "The URI template this request is expected to be...") RepeatDataQueryCmd.Flags().Int32Var(&RepeatDataQueryInput.FInt32, "f_int32", 0, "Some top level fields, to test that these are...") RepeatDataQueryCmd.Flags().Int64Var(&RepeatDataQueryInput.FInt64, "f_int64", 0, "") RepeatDataQueryCmd.Flags().Float64Var(&RepeatDataQueryInput.FDouble, "f_double", 0.0, "") RepeatDataQueryCmd.Flags().Int32Var(&repeatDataQueryInputPInt32, "p_int32", 0, "") RepeatDataQueryCmd.Flags().Int64Var(&repeatDataQueryInputPInt64, "p_int64", 0, "") RepeatDataQueryCmd.Flags().Float64Var(&repeatDataQueryInputPDouble, "p_double", 0.0, "") RepeatDataQueryCmd.Flags().StringVar(&RepeatDataQueryFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var RepeatDataQueryCmd = &cobra.Command{ Use: "repeat-data-query", Short: "This method echoes the ComplianceData request....", Long: "This method echoes the ComplianceData request. This method exercises sending all request fields as query parameters.", PreRun: func(cmd *cobra.Command, args []string) { if RepeatDataQueryFromFile == "" { } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if RepeatDataQueryFromFile != "" { in, err = os.Open(RepeatDataQueryFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &RepeatDataQueryInput) if err != nil { return err } } else { RepeatDataQueryInput.Info.FKingdom = genprotopb.ComplianceData_LifeKingdom(genprotopb.ComplianceData_LifeKingdom_value[strings.ToUpper(RepeatDataQueryInputInfoFKingdom)]) RepeatDataQueryInput.Info.FChild.FContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataQueryInputInfoFChildFContinent)]) RepeatDataQueryInput.Info.FChild.PContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataQueryInputInfoFChildPContinent)]) if cmd.Flags().Changed("info.p_kingdom") { e := genprotopb.ComplianceData_LifeKingdom(genprotopb.ComplianceData_LifeKingdom_value[strings.ToUpper(RepeatDataQueryInputInfoPKingdom)]) RepeatDataQueryInput.Info.PKingdom = &e } RepeatDataQueryInput.Info.PChild.FContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataQueryInputInfoPChildFContinent)]) RepeatDataQueryInput.Info.PChild.PContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataQueryInputInfoPChildPContinent)]) if cmd.Flags().Changed("info.f_child.p_string") { RepeatDataQueryInput.Info.FChild.PString = &repeatDataQueryInputInfoFChildPString } if cmd.Flags().Changed("info.f_child.p_float") { RepeatDataQueryInput.Info.FChild.PFloat = &repeatDataQueryInputInfoFChildPFloat } if cmd.Flags().Changed("info.f_child.p_double") { RepeatDataQueryInput.Info.FChild.PDouble = &repeatDataQueryInputInfoFChildPDouble } if cmd.Flags().Changed("info.f_child.p_bool") { RepeatDataQueryInput.Info.FChild.PBool = &repeatDataQueryInputInfoFChildPBool } if cmd.Flags().Changed("info.p_string") { RepeatDataQueryInput.Info.PString = &repeatDataQueryInputInfoPString } if cmd.Flags().Changed("info.p_int32") { RepeatDataQueryInput.Info.PInt32 = &repeatDataQueryInputInfoPInt32 } if cmd.Flags().Changed("info.p_sint32") { RepeatDataQueryInput.Info.PSint32 = &repeatDataQueryInputInfoPSint32 } if cmd.Flags().Changed("info.p_sfixed32") { RepeatDataQueryInput.Info.PSfixed32 = &repeatDataQueryInputInfoPSfixed32 } if cmd.Flags().Changed("info.p_uint32") { RepeatDataQueryInput.Info.PUint32 = &repeatDataQueryInputInfoPUint32 } if cmd.Flags().Changed("info.p_fixed32") { RepeatDataQueryInput.Info.PFixed32 = &repeatDataQueryInputInfoPFixed32 } if cmd.Flags().Changed("info.p_int64") { RepeatDataQueryInput.Info.PInt64 = &repeatDataQueryInputInfoPInt64 } if cmd.Flags().Changed("info.p_sint64") { RepeatDataQueryInput.Info.PSint64 = &repeatDataQueryInputInfoPSint64 } if cmd.Flags().Changed("info.p_sfixed64") { RepeatDataQueryInput.Info.PSfixed64 = &repeatDataQueryInputInfoPSfixed64 } if cmd.Flags().Changed("info.p_uint64") { RepeatDataQueryInput.Info.PUint64 = &repeatDataQueryInputInfoPUint64 } if cmd.Flags().Changed("info.p_fixed64") { RepeatDataQueryInput.Info.PFixed64 = &repeatDataQueryInputInfoPFixed64 } if cmd.Flags().Changed("info.p_float") { RepeatDataQueryInput.Info.PFloat = &repeatDataQueryInputInfoPFloat } if cmd.Flags().Changed("info.p_double") { RepeatDataQueryInput.Info.PDouble = &repeatDataQueryInputInfoPDouble } if cmd.Flags().Changed("info.p_bool") { RepeatDataQueryInput.Info.PBool = &repeatDataQueryInputInfoPBool } if cmd.Flags().Changed("info.p_child.p_string") { RepeatDataQueryInput.Info.PChild.PString = &repeatDataQueryInputInfoPChildPString } if cmd.Flags().Changed("info.p_child.p_float") { RepeatDataQueryInput.Info.PChild.PFloat = &repeatDataQueryInputInfoPChildPFloat } if cmd.Flags().Changed("info.p_child.p_double") { RepeatDataQueryInput.Info.PChild.PDouble = &repeatDataQueryInputInfoPChildPDouble } if cmd.Flags().Changed("info.p_child.p_bool") { RepeatDataQueryInput.Info.PChild.PBool = &repeatDataQueryInputInfoPChildPBool } if cmd.Flags().Changed("intended_binding_uri") { RepeatDataQueryInput.IntendedBindingUri = &repeatDataQueryInputIntendedBindingUri } if cmd.Flags().Changed("p_int32") { RepeatDataQueryInput.PInt32 = &repeatDataQueryInputPInt32 } if cmd.Flags().Changed("p_int64") { RepeatDataQueryInput.PInt64 = &repeatDataQueryInputPInt64 } if cmd.Flags().Changed("p_double") { RepeatDataQueryInput.PDouble = &repeatDataQueryInputPDouble } } if Verbose { printVerboseInput("Compliance", "RepeatDataQuery", &RepeatDataQueryInput) } resp, err := ComplianceClient.RepeatDataQuery(ctx, &RepeatDataQueryInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/repeat-data-simple-path.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" "strings" ) var RepeatDataSimplePathInput genprotopb.RepeatRequest var RepeatDataSimplePathFromFile string var RepeatDataSimplePathInputInfoFKingdom string var RepeatDataSimplePathInputInfoFChildFContinent string var repeatDataSimplePathInputInfoFChildPString string var repeatDataSimplePathInputInfoFChildPFloat float32 var repeatDataSimplePathInputInfoFChildPDouble float64 var repeatDataSimplePathInputInfoFChildPBool bool var RepeatDataSimplePathInputInfoFChildPContinent string var repeatDataSimplePathInputInfoPString string var repeatDataSimplePathInputInfoPInt32 int32 var repeatDataSimplePathInputInfoPSint32 int32 var repeatDataSimplePathInputInfoPSfixed32 int32 var repeatDataSimplePathInputInfoPUint32 uint32 var repeatDataSimplePathInputInfoPFixed32 uint32 var repeatDataSimplePathInputInfoPInt64 int64 var repeatDataSimplePathInputInfoPSint64 int64 var repeatDataSimplePathInputInfoPSfixed64 int64 var repeatDataSimplePathInputInfoPUint64 uint64 var repeatDataSimplePathInputInfoPFixed64 uint64 var repeatDataSimplePathInputInfoPFloat float32 var repeatDataSimplePathInputInfoPDouble float64 var repeatDataSimplePathInputInfoPBool bool var RepeatDataSimplePathInputInfoPKingdom string var RepeatDataSimplePathInputInfoPChildFContinent string var repeatDataSimplePathInputInfoPChildPString string var repeatDataSimplePathInputInfoPChildPFloat float32 var repeatDataSimplePathInputInfoPChildPDouble float64 var repeatDataSimplePathInputInfoPChildPBool bool var RepeatDataSimplePathInputInfoPChildPContinent string var repeatDataSimplePathInputIntendedBindingUri string var repeatDataSimplePathInputPInt32 int32 var repeatDataSimplePathInputPInt64 int64 var repeatDataSimplePathInputPDouble float64 func init() { ComplianceServiceCmd.AddCommand(RepeatDataSimplePathCmd) RepeatDataSimplePathInput.Info = new(genprotopb.ComplianceData) RepeatDataSimplePathInput.Info.FChild = new(genprotopb.ComplianceDataChild) RepeatDataSimplePathInput.Info.FChild.FChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataSimplePathInput.Info.FChild.PChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataSimplePathInput.Info.PChild = new(genprotopb.ComplianceDataChild) RepeatDataSimplePathInput.Info.PChild.FChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataSimplePathInput.Info.PChild.PChild = new(genprotopb.ComplianceDataGrandchild) RepeatDataSimplePathCmd.Flags().StringVar(&RepeatDataSimplePathInput.Name, "name", "", "") RepeatDataSimplePathCmd.Flags().StringVar(&RepeatDataSimplePathInput.Info.FString, "info.f_string", "", "") RepeatDataSimplePathCmd.Flags().Int32Var(&RepeatDataSimplePathInput.Info.FInt32, "info.f_int32", 0, "") RepeatDataSimplePathCmd.Flags().Int32Var(&RepeatDataSimplePathInput.Info.FSint32, "info.f_sint32", 0, "") RepeatDataSimplePathCmd.Flags().Int32Var(&RepeatDataSimplePathInput.Info.FSfixed32, "info.f_sfixed32", 0, "") RepeatDataSimplePathCmd.Flags().Uint32Var(&RepeatDataSimplePathInput.Info.FUint32, "info.f_uint32", 0, "") RepeatDataSimplePathCmd.Flags().Uint32Var(&RepeatDataSimplePathInput.Info.FFixed32, "info.f_fixed32", 0, "") RepeatDataSimplePathCmd.Flags().Int64Var(&RepeatDataSimplePathInput.Info.FInt64, "info.f_int64", 0, "") RepeatDataSimplePathCmd.Flags().Int64Var(&RepeatDataSimplePathInput.Info.FSint64, "info.f_sint64", 0, "") RepeatDataSimplePathCmd.Flags().Int64Var(&RepeatDataSimplePathInput.Info.FSfixed64, "info.f_sfixed64", 0, "") RepeatDataSimplePathCmd.Flags().Uint64Var(&RepeatDataSimplePathInput.Info.FUint64, "info.f_uint64", 0, "") RepeatDataSimplePathCmd.Flags().Uint64Var(&RepeatDataSimplePathInput.Info.FFixed64, "info.f_fixed64", 0, "") RepeatDataSimplePathCmd.Flags().Float64Var(&RepeatDataSimplePathInput.Info.FDouble, "info.f_double", 0.0, "") RepeatDataSimplePathCmd.Flags().Float32Var(&RepeatDataSimplePathInput.Info.FFloat, "info.f_float", 0.0, "") RepeatDataSimplePathCmd.Flags().BoolVar(&RepeatDataSimplePathInput.Info.FBool, "info.f_bool", false, "") RepeatDataSimplePathCmd.Flags().BytesHexVar(&RepeatDataSimplePathInput.Info.FBytes, "info.f_bytes", []byte{}, "") RepeatDataSimplePathCmd.Flags().StringVar(&RepeatDataSimplePathInputInfoFKingdom, "info.f_kingdom", "", "") RepeatDataSimplePathCmd.Flags().StringVar(&RepeatDataSimplePathInput.Info.FChild.FString, "info.f_child.f_string", "", "") RepeatDataSimplePathCmd.Flags().Float32Var(&RepeatDataSimplePathInput.Info.FChild.FFloat, "info.f_child.f_float", 0.0, "") RepeatDataSimplePathCmd.Flags().Float64Var(&RepeatDataSimplePathInput.Info.FChild.FDouble, "info.f_child.f_double", 0.0, "") RepeatDataSimplePathCmd.Flags().BoolVar(&RepeatDataSimplePathInput.Info.FChild.FBool, "info.f_child.f_bool", false, "") RepeatDataSimplePathCmd.Flags().StringVar(&RepeatDataSimplePathInputInfoFChildFContinent, "info.f_child.f_continent", "", "") RepeatDataSimplePathCmd.Flags().StringVar(&RepeatDataSimplePathInput.Info.FChild.FChild.FString, "info.f_child.f_child.f_string", "", "") RepeatDataSimplePathCmd.Flags().Float64Var(&RepeatDataSimplePathInput.Info.FChild.FChild.FDouble, "info.f_child.f_child.f_double", 0.0, "") RepeatDataSimplePathCmd.Flags().BoolVar(&RepeatDataSimplePathInput.Info.FChild.FChild.FBool, "info.f_child.f_child.f_bool", false, "") RepeatDataSimplePathCmd.Flags().StringVar(&repeatDataSimplePathInputInfoFChildPString, "info.f_child.p_string", "", "") RepeatDataSimplePathCmd.Flags().Float32Var(&repeatDataSimplePathInputInfoFChildPFloat, "info.f_child.p_float", 0.0, "") RepeatDataSimplePathCmd.Flags().Float64Var(&repeatDataSimplePathInputInfoFChildPDouble, "info.f_child.p_double", 0.0, "") RepeatDataSimplePathCmd.Flags().BoolVar(&repeatDataSimplePathInputInfoFChildPBool, "info.f_child.p_bool", false, "") RepeatDataSimplePathCmd.Flags().StringVar(&RepeatDataSimplePathInputInfoFChildPContinent, "info.f_child.p_continent", "", "") RepeatDataSimplePathCmd.Flags().StringVar(&RepeatDataSimplePathInput.Info.FChild.PChild.FString, "info.f_child.p_child.f_string", "", "") RepeatDataSimplePathCmd.Flags().Float64Var(&RepeatDataSimplePathInput.Info.FChild.PChild.FDouble, "info.f_child.p_child.f_double", 0.0, "") RepeatDataSimplePathCmd.Flags().BoolVar(&RepeatDataSimplePathInput.Info.FChild.PChild.FBool, "info.f_child.p_child.f_bool", false, "") RepeatDataSimplePathCmd.Flags().StringVar(&repeatDataSimplePathInputInfoPString, "info.p_string", "", "") RepeatDataSimplePathCmd.Flags().Int32Var(&repeatDataSimplePathInputInfoPInt32, "info.p_int32", 0, "") RepeatDataSimplePathCmd.Flags().Int32Var(&repeatDataSimplePathInputInfoPSint32, "info.p_sint32", 0, "") RepeatDataSimplePathCmd.Flags().Int32Var(&repeatDataSimplePathInputInfoPSfixed32, "info.p_sfixed32", 0, "") RepeatDataSimplePathCmd.Flags().Uint32Var(&repeatDataSimplePathInputInfoPUint32, "info.p_uint32", 0, "") RepeatDataSimplePathCmd.Flags().Uint32Var(&repeatDataSimplePathInputInfoPFixed32, "info.p_fixed32", 0, "") RepeatDataSimplePathCmd.Flags().Int64Var(&repeatDataSimplePathInputInfoPInt64, "info.p_int64", 0, "") RepeatDataSimplePathCmd.Flags().Int64Var(&repeatDataSimplePathInputInfoPSint64, "info.p_sint64", 0, "") RepeatDataSimplePathCmd.Flags().Int64Var(&repeatDataSimplePathInputInfoPSfixed64, "info.p_sfixed64", 0, "") RepeatDataSimplePathCmd.Flags().Uint64Var(&repeatDataSimplePathInputInfoPUint64, "info.p_uint64", 0, "") RepeatDataSimplePathCmd.Flags().Uint64Var(&repeatDataSimplePathInputInfoPFixed64, "info.p_fixed64", 0, "") RepeatDataSimplePathCmd.Flags().Float32Var(&repeatDataSimplePathInputInfoPFloat, "info.p_float", 0.0, "") RepeatDataSimplePathCmd.Flags().Float64Var(&repeatDataSimplePathInputInfoPDouble, "info.p_double", 0.0, "") RepeatDataSimplePathCmd.Flags().BoolVar(&repeatDataSimplePathInputInfoPBool, "info.p_bool", false, "") RepeatDataSimplePathCmd.Flags().StringVar(&RepeatDataSimplePathInputInfoPKingdom, "info.p_kingdom", "", "") RepeatDataSimplePathCmd.Flags().StringVar(&RepeatDataSimplePathInput.Info.PChild.FString, "info.p_child.f_string", "", "") RepeatDataSimplePathCmd.Flags().Float32Var(&RepeatDataSimplePathInput.Info.PChild.FFloat, "info.p_child.f_float", 0.0, "") RepeatDataSimplePathCmd.Flags().Float64Var(&RepeatDataSimplePathInput.Info.PChild.FDouble, "info.p_child.f_double", 0.0, "") RepeatDataSimplePathCmd.Flags().BoolVar(&RepeatDataSimplePathInput.Info.PChild.FBool, "info.p_child.f_bool", false, "") RepeatDataSimplePathCmd.Flags().StringVar(&RepeatDataSimplePathInputInfoPChildFContinent, "info.p_child.f_continent", "", "") RepeatDataSimplePathCmd.Flags().StringVar(&RepeatDataSimplePathInput.Info.PChild.FChild.FString, "info.p_child.f_child.f_string", "", "") RepeatDataSimplePathCmd.Flags().Float64Var(&RepeatDataSimplePathInput.Info.PChild.FChild.FDouble, "info.p_child.f_child.f_double", 0.0, "") RepeatDataSimplePathCmd.Flags().BoolVar(&RepeatDataSimplePathInput.Info.PChild.FChild.FBool, "info.p_child.f_child.f_bool", false, "") RepeatDataSimplePathCmd.Flags().StringVar(&repeatDataSimplePathInputInfoPChildPString, "info.p_child.p_string", "", "") RepeatDataSimplePathCmd.Flags().Float32Var(&repeatDataSimplePathInputInfoPChildPFloat, "info.p_child.p_float", 0.0, "") RepeatDataSimplePathCmd.Flags().Float64Var(&repeatDataSimplePathInputInfoPChildPDouble, "info.p_child.p_double", 0.0, "") RepeatDataSimplePathCmd.Flags().BoolVar(&repeatDataSimplePathInputInfoPChildPBool, "info.p_child.p_bool", false, "") RepeatDataSimplePathCmd.Flags().StringVar(&RepeatDataSimplePathInputInfoPChildPContinent, "info.p_child.p_continent", "", "") RepeatDataSimplePathCmd.Flags().StringVar(&RepeatDataSimplePathInput.Info.PChild.PChild.FString, "info.p_child.p_child.f_string", "", "") RepeatDataSimplePathCmd.Flags().Float64Var(&RepeatDataSimplePathInput.Info.PChild.PChild.FDouble, "info.p_child.p_child.f_double", 0.0, "") RepeatDataSimplePathCmd.Flags().BoolVar(&RepeatDataSimplePathInput.Info.PChild.PChild.FBool, "info.p_child.p_child.f_bool", false, "") RepeatDataSimplePathCmd.Flags().BoolVar(&RepeatDataSimplePathInput.ServerVerify, "server_verify", false, "If true, the server will verify that the received...") RepeatDataSimplePathCmd.Flags().StringVar(&repeatDataSimplePathInputIntendedBindingUri, "intended_binding_uri", "", "The URI template this request is expected to be...") RepeatDataSimplePathCmd.Flags().Int32Var(&RepeatDataSimplePathInput.FInt32, "f_int32", 0, "Some top level fields, to test that these are...") RepeatDataSimplePathCmd.Flags().Int64Var(&RepeatDataSimplePathInput.FInt64, "f_int64", 0, "") RepeatDataSimplePathCmd.Flags().Float64Var(&RepeatDataSimplePathInput.FDouble, "f_double", 0.0, "") RepeatDataSimplePathCmd.Flags().Int32Var(&repeatDataSimplePathInputPInt32, "p_int32", 0, "") RepeatDataSimplePathCmd.Flags().Int64Var(&repeatDataSimplePathInputPInt64, "p_int64", 0, "") RepeatDataSimplePathCmd.Flags().Float64Var(&repeatDataSimplePathInputPDouble, "p_double", 0.0, "") RepeatDataSimplePathCmd.Flags().StringVar(&RepeatDataSimplePathFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var RepeatDataSimplePathCmd = &cobra.Command{ Use: "repeat-data-simple-path", Short: "This method echoes the ComplianceData request....", Long: "This method echoes the ComplianceData request. This method exercises sending some parameters as 'simple' path variables (i.e., of the form ...", PreRun: func(cmd *cobra.Command, args []string) { if RepeatDataSimplePathFromFile == "" { } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if RepeatDataSimplePathFromFile != "" { in, err = os.Open(RepeatDataSimplePathFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &RepeatDataSimplePathInput) if err != nil { return err } } else { RepeatDataSimplePathInput.Info.FKingdom = genprotopb.ComplianceData_LifeKingdom(genprotopb.ComplianceData_LifeKingdom_value[strings.ToUpper(RepeatDataSimplePathInputInfoFKingdom)]) RepeatDataSimplePathInput.Info.FChild.FContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataSimplePathInputInfoFChildFContinent)]) RepeatDataSimplePathInput.Info.FChild.PContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataSimplePathInputInfoFChildPContinent)]) if cmd.Flags().Changed("info.p_kingdom") { e := genprotopb.ComplianceData_LifeKingdom(genprotopb.ComplianceData_LifeKingdom_value[strings.ToUpper(RepeatDataSimplePathInputInfoPKingdom)]) RepeatDataSimplePathInput.Info.PKingdom = &e } RepeatDataSimplePathInput.Info.PChild.FContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataSimplePathInputInfoPChildFContinent)]) RepeatDataSimplePathInput.Info.PChild.PContinent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(RepeatDataSimplePathInputInfoPChildPContinent)]) if cmd.Flags().Changed("info.f_child.p_string") { RepeatDataSimplePathInput.Info.FChild.PString = &repeatDataSimplePathInputInfoFChildPString } if cmd.Flags().Changed("info.f_child.p_float") { RepeatDataSimplePathInput.Info.FChild.PFloat = &repeatDataSimplePathInputInfoFChildPFloat } if cmd.Flags().Changed("info.f_child.p_double") { RepeatDataSimplePathInput.Info.FChild.PDouble = &repeatDataSimplePathInputInfoFChildPDouble } if cmd.Flags().Changed("info.f_child.p_bool") { RepeatDataSimplePathInput.Info.FChild.PBool = &repeatDataSimplePathInputInfoFChildPBool } if cmd.Flags().Changed("info.p_string") { RepeatDataSimplePathInput.Info.PString = &repeatDataSimplePathInputInfoPString } if cmd.Flags().Changed("info.p_int32") { RepeatDataSimplePathInput.Info.PInt32 = &repeatDataSimplePathInputInfoPInt32 } if cmd.Flags().Changed("info.p_sint32") { RepeatDataSimplePathInput.Info.PSint32 = &repeatDataSimplePathInputInfoPSint32 } if cmd.Flags().Changed("info.p_sfixed32") { RepeatDataSimplePathInput.Info.PSfixed32 = &repeatDataSimplePathInputInfoPSfixed32 } if cmd.Flags().Changed("info.p_uint32") { RepeatDataSimplePathInput.Info.PUint32 = &repeatDataSimplePathInputInfoPUint32 } if cmd.Flags().Changed("info.p_fixed32") { RepeatDataSimplePathInput.Info.PFixed32 = &repeatDataSimplePathInputInfoPFixed32 } if cmd.Flags().Changed("info.p_int64") { RepeatDataSimplePathInput.Info.PInt64 = &repeatDataSimplePathInputInfoPInt64 } if cmd.Flags().Changed("info.p_sint64") { RepeatDataSimplePathInput.Info.PSint64 = &repeatDataSimplePathInputInfoPSint64 } if cmd.Flags().Changed("info.p_sfixed64") { RepeatDataSimplePathInput.Info.PSfixed64 = &repeatDataSimplePathInputInfoPSfixed64 } if cmd.Flags().Changed("info.p_uint64") { RepeatDataSimplePathInput.Info.PUint64 = &repeatDataSimplePathInputInfoPUint64 } if cmd.Flags().Changed("info.p_fixed64") { RepeatDataSimplePathInput.Info.PFixed64 = &repeatDataSimplePathInputInfoPFixed64 } if cmd.Flags().Changed("info.p_float") { RepeatDataSimplePathInput.Info.PFloat = &repeatDataSimplePathInputInfoPFloat } if cmd.Flags().Changed("info.p_double") { RepeatDataSimplePathInput.Info.PDouble = &repeatDataSimplePathInputInfoPDouble } if cmd.Flags().Changed("info.p_bool") { RepeatDataSimplePathInput.Info.PBool = &repeatDataSimplePathInputInfoPBool } if cmd.Flags().Changed("info.p_child.p_string") { RepeatDataSimplePathInput.Info.PChild.PString = &repeatDataSimplePathInputInfoPChildPString } if cmd.Flags().Changed("info.p_child.p_float") { RepeatDataSimplePathInput.Info.PChild.PFloat = &repeatDataSimplePathInputInfoPChildPFloat } if cmd.Flags().Changed("info.p_child.p_double") { RepeatDataSimplePathInput.Info.PChild.PDouble = &repeatDataSimplePathInputInfoPChildPDouble } if cmd.Flags().Changed("info.p_child.p_bool") { RepeatDataSimplePathInput.Info.PChild.PBool = &repeatDataSimplePathInputInfoPChildPBool } if cmd.Flags().Changed("intended_binding_uri") { RepeatDataSimplePathInput.IntendedBindingUri = &repeatDataSimplePathInputIntendedBindingUri } if cmd.Flags().Changed("p_int32") { RepeatDataSimplePathInput.PInt32 = &repeatDataSimplePathInputPInt32 } if cmd.Flags().Changed("p_int64") { RepeatDataSimplePathInput.PInt64 = &repeatDataSimplePathInputPInt64 } if cmd.Flags().Changed("p_double") { RepeatDataSimplePathInput.PDouble = &repeatDataSimplePathInputPDouble } } if Verbose { printVerboseInput("Compliance", "RepeatDataSimplePath", &RepeatDataSimplePathInput) } resp, err := ComplianceClient.RepeatDataSimplePath(ctx, &RepeatDataSimplePathInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/report-session.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var ReportSessionInput genprotopb.ReportSessionRequest var ReportSessionFromFile string func init() { TestingServiceCmd.AddCommand(ReportSessionCmd) ReportSessionCmd.Flags().StringVar(&ReportSessionInput.Name, "name", "", "The session to be reported on.") ReportSessionCmd.Flags().StringVar(&ReportSessionFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var ReportSessionCmd = &cobra.Command{ Use: "report-session", Short: "Report on the status of a session. This...", Long: "Report on the status of a session. This generates a report detailing which tests have been completed, and an overall rollup.", PreRun: func(cmd *cobra.Command, args []string) { if ReportSessionFromFile == "" { } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if ReportSessionFromFile != "" { in, err = os.Open(ReportSessionFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &ReportSessionInput) if err != nil { return err } } if Verbose { printVerboseInput("Testing", "ReportSession", &ReportSessionInput) } resp, err := TestingClient.ReportSession(ctx, &ReportSessionInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/run.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "os" "os/signal" "syscall" "github.com/spf13/cobra" ) func message(err error) string { if err == nil { return "ok" } return err.Error() } func init() { config := RuntimeConfig{} runCmd := &cobra.Command{ Use: "run", Short: "Runs the showcase server", Run: func(cmd *cobra.Command, args []string) { cmuxServer := CreateAllEndpoints(config) done := make(chan os.Signal, 2) signal.Notify(done, os.Interrupt, os.Kill, syscall.SIGTERM, syscall.SIGHUP) go func() { sig := <-done stdLog.Printf("Got signal %q", sig) stdLog.Printf("Shutting down server: %s", message(cmuxServer.Shutdown())) // TODO: Delete the following line once this PR is // merged: https://github.com/soheilhy/cmux/pull/69. The issue is // that the user cannot Ctrl-C the main binary, probably due to // https://github.com/soheilhy/cmux/pull/69#issuecomment-712928041. os.Exit(1) }() stdLog.Printf("Server finished: %s", message(cmuxServer.Serve())) }, } rootCmd.AddCommand(runCmd) runCmd.Flags().StringVarP( &config.port, "port", "p", ":7469", "The port that showcase will be served on.") runCmd.Flags().StringVarP( &config.fallbackPort, "fallback-port", "f", ":1337", "The port that the fallback-proxy will be served on.") runCmd.Flags().StringVar( &config.tlsCaCert, "mtls-ca-cert", "", "The Root CA certificate path for custom mutual TLS channel.") runCmd.Flags().StringVar( &config.tlsCert, "mtls-cert", "", "The server certificate path for custom mutual TLS channel.") runCmd.Flags().StringVar( &config.tlsKey, "mtls-key", "", "The server private key path for custom mutual TLS channel.") } ================================================ FILE: cmd/gapic-showcase/search-blurbs.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var SearchBlurbsInput genprotopb.SearchBlurbsRequest var SearchBlurbsFromFile string var SearchBlurbsFollow bool var SearchBlurbsPollOperation string func init() { MessagingServiceCmd.AddCommand(SearchBlurbsCmd) SearchBlurbsCmd.Flags().StringVar(&SearchBlurbsInput.Query, "query", "", "Required. The query used to search for blurbs containing to...") SearchBlurbsCmd.Flags().StringVar(&SearchBlurbsInput.Parent, "parent", "", "The rooms or profiles to search. If unset,...") SearchBlurbsCmd.Flags().Int32Var(&SearchBlurbsInput.PageSize, "page_size", 10, "Default is 10. The maximum number of blurbs return. Server may...") SearchBlurbsCmd.Flags().StringVar(&SearchBlurbsInput.PageToken, "page_token", "", "The value of ...") SearchBlurbsCmd.Flags().StringVar(&SearchBlurbsFromFile, "from_file", "", "Absolute path to JSON file containing request payload") SearchBlurbsCmd.Flags().BoolVar(&SearchBlurbsFollow, "follow", false, "Block until the long running operation completes") MessagingServiceCmd.AddCommand(SearchBlurbsPollCmd) SearchBlurbsPollCmd.Flags().BoolVar(&SearchBlurbsFollow, "follow", false, "Block until the long running operation completes") SearchBlurbsPollCmd.Flags().StringVar(&SearchBlurbsPollOperation, "operation", "", "Required. Operation name to poll for") SearchBlurbsPollCmd.MarkFlagRequired("operation") } var SearchBlurbsCmd = &cobra.Command{ Use: "search-blurbs", Short: "This method searches through all blurbs across...", Long: "This method searches through all blurbs across all rooms and profiles for blurbs containing to words found in the query. Only posts that contain an...", PreRun: func(cmd *cobra.Command, args []string) { if SearchBlurbsFromFile == "" { cmd.MarkFlagRequired("query") } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if SearchBlurbsFromFile != "" { in, err = os.Open(SearchBlurbsFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &SearchBlurbsInput) if err != nil { return err } } if Verbose { printVerboseInput("Messaging", "SearchBlurbs", &SearchBlurbsInput) } resp, err := MessagingClient.SearchBlurbs(ctx, &SearchBlurbsInput) if err != nil { return err } if !SearchBlurbsFollow { var s interface{} s = resp.Name() if OutputJSON { d := make(map[string]string) d["operation"] = resp.Name() s = d } printMessage(s) return err } result, err := resp.Wait(ctx) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(result) return err }, } var SearchBlurbsPollCmd = &cobra.Command{ Use: "poll-search-blurbs", Short: "Poll the status of a SearchBlurbsOperation by name", RunE: func(cmd *cobra.Command, args []string) (err error) { op := MessagingClient.SearchBlurbsOperation(SearchBlurbsPollOperation) if SearchBlurbsFollow { resp, err := op.Wait(ctx) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err } resp, err := op.Poll(ctx) if err != nil { return err } else if resp != nil { if Verbose { fmt.Print("Output: ") } printMessage(resp) return } if op.Done() { fmt.Println(fmt.Sprintf("Operation %s is done", op.Name())) } else { fmt.Println(fmt.Sprintf("Operation %s not done", op.Name())) } return err }, } ================================================ FILE: cmd/gapic-showcase/send-blurbs.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "bufio" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var SendBlurbsFromFile string func init() { MessagingServiceCmd.AddCommand(SendBlurbsCmd) SendBlurbsCmd.Flags().StringVar(&SendBlurbsFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var SendBlurbsCmd = &cobra.Command{ Use: "send-blurbs", Short: "This is a stream to create multiple blurbs. If an...", Long: "This is a stream to create multiple blurbs. If an invalid blurb is requested to be created, the stream will close with an error.", PreRun: func(cmd *cobra.Command, args []string) { }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if SendBlurbsFromFile != "" { in, err = os.Open(SendBlurbsFromFile) if err != nil { return err } defer in.Close() } stream, err := MessagingClient.SendBlurbs(ctx) if err != nil { return err } if Verbose { fmt.Println("Client stream open. Close with ctrl+D.") } var SendBlurbsInput genprotopb.CreateBlurbRequest scanner := bufio.NewScanner(in) for scanner.Scan() { input := scanner.Text() if input == "" { continue } err = jsonpb.UnmarshalString(input, &SendBlurbsInput) if err != nil { return err } err = stream.Send(&SendBlurbsInput) if err != nil { return err } } if err = scanner.Err(); err != nil { return err } resp, err := stream.CloseAndRecv() if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/sequence_service.go ================================================ // Code generated. DO NOT EDIT. package main import ( "fmt" "github.com/spf13/cobra" "github.com/spf13/viper" "golang.org/x/oauth2" "google.golang.org/api/option" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" gapic "github.com/googleapis/gapic-showcase/client" ) var SequenceConfig *viper.Viper var SequenceClient *gapic.SequenceClient var SequenceSubCommands []string = []string{ "create-sequence", "create-streaming-sequence", "get-sequence-report", "get-streaming-sequence-report", "attempt-sequence", "attempt-streaming-sequence", } func init() { rootCmd.AddCommand(SequenceServiceCmd) SequenceConfig = viper.New() SequenceConfig.SetEnvPrefix("GAPIC-SHOWCASE_SEQUENCE") SequenceConfig.AutomaticEnv() SequenceServiceCmd.PersistentFlags().Bool("insecure", false, "Make insecure client connection. Or use GAPIC-SHOWCASE_SEQUENCE_INSECURE. Must be used with \"address\" option") SequenceConfig.BindPFlag("insecure", SequenceServiceCmd.PersistentFlags().Lookup("insecure")) SequenceConfig.BindEnv("insecure") SequenceServiceCmd.PersistentFlags().String("address", "", "Set API address used by client. Or use GAPIC-SHOWCASE_SEQUENCE_ADDRESS.") SequenceConfig.BindPFlag("address", SequenceServiceCmd.PersistentFlags().Lookup("address")) SequenceConfig.BindEnv("address") SequenceServiceCmd.PersistentFlags().String("token", "", "Set Bearer token used by the client. Or use GAPIC-SHOWCASE_SEQUENCE_TOKEN.") SequenceConfig.BindPFlag("token", SequenceServiceCmd.PersistentFlags().Lookup("token")) SequenceConfig.BindEnv("token") SequenceServiceCmd.PersistentFlags().String("api_key", "", "Set API Key used by the client. Or use GAPIC-SHOWCASE_SEQUENCE_API_KEY.") SequenceConfig.BindPFlag("api_key", SequenceServiceCmd.PersistentFlags().Lookup("api_key")) SequenceConfig.BindEnv("api_key") } var SequenceServiceCmd = &cobra.Command{ Use: "sequence", Short: "A service that enables testing of unary and...", Long: "A service that enables testing of unary and server streaming calls by specifying a specific, predictable sequence of responses from the service", ValidArgs: SequenceSubCommands, PersistentPreRunE: func(cmd *cobra.Command, args []string) (err error) { var opts []option.ClientOption address := SequenceConfig.GetString("address") if address != "" { opts = append(opts, option.WithEndpoint(address)) } if SequenceConfig.GetBool("insecure") { if address == "" { return fmt.Errorf("Missing address to use with insecure connection") } conn, err := grpc.Dial(address, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { return err } opts = append(opts, option.WithGRPCConn(conn)) } if token := SequenceConfig.GetString("token"); token != "" { opts = append(opts, option.WithTokenSource(oauth2.StaticTokenSource( &oauth2.Token{ AccessToken: token, TokenType: "Bearer", }))) } if key := SequenceConfig.GetString("api_key"); key != "" { opts = append(opts, option.WithAPIKey(key)) } SequenceClient, err = gapic.NewSequenceClient(ctx, opts...) return }, } ================================================ FILE: cmd/gapic-showcase/stream-blurbs.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "io" "os" timestamppb "google.golang.org/protobuf/types/known/timestamppb" ) var StreamBlurbsInput genprotopb.StreamBlurbsRequest var StreamBlurbsFromFile string func init() { MessagingServiceCmd.AddCommand(StreamBlurbsCmd) StreamBlurbsInput.ExpireTime = new(timestamppb.Timestamp) StreamBlurbsCmd.Flags().StringVar(&StreamBlurbsInput.Name, "name", "", "Required. The resource name of a chat room or user profile...") StreamBlurbsCmd.Flags().Int64Var(&StreamBlurbsInput.ExpireTime.Seconds, "expire_time.seconds", 0, "Represents seconds of UTC time since Unix epoch ...") StreamBlurbsCmd.Flags().Int32Var(&StreamBlurbsInput.ExpireTime.Nanos, "expire_time.nanos", 0, "Non-negative fractions of a second at nanosecond...") StreamBlurbsCmd.Flags().StringVar(&StreamBlurbsFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var StreamBlurbsCmd = &cobra.Command{ Use: "stream-blurbs", Short: "This returns a stream that emits the blurbs that...", Long: "This returns a stream that emits the blurbs that are created for a particular chat room or user profile.", PreRun: func(cmd *cobra.Command, args []string) { if StreamBlurbsFromFile == "" { cmd.MarkFlagRequired("name") } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if StreamBlurbsFromFile != "" { in, err = os.Open(StreamBlurbsFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &StreamBlurbsInput) if err != nil { return err } } if Verbose { printVerboseInput("Messaging", "StreamBlurbs", &StreamBlurbsInput) } resp, err := MessagingClient.StreamBlurbs(ctx, &StreamBlurbsInput) if err != nil { return err } var item *genprotopb.StreamBlurbsResponse for { item, err = resp.Recv() if err != nil { break } if Verbose { fmt.Print("Output: ") } printMessage(item) } if err == io.EOF { return nil } return err }, } ================================================ FILE: cmd/gapic-showcase/testing_service.go ================================================ // Code generated. DO NOT EDIT. package main import ( "fmt" "github.com/spf13/cobra" "github.com/spf13/viper" "golang.org/x/oauth2" "google.golang.org/api/option" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" gapic "github.com/googleapis/gapic-showcase/client" ) var TestingConfig *viper.Viper var TestingClient *gapic.TestingClient var TestingSubCommands []string = []string{ "create-session", "get-session", "list-sessions", "delete-session", "report-session", "list-tests", "delete-test", "verify-test", } func init() { rootCmd.AddCommand(TestingServiceCmd) TestingConfig = viper.New() TestingConfig.SetEnvPrefix("GAPIC-SHOWCASE_TESTING") TestingConfig.AutomaticEnv() TestingServiceCmd.PersistentFlags().Bool("insecure", false, "Make insecure client connection. Or use GAPIC-SHOWCASE_TESTING_INSECURE. Must be used with \"address\" option") TestingConfig.BindPFlag("insecure", TestingServiceCmd.PersistentFlags().Lookup("insecure")) TestingConfig.BindEnv("insecure") TestingServiceCmd.PersistentFlags().String("address", "", "Set API address used by client. Or use GAPIC-SHOWCASE_TESTING_ADDRESS.") TestingConfig.BindPFlag("address", TestingServiceCmd.PersistentFlags().Lookup("address")) TestingConfig.BindEnv("address") TestingServiceCmd.PersistentFlags().String("token", "", "Set Bearer token used by the client. Or use GAPIC-SHOWCASE_TESTING_TOKEN.") TestingConfig.BindPFlag("token", TestingServiceCmd.PersistentFlags().Lookup("token")) TestingConfig.BindEnv("token") TestingServiceCmd.PersistentFlags().String("api_key", "", "Set API Key used by the client. Or use GAPIC-SHOWCASE_TESTING_API_KEY.") TestingConfig.BindPFlag("api_key", TestingServiceCmd.PersistentFlags().Lookup("api_key")) TestingConfig.BindEnv("api_key") } var TestingServiceCmd = &cobra.Command{ Use: "testing", Short: "A service to facilitate running discrete sets of...", Long: "A service to facilitate running discrete sets of tests against Showcase. Adding this comment with special characters for comment formatting tests: ...", ValidArgs: TestingSubCommands, PersistentPreRunE: func(cmd *cobra.Command, args []string) (err error) { var opts []option.ClientOption address := TestingConfig.GetString("address") if address != "" { opts = append(opts, option.WithEndpoint(address)) } if TestingConfig.GetBool("insecure") { if address == "" { return fmt.Errorf("Missing address to use with insecure connection") } conn, err := grpc.Dial(address, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { return err } opts = append(opts, option.WithGRPCConn(conn)) } if token := TestingConfig.GetString("token"); token != "" { opts = append(opts, option.WithTokenSource(oauth2.StaticTokenSource( &oauth2.Token{ AccessToken: token, TokenType: "Bearer", }))) } if key := TestingConfig.GetString("api_key"); key != "" { opts = append(opts, option.WithAPIKey(key)) } TestingClient, err = gapic.NewTestingClient(ctx, opts...) return }, } ================================================ FILE: cmd/gapic-showcase/update-blurb.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" fieldmaskpb "google.golang.org/protobuf/types/known/fieldmaskpb" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var UpdateBlurbInput genprotopb.UpdateBlurbRequest var UpdateBlurbFromFile string var UpdateBlurbInputBlurbContent string var UpdateBlurbInputBlurbContentImage genprotopb.Blurb_Image var UpdateBlurbInputBlurbContentText genprotopb.Blurb_Text var UpdateBlurbInputBlurbLegacyId string var UpdateBlurbInputBlurbLegacyIdLegacyRoomId genprotopb.Blurb_LegacyRoomId var UpdateBlurbInputBlurbLegacyIdLegacyUserId genprotopb.Blurb_LegacyUserId func init() { MessagingServiceCmd.AddCommand(UpdateBlurbCmd) UpdateBlurbInput.Blurb = new(genprotopb.Blurb) UpdateBlurbInput.UpdateMask = new(fieldmaskpb.FieldMask) UpdateBlurbCmd.Flags().StringVar(&UpdateBlurbInput.Blurb.Name, "blurb.name", "", "The resource name of the chat room.") UpdateBlurbCmd.Flags().StringVar(&UpdateBlurbInput.Blurb.User, "blurb.user", "", "Required. The resource name of the blurb's author.") UpdateBlurbCmd.Flags().StringVar(&UpdateBlurbInputBlurbContentText.Text, "blurb.content.text", "", "The textual content of this blurb.") UpdateBlurbCmd.Flags().BytesHexVar(&UpdateBlurbInputBlurbContentImage.Image, "blurb.content.image", []byte{}, "The image content of this blurb.") UpdateBlurbCmd.Flags().StringVar(&UpdateBlurbInputBlurbLegacyIdLegacyRoomId.LegacyRoomId, "blurb.legacy_id.legacy_room_id", "", "The legacy id of the room. This field is used to...") UpdateBlurbCmd.Flags().StringVar(&UpdateBlurbInputBlurbLegacyIdLegacyUserId.LegacyUserId, "blurb.legacy_id.legacy_user_id", "", "The legacy id of the user. This field is used to...") UpdateBlurbCmd.Flags().StringSliceVar(&UpdateBlurbInput.UpdateMask.Paths, "update_mask.paths", []string{}, "The set of field mask paths.") UpdateBlurbCmd.Flags().StringVar(&UpdateBlurbInputBlurbContent, "blurb.content", "", "Choices: text, image") UpdateBlurbCmd.Flags().StringVar(&UpdateBlurbInputBlurbLegacyId, "blurb.legacy_id", "", "Choices: legacy_room_id, legacy_user_id") UpdateBlurbCmd.Flags().StringVar(&UpdateBlurbFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var UpdateBlurbCmd = &cobra.Command{ Use: "update-blurb", Short: "Updates a blurb.", Long: "Updates a blurb.", PreRun: func(cmd *cobra.Command, args []string) { if UpdateBlurbFromFile == "" { cmd.MarkFlagRequired("blurb.user") cmd.MarkFlagRequired("blurb.content") cmd.MarkFlagRequired("blurb.legacy_id") } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if UpdateBlurbFromFile != "" { in, err = os.Open(UpdateBlurbFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &UpdateBlurbInput) if err != nil { return err } } else { switch UpdateBlurbInputBlurbContent { case "image": UpdateBlurbInput.Blurb.Content = &UpdateBlurbInputBlurbContentImage case "text": UpdateBlurbInput.Blurb.Content = &UpdateBlurbInputBlurbContentText default: return fmt.Errorf("Missing oneof choice for blurb.content") } switch UpdateBlurbInputBlurbLegacyId { case "legacy_room_id": UpdateBlurbInput.Blurb.LegacyId = &UpdateBlurbInputBlurbLegacyIdLegacyRoomId case "legacy_user_id": UpdateBlurbInput.Blurb.LegacyId = &UpdateBlurbInputBlurbLegacyIdLegacyUserId default: return fmt.Errorf("Missing oneof choice for blurb.legacy_id") } } if Verbose { printVerboseInput("Messaging", "UpdateBlurb", &UpdateBlurbInput) } resp, err := MessagingClient.UpdateBlurb(ctx, &UpdateBlurbInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/update-room.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" fieldmaskpb "google.golang.org/protobuf/types/known/fieldmaskpb" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var UpdateRoomInput genprotopb.UpdateRoomRequest var UpdateRoomFromFile string func init() { MessagingServiceCmd.AddCommand(UpdateRoomCmd) UpdateRoomInput.Room = new(genprotopb.Room) UpdateRoomInput.UpdateMask = new(fieldmaskpb.FieldMask) UpdateRoomCmd.Flags().StringVar(&UpdateRoomInput.Room.Name, "room.name", "", "The resource name of the chat room.") UpdateRoomCmd.Flags().StringVar(&UpdateRoomInput.Room.DisplayName, "room.display_name", "", "Required. The human readable name of the chat room.") UpdateRoomCmd.Flags().StringVar(&UpdateRoomInput.Room.Description, "room.description", "", "The description of the chat room.") UpdateRoomCmd.Flags().StringSliceVar(&UpdateRoomInput.UpdateMask.Paths, "update_mask.paths", []string{}, "The set of field mask paths.") UpdateRoomCmd.Flags().StringVar(&UpdateRoomFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var UpdateRoomCmd = &cobra.Command{ Use: "update-room", Short: "Updates a room.", Long: "Updates a room.", PreRun: func(cmd *cobra.Command, args []string) { if UpdateRoomFromFile == "" { cmd.MarkFlagRequired("room.display_name") } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if UpdateRoomFromFile != "" { in, err = os.Open(UpdateRoomFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &UpdateRoomInput) if err != nil { return err } } if Verbose { printVerboseInput("Messaging", "UpdateRoom", &UpdateRoomInput) } resp, err := MessagingClient.UpdateRoom(ctx, &UpdateRoomInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/update-user.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" fieldmaskpb "google.golang.org/protobuf/types/known/fieldmaskpb" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var UpdateUserInput genprotopb.UpdateUserRequest var UpdateUserFromFile string var updateUserInputUserAge int32 var updateUserInputUserHeightFeet float64 var updateUserInputUserNickname string var updateUserInputUserEnableNotifications bool func init() { IdentityServiceCmd.AddCommand(UpdateUserCmd) UpdateUserInput.User = new(genprotopb.User) UpdateUserInput.UpdateMask = new(fieldmaskpb.FieldMask) UpdateUserCmd.Flags().StringVar(&UpdateUserInput.User.Name, "user.name", "", "The resource name of the user.") UpdateUserCmd.Flags().StringVar(&UpdateUserInput.User.DisplayName, "user.display_name", "", "Required. The display_name of the user.") UpdateUserCmd.Flags().StringVar(&UpdateUserInput.User.Email, "user.email", "", "Required. The email address of the user.") UpdateUserCmd.Flags().Int32Var(&updateUserInputUserAge, "user.age", 0, "The age of the user in years.") UpdateUserCmd.Flags().Float64Var(&updateUserInputUserHeightFeet, "user.height_feet", 0.0, "The height of the user in feet.") UpdateUserCmd.Flags().StringVar(&updateUserInputUserNickname, "user.nickname", "", "The nickname of the user. (--...") UpdateUserCmd.Flags().BoolVar(&updateUserInputUserEnableNotifications, "user.enable_notifications", false, "Enables the receiving of notifications. The...") UpdateUserCmd.Flags().StringSliceVar(&UpdateUserInput.UpdateMask.Paths, "update_mask.paths", []string{}, "The set of field mask paths.") UpdateUserCmd.Flags().StringVar(&UpdateUserFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var UpdateUserCmd = &cobra.Command{ Use: "update-user", Short: "Updates a user.", Long: "Updates a user.", PreRun: func(cmd *cobra.Command, args []string) { if UpdateUserFromFile == "" { cmd.MarkFlagRequired("user.display_name") cmd.MarkFlagRequired("user.email") } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if UpdateUserFromFile != "" { in, err = os.Open(UpdateUserFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &UpdateUserInput) if err != nil { return err } } else { if cmd.Flags().Changed("user.age") { UpdateUserInput.User.Age = &updateUserInputUserAge } if cmd.Flags().Changed("user.height_feet") { UpdateUserInput.User.HeightFeet = &updateUserInputUserHeightFeet } if cmd.Flags().Changed("user.nickname") { UpdateUserInput.User.Nickname = &updateUserInputUserNickname } if cmd.Flags().Changed("user.enable_notifications") { UpdateUserInput.User.EnableNotifications = &updateUserInputUserEnableNotifications } } if Verbose { printVerboseInput("Identity", "UpdateUser", &UpdateUserInput) } resp, err := IdentityClient.UpdateUser(ctx, &UpdateUserInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/verify-enum.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" "strings" ) var VerifyEnumInput genprotopb.EnumResponse var VerifyEnumFromFile string var VerifyEnumInputContinent string func init() { ComplianceServiceCmd.AddCommand(VerifyEnumCmd) VerifyEnumInput.Request = new(genprotopb.EnumRequest) VerifyEnumCmd.Flags().BoolVar(&VerifyEnumInput.Request.UnknownEnum, "request.unknown_enum", false, "Whether the client is requesting a new, unknown...") VerifyEnumCmd.Flags().StringVar(&VerifyEnumInputContinent, "continent", "", "The actual enum the server provided.") VerifyEnumCmd.Flags().StringVar(&VerifyEnumFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var VerifyEnumCmd = &cobra.Command{ Use: "verify-enum", Short: "This method is used to verify that clients can...", Long: "This method is used to verify that clients can round-trip enum values, which is particularly important for unknown enum values over REST....", PreRun: func(cmd *cobra.Command, args []string) { if VerifyEnumFromFile == "" { } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if VerifyEnumFromFile != "" { in, err = os.Open(VerifyEnumFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &VerifyEnumInput) if err != nil { return err } } else { VerifyEnumInput.Continent = genprotopb.Continent(genprotopb.Continent_value[strings.ToUpper(VerifyEnumInputContinent)]) } if Verbose { printVerboseInput("Compliance", "VerifyEnum", &VerifyEnumInput) } resp, err := ComplianceClient.VerifyEnum(ctx, &VerifyEnumInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/verify-test.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" ) var VerifyTestInput genprotopb.VerifyTestRequest var VerifyTestFromFile string func init() { TestingServiceCmd.AddCommand(VerifyTestCmd) VerifyTestCmd.Flags().StringVar(&VerifyTestInput.Name, "name", "", "The test to have an answer registered to it.") VerifyTestCmd.Flags().BytesHexVar(&VerifyTestInput.Answer, "answer", []byte{}, "The answer from the test.") VerifyTestCmd.Flags().StringVar(&VerifyTestFromFile, "from_file", "", "Absolute path to JSON file containing request payload") } var VerifyTestCmd = &cobra.Command{ Use: "verify-test", Short: "Register a response to a test. In cases where a...", Long: "Register a response to a test. In cases where a test involves registering a final answer at the end of the test, this method provides the means to...", PreRun: func(cmd *cobra.Command, args []string) { if VerifyTestFromFile == "" { } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if VerifyTestFromFile != "" { in, err = os.Open(VerifyTestFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &VerifyTestInput) if err != nil { return err } } if Verbose { printVerboseInput("Testing", "VerifyTest", &VerifyTestInput) } resp, err := TestingClient.VerifyTest(ctx, &VerifyTestInput) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err }, } ================================================ FILE: cmd/gapic-showcase/version.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "strings" root "github.com/googleapis/gapic-showcase" ) func init() { // Make roots version option only emit the version. This is used in Actions. // The template looks weird on purpose. Leaving as a single line causes the // output to append an extra character. rootCmd.Version = strings.TrimSpace(root.Version) rootCmd.SetVersionTemplate( `{{printf "%s" .Version}}`) } ================================================ FILE: cmd/gapic-showcase/wait.go ================================================ // Code generated. DO NOT EDIT. package main import ( "github.com/spf13/cobra" anypb "google.golang.org/protobuf/types/known/anypb" durationpb "google.golang.org/protobuf/types/known/durationpb" "fmt" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/golang/protobuf/jsonpb" "os" statuspb "google.golang.org/genproto/googleapis/rpc/status" timestamppb "google.golang.org/protobuf/types/known/timestamppb" ) var WaitInput genprotopb.WaitRequest var WaitFromFile string var WaitFollow bool var WaitPollOperation string var WaitInputEnd string var WaitInputEndEndTime genprotopb.WaitRequest_EndTime var WaitInputEndTtl genprotopb.WaitRequest_Ttl var WaitInputResponse string var WaitInputResponseError genprotopb.WaitRequest_Error var WaitInputResponseSuccess genprotopb.WaitRequest_Success var WaitInputResponseErrorDetails []string func init() { EchoServiceCmd.AddCommand(WaitCmd) WaitInputEndEndTime.EndTime = new(timestamppb.Timestamp) WaitInputEndTtl.Ttl = new(durationpb.Duration) WaitInputResponseError.Error = new(statuspb.Status) WaitInputResponseSuccess.Success = new(genprotopb.WaitResponse) WaitCmd.Flags().Int64Var(&WaitInputEndEndTime.EndTime.Seconds, "end.end_time.seconds", 0, "Represents seconds of UTC time since Unix epoch ...") WaitCmd.Flags().Int32Var(&WaitInputEndEndTime.EndTime.Nanos, "end.end_time.nanos", 0, "Non-negative fractions of a second at nanosecond...") WaitCmd.Flags().Int64Var(&WaitInputEndTtl.Ttl.Seconds, "end.ttl.seconds", 0, "Signed seconds of the span of time. Must be from...") WaitCmd.Flags().Int32Var(&WaitInputEndTtl.Ttl.Nanos, "end.ttl.nanos", 0, "Signed fractions of a second at nanosecond...") WaitCmd.Flags().Int32Var(&WaitInputResponseError.Error.Code, "response.error.code", 0, "The status code, which should be an enum value of...") WaitCmd.Flags().StringVar(&WaitInputResponseError.Error.Message, "response.error.message", "", "A developer-facing error message, which should be...") WaitCmd.Flags().StringArrayVar(&WaitInputResponseErrorDetails, "response.error.details", []string{}, "A list of messages that carry the error details. ...") WaitCmd.Flags().StringVar(&WaitInputResponseSuccess.Success.Content, "response.success.content", "", "This content of the result.") WaitCmd.Flags().StringVar(&WaitInputEnd, "end", "", "Choices: end_time, ttl") WaitCmd.Flags().StringVar(&WaitInputResponse, "response", "", "Choices: error, success") WaitCmd.Flags().StringVar(&WaitFromFile, "from_file", "", "Absolute path to JSON file containing request payload") WaitCmd.Flags().BoolVar(&WaitFollow, "follow", false, "Block until the long running operation completes") EchoServiceCmd.AddCommand(WaitPollCmd) WaitPollCmd.Flags().BoolVar(&WaitFollow, "follow", false, "Block until the long running operation completes") WaitPollCmd.Flags().StringVar(&WaitPollOperation, "operation", "", "Required. Operation name to poll for") WaitPollCmd.MarkFlagRequired("operation") } var WaitCmd = &cobra.Command{ Use: "wait", Short: "This method will wait for the requested amount of...", Long: "This method will wait for the requested amount of time and then return. This method showcases how a client handles a request timeout.", PreRun: func(cmd *cobra.Command, args []string) { if WaitFromFile == "" { cmd.MarkFlagRequired("end") cmd.MarkFlagRequired("response") } }, RunE: func(cmd *cobra.Command, args []string) (err error) { in := os.Stdin if WaitFromFile != "" { in, err = os.Open(WaitFromFile) if err != nil { return err } defer in.Close() err = jsonpb.Unmarshal(in, &WaitInput) if err != nil { return err } } else { switch WaitInputEnd { case "end_time": WaitInput.End = &WaitInputEndEndTime case "ttl": WaitInput.End = &WaitInputEndTtl default: return fmt.Errorf("Missing oneof choice for end") } switch WaitInputResponse { case "error": WaitInput.Response = &WaitInputResponseError case "success": WaitInput.Response = &WaitInputResponseSuccess default: return fmt.Errorf("Missing oneof choice for response") } } // unmarshal JSON strings into slice of structs for _, item := range WaitInputResponseErrorDetails { tmp := anypb.Any{} err = jsonpb.UnmarshalString(item, &tmp) if err != nil { return } WaitInputResponseError.Error.Details = append(WaitInputResponseError.Error.Details, &tmp) } if Verbose { printVerboseInput("Echo", "Wait", &WaitInput) } resp, err := EchoClient.Wait(ctx, &WaitInput) if err != nil { return err } if !WaitFollow { var s interface{} s = resp.Name() if OutputJSON { d := make(map[string]string) d["operation"] = resp.Name() s = d } printMessage(s) return err } result, err := resp.Wait(ctx) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(result) return err }, } var WaitPollCmd = &cobra.Command{ Use: "poll-wait", Short: "Poll the status of a WaitOperation by name", RunE: func(cmd *cobra.Command, args []string) (err error) { op := EchoClient.WaitOperation(WaitPollOperation) if WaitFollow { resp, err := op.Wait(ctx) if err != nil { return err } if Verbose { fmt.Print("Output: ") } printMessage(resp) return err } resp, err := op.Poll(ctx) if err != nil { return err } else if resp != nil { if Verbose { fmt.Print("Output: ") } printMessage(resp) return } if op.Done() { fmt.Println(fmt.Sprintf("Operation %s is done", op.Name())) } else { fmt.Println(fmt.Sprintf("Operation %s not done", op.Name())) } return err }, } ================================================ FILE: go.mod ================================================ module github.com/googleapis/gapic-showcase require ( cloud.google.com/go/iam v1.9.0 cloud.google.com/go/longrunning v0.11.0 github.com/ghodss/yaml v1.0.0 github.com/golang/protobuf v1.5.4 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 github.com/googleapis/gax-go/v2 v2.22.0 github.com/googleapis/grpc-fallback-go v0.1.4 github.com/gorilla/mux v1.8.1 github.com/iancoleman/strcase v0.3.0 github.com/soheilhy/cmux v0.1.5 github.com/spf13/cobra v1.10.2 github.com/spf13/viper v1.21.0 golang.org/x/oauth2 v0.36.0 golang.org/x/sync v0.20.0 google.golang.org/api v0.276.0 google.golang.org/genproto v0.0.0-20260414002931-afd174a4e478 google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 google.golang.org/grpc v1.80.0 google.golang.org/protobuf v1.36.11 ) require ( cloud.google.com/go v0.123.0 // indirect cloud.google.com/go/auth v0.20.0 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect cloud.google.com/go/compute/metadata v0.9.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/google/s2a-go v0.1.9 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/sagikazarmark/locafero v0.12.0 // indirect github.com/spf13/afero v1.15.0 // indirect github.com/spf13/cast v1.10.0 // indirect github.com/spf13/pflag v1.0.10 // indirect github.com/subosito/gotenv v1.6.0 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.67.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 // indirect go.opentelemetry.io/otel v1.43.0 // indirect go.opentelemetry.io/otel/metric v1.43.0 // indirect go.opentelemetry.io/otel/trace v1.43.0 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/crypto v0.49.0 // indirect golang.org/x/net v0.52.0 // indirect golang.org/x/sys v0.42.0 // indirect golang.org/x/text v0.35.0 // indirect golang.org/x/time v0.15.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) go 1.25.0 toolchain go1.26.2 ================================================ FILE: go.sum ================================================ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= cloud.google.com/go/auth v0.20.0 h1:kXTssoVb4azsVDoUiF8KvxAqrsQcQtB53DcSgta74CA= cloud.google.com/go/auth v0.20.0/go.mod h1:942/yi/itH1SsmpyrbnTMDgGfdy2BUqIKyd0cyYLc5Q= cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= cloud.google.com/go/iam v1.9.0 h1:89wyjxT6DL4b5rk/Nk8eBC9DHqf+JiMstrn5IEYxFw4= cloud.google.com/go/iam v1.9.0/go.mod h1:KP+nKGugNJW4LcLx1uEZcq1ok5sQHFaQehQNl4QDgV4= cloud.google.com/go/longrunning v0.11.0 h1:fE4XVLJQj+gRnw1HrbDyQXXgC0aiqY3wxP7DDU4cWk0= cloud.google.com/go/longrunning v0.11.0/go.mod h1:8nqFBPOO1U/XkhWl0I19AMZEphrHi73VNABIpKYaTwM= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.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/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/Tv1FZd4SCg8axKApyNyRsAt/w= github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/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.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA= github.com/envoyproxy/go-control-plane/envoy v1.36.0 h1:yg/JjO5E7ubRyKX3m07GF3reDNEnfOboJ0QySbH736g= github.com/envoyproxy/go-control-plane/envoy v1.36.0/go.mod h1:ty89S1YCCVruQAm9OtKeEkQLTb+Lkz0k8v9W0Oxsv98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v1.3.0 h1:TvGH1wof4H33rezVKWSpqKz5NXWg5VPuZ0uONDT6eb4= github.com/envoyproxy/protoc-gen-validate v1.3.0/go.mod h1:HvYl7zwPa5mffgyeTUHA9zHIH36nmrm7oCbo4YKoSWA= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 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.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.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.14 h1:yh8ncqsbUY4shRD5dA6RlzjJaT4hi3kII+zYw8wmLb8= github.com/googleapis/enterprise-certificate-proxy v0.3.14/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg= github.com/googleapis/gax-go/v2 v2.22.0 h1:PjIWBpgGIVKGoCXuiCoP64altEJCj3/Ei+kSU5vlZD4= github.com/googleapis/gax-go/v2 v2.22.0/go.mod h1:irWBbALSr0Sk3qlqb9SyJ1h68WjgeFuiOzI4Rqw5+aY= github.com/googleapis/grpc-fallback-go v0.1.4 h1:tEDqZnKGKQpYrmEuu3VVBTw3pijHJsKz/Lu2U0L9AV0= github.com/googleapis/grpc-fallback-go v0.1.4/go.mod h1:R7P0bK21nlCMc4hdtiwmXMzKXThllMim0cUZvClg6XQ= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= 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/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4= github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.67.0 h1:yI1/OhfEPy7J9eoa6Sj051C7n5dvpj0QX8g4sRchg04= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.67.0/go.mod h1:NoUCKYWK+3ecatC4HjkRktREheMeEtrXoQxrqYFeHSc= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 h1:OyrsyzuttWTSur2qN/Lm0m2a8yqyIjUVBZcxFPuXq2o= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0/go.mod h1:C2NGBr+kAB4bk3xtMXfZ94gqFDtg/GkI7e9zqGh5Beg= go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= 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-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/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= 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.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= 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= gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= google.golang.org/api v0.276.0 h1:nVArUtfLEihtW+b0DdcqRGK1xoEm2+ltAihyztq7MKY= google.golang.org/api v0.276.0/go.mod h1:Fnag/EWUPIcJXuIkP1pjoTgS5vdxlk3eeemL7Do6bvw= 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-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20201008135153-289734e2e40c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20260414002931-afd174a4e478 h1:aLsVTW0lZ8+IY5u/ERjZSCvAmhuR7slKzyha3YikDNA= google.golang.org/genproto v0.0.0-20260414002931-afd174a4e478/go.mod h1:YJAzKjfHIUHb9T+bfu8L7mthAp7VVXQBUs1PLdBWS7M= google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 h1:yQugLulqltosq0B/f8l4w9VryjV+N/5gcW0jQ3N8Qec= google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478/go.mod h1:C6ADNqOxbgdUUeRTU+LCHDPB9ttAMCTff6auwCVa4uc= google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 h1:RmoJA1ujG+/lRGNfUnOMfhCy5EipVMyvUE+KNbPbTlw= google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= 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.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.0/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 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= ================================================ FILE: renovate.json ================================================ { "extends": [ "config:base", ":disableDependencyDashboard", "group:all", "schedule:weekly", ":semanticCommitTypeAll(chore)" ], "pinVersions": false, "bazel": { "managerBranchPrefix": "bazel-" }, "packageRules": [ { "matchPackagePatterns": [ "com_google_protobuf" ], "enabled": false } ], "golang": { "postUpdateOptions": [ "gomodTidy" ], "managerBranchPrefix": "golang-" }, "ignoreDeps": [ "google.golang.org/grpc" ], "rebaseWhen": "behind-base-branch", "labels": [ "automerge" ], "timezone": "America/Los_Angeles" } ================================================ FILE: schema/google/showcase/v1beta1/BUILD.bazel ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Provides proto_library target Exports grpc service config """ load ("@rules_proto//proto:defs.bzl", "proto_library") # This is an API workspace, having public visibility by default makes perfect sense. package(default_visibility = ["//visibility:public"]) exports_files(glob(["*.json"]) + glob(["*.yaml"])) ## # the proto files wrapped with dependencies # proto_library( name = "showcase_proto", srcs = [":compliance.proto", ":echo.proto", ":identity.proto", ":messaging.proto", ":rest_error.proto", ":sequence.proto", ":testing.proto" ], deps = [ "@com_google_googleapis//google/api:annotations_proto", "@com_google_googleapis//google/api:client_proto", "@com_google_googleapis//google/api:field_behavior_proto", "@com_google_googleapis//google/api:field_info_proto", "@com_google_googleapis//google/api:resource_proto", "@com_google_googleapis//google/api:routing_proto", "@com_google_googleapis//google/longrunning:operations_proto", "@com_google_googleapis//google/rpc:code_proto", "@com_google_googleapis//google/rpc:error_details_proto", "@com_google_googleapis//google/rpc:status_proto", "@com_google_protobuf//:any_proto", "@com_google_protobuf//:duration_proto", "@com_google_protobuf//:empty_proto", "@com_google_protobuf//:field_mask_proto", "@com_google_protobuf//:timestamp_proto", ] ) ================================================ FILE: schema/google/showcase/v1beta1/compliance.proto ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. syntax = "proto3"; import "google/api/annotations.proto"; import "google/api/client.proto"; package google.showcase.v1beta1; option go_package = "github.com/googleapis/gapic-showcase/server/genproto"; option java_package = "com.google.showcase.v1beta1"; option java_multiple_files = true; option ruby_package = "Google::Showcase::V1beta1"; // This service is used to test that GAPICs implement various REST-related features correctly. This mostly means transcoding proto3 requests to REST format // correctly for various types of HTTP annotations, but it also includes verifying that unknown (numeric) enums received by clients can be round-tripped // correctly. service Compliance { // This service is meant to only run locally on the port 7469 (keypad digits // for "show"). option (google.api.default_host) = "localhost:7469"; // This method echoes the ComplianceData request. This method exercises // sending the entire request object in the REST body. rpc RepeatDataBody(RepeatRequest) returns (RepeatResponse) { option (google.api.http) = { post: "/v1beta1/repeat:body" body: "*" }; } // This method echoes the ComplianceData request. This method exercises // sending the a message-type field in the REST body. Per AIP-127, only // top-level, non-repeated fields can be sent this way. rpc RepeatDataBodyInfo(RepeatRequest) returns (RepeatResponse) { option (google.api.http) = { post: "/v1beta1/repeat:bodyinfo" body: "info" }; } // This method echoes the ComplianceData request. This method exercises // sending all request fields as query parameters. rpc RepeatDataQuery(RepeatRequest) returns (RepeatResponse) { option (google.api.http) = { get: "/v1beta1/repeat:query" }; } // This method echoes the ComplianceData request. This method exercises // sending some parameters as "simple" path variables (i.e., of the form // "/bar/{foo}" rather than "/{foo=bar/*}"), and the rest as query parameters. rpc RepeatDataSimplePath(RepeatRequest) returns (RepeatResponse) { option (google.api.http) = { get: "/v1beta1/repeat/{info.f_string}/{info.f_int32}/{info.f_double}/{info.f_bool}/{info.f_kingdom}:simplepath" }; } // Same as RepeatDataSimplePath, but with a path resource. rpc RepeatDataPathResource(RepeatRequest) returns (RepeatResponse) { option (google.api.http) = { get: "/v1beta1/repeat/{info.f_string=first/*}/{info.f_child.f_string=second/*}/bool/{info.f_bool}:pathresource" additional_bindings { get: "/v1beta1/repeat/{info.f_child.f_string=first/*}/{info.f_string=second/*}/bool/{info.f_bool}:childfirstpathresource" } }; } // Same as RepeatDataSimplePath, but with a trailing resource. rpc RepeatDataPathTrailingResource(RepeatRequest) returns (RepeatResponse) { option (google.api.http) = { get: "/v1beta1/repeat/{info.f_string=first/*}/{info.f_child.f_string=second/**}:pathtrailingresource" }; } // This method echoes the ComplianceData request, using the HTTP PUT method. rpc RepeatDataBodyPut(RepeatRequest) returns (RepeatResponse) { option (google.api.http) = { put: "/v1beta1/repeat:bodyput" body: "*" }; } // This method echoes the ComplianceData request, using the HTTP PATCH method. rpc RepeatDataBodyPatch(RepeatRequest) returns (RepeatResponse) { option (google.api.http) = { patch: "/v1beta1/repeat:bodypatch" body: "*" }; } // This method requests an enum value from the server. Depending on the contents of EnumRequest, the enum value returned will be a known enum declared in the // .proto file, or a made-up enum value the is unknown to the client. To verify that clients can round-trip unknown enum values they receive, use the // response from this RPC as the request to VerifyEnum() // // The values of enums sent by the server when a known or unknown value is requested will be the same within a single Showcase server run (this is needed for // VerifyEnum() to work) but are not guaranteed to be the same across separate Showcase server runs. rpc GetEnum(EnumRequest) returns (EnumResponse) { option (google.api.http) = { get: "/v1beta1/compliance/enum" }; } // This method is used to verify that clients can round-trip enum values, which is particularly important for unknown enum values over REST. VerifyEnum() // verifies that its request, which is presumably the response that the client previously got to a GetEnum(), contains the correct data. If so, it responds // with the same EnumResponse; otherwise, the RPC errors. // // This works because the values of enums sent by the server when a known or unknown value is requested will be the same within a single Showcase server run, // although they are not guaranteed to be the same across separate Showcase server runs. rpc VerifyEnum(EnumResponse) returns (EnumResponse) { option (google.api.http) = { post: "/v1beta1/compliance/enum" }; } } message RepeatRequest { string name = 1; ComplianceData info = 2; // If true, the server will verify that the received request matches // the request with the same name in the compliance test suite. bool server_verify = 3; // The URI template this request is expected to be bound to server-side. optional string intended_binding_uri = 10; // Some top level fields, to test that these are encoded correctly // in query params. int32 f_int32 = 4; int64 f_int64 = 5; double f_double = 6; optional int32 p_int32 = 7; optional int64 p_int64 = 8; optional double p_double = 9; } message RepeatResponse { RepeatRequest request = 1; // The URI template the request was bound to server-side. string binding_uri = 2; } // ComplianceSuite contains a set of requests that microgenerators should issue // over REST to the Compliance service to test their gRPC-to-REST transcoding // implementation. message ComplianceSuite { repeated ComplianceGroup group = 1; } // ComplianceGroups encapsulates a group of RPC requests to the Compliance // server: one request for each combination of elements of `rpcs` and of // `requests`. message ComplianceGroup { string name = 1; repeated string rpcs = 2; repeated RepeatRequest requests = 3; } // ComplianceData is a message used for testing REST transcoding of // different data types. message ComplianceData { enum LifeKingdom { LIFE_KINGDOM_UNSPECIFIED = 0; ARCHAEBACTERIA = 1; EUBACTERIA = 2; PROTISTA = 3; FUNGI = 4; PLANTAE = 5; ANIMALIA = 6; } // scalar types string f_string = 1; int32 f_int32 = 2; sint32 f_sint32 = 3; sfixed32 f_sfixed32 = 4; uint32 f_uint32 = 5; fixed32 f_fixed32 = 6; int64 f_int64 = 7; sint64 f_sint64 = 8; sfixed64 f_sfixed64 = 9; uint64 f_uint64 = 10; fixed64 f_fixed64 = 11; double f_double = 12; float f_float = 13; bool f_bool = 14; bytes f_bytes = 15; LifeKingdom f_kingdom = 22; ComplianceDataChild f_child = 16; // optional fields optional string p_string = 17; optional int32 p_int32 = 18; optional sint32 p_sint32 = 39; optional sfixed32 p_sfixed32 = 40; optional uint32 p_uint32 = 41; optional fixed32 p_fixed32 = 42; optional int64 p_int64 = 43; optional sint64 p_sint64 = 44; optional sfixed64 p_sfixed64 = 45; optional uint64 p_uint64 = 46; optional fixed64 p_fixed64 = 47; optional float p_float = 48; optional double p_double = 19; optional bool p_bool = 20; // The proto compiler seems to misgenerate optional bytes fields. // The generated code looks like: // ``` // if cmd.Flags().Changed("info.p_bytes") { // RepeatDataBodyInfoInput.Info.PBytes = &repeatDataBodyInfoInputInfoPBytes // } // ``` // The dereference of `&repeatDataBodyInfoInputInfoPBytes` is incorrect since // `repeatDataBodyInfoInputInfoPBytes` is already a `byte[]` // optional bytes p_bytes = 49; optional LifeKingdom p_kingdom = 23; optional ComplianceDataChild p_child = 21; } message ComplianceDataChild { string f_string = 1; float f_float = 2; double f_double = 3; bool f_bool = 4; Continent f_continent = 11; ComplianceDataGrandchild f_child = 5; optional string p_string = 6; optional float p_float = 7; optional double p_double = 8; optional bool p_bool = 9; Continent p_continent = 12; optional ComplianceDataGrandchild p_child = 10; } message ComplianceDataGrandchild { string f_string = 1; double f_double = 2; bool f_bool = 3; } enum Continent { CONTINENT_UNSPECIFIED = 0; AFRICA = 1; AMERICA = 2; ANTARTICA = 3; AUSTRALIA = 4; EUROPE = 5; } message EnumRequest { // Whether the client is requesting a new, unknown enum value or a known enum value already declared in this proto file. bool unknown_enum = 1; } message EnumResponse { // The original request for a known or unknown enum from the server. EnumRequest request = 1; // The actual enum the server provided. Continent continent = 2; } ================================================ FILE: schema/google/showcase/v1beta1/echo.proto ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. syntax = "proto3"; import "google/api/annotations.proto"; import "google/api/client.proto"; import "google/api/field_behavior.proto"; import "google/api/field_info.proto"; import "google/api/routing.proto"; import "google/longrunning/operations.proto"; import "google/protobuf/any.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/timestamp.proto"; import "google/rpc/status.proto"; package google.showcase.v1beta1; option go_package = "github.com/googleapis/gapic-showcase/server/genproto"; option java_package = "com.google.showcase.v1beta1"; option java_multiple_files = true; option ruby_package = "Google::Showcase::V1beta1"; // This service is used showcase the four main types of rpcs - unary, server // side streaming, client side streaming, and bidirectional streaming. This // service also exposes methods that explicitly implement server delay, and // paginated calls. Set the 'showcase-trailer' metadata key on any method // to have the values echoed in the response trailers. Set the // 'x-goog-request-params' metadata key on any method to have the values // echoed in the response headers. service Echo { // This service is meant to only run locally on the port 7469 (keypad digits // for "show"). option (google.api.default_host) = "localhost:7469"; // See https://github.com/aip-dev/google.aip.dev/pull/1331 option (google.api.api_version) = "v1_20240408"; // This method simply echoes the request. This method showcases unary RPCs. rpc Echo(EchoRequest) returns (EchoResponse) { option (google.api.http) = { post: "/v1beta1/echo:echo" body: "*" }; option (google.api.routing) = { routing_parameters{ field: "header" } routing_parameters{ field: "header" path_template: "{routing_id=**}" } routing_parameters{ field: "header" path_template: "{table_name=regions/*/zones/*/**}" } routing_parameters{ field: "header" path_template: "{super_id=projects/*}/**" } routing_parameters{ field: "header" path_template: "{table_name=projects/*/instances/*/**}" } routing_parameters{ field: "header" path_template: "projects/*/{instance_id=instances/*}/**" } routing_parameters{ field: "other_header" path_template: "{baz=**}" } routing_parameters{ field: "other_header" path_template: "{qux=projects/*}/**" } }; } // This method returns error details in a repeated "google.protobuf.Any" // field. This method showcases handling errors thus encoded, particularly // over REST transport. Note that GAPICs only allow the type // "google.protobuf.Any" for field paths ending in "error.details", and, at // run-time, the actual types for these fields must be one of the types in // google/rpc/error_details.proto. rpc EchoErrorDetails(EchoErrorDetailsRequest) returns (EchoErrorDetailsResponse) { option (google.api.http) = { post: "/v1beta1/echo:error-details" body: "*" }; } // This method always fails with a gRPC "Aborted" error status that contains // multiple error details. These include one instance of each of the standard // ones in error_details.proto // (https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto) // plus a custom, Showcase-defined PoetryError. The intent of this RPC is to // verify that GAPICs can process these various error details and surface them // to the user in an idiomatic form. rpc FailEchoWithDetails(FailEchoWithDetailsRequest) returns (FailEchoWithDetailsResponse) { option (google.api.http) = { post: "/v1beta1/echo:failWithDetails" body: "*" }; } // This method splits the given content into words and will pass each word back // through the stream. This method showcases server-side streaming RPCs. rpc Expand(ExpandRequest) returns (stream EchoResponse) { option (google.api.http) = { post: "/v1beta1/echo:expand" body: "*" }; // TODO(landrito): change this to be `fields: ["content", "error"]` once // github.com/dcodeIO/protobuf.js/issues/1094 has been resolved. option (google.api.method_signature) = "content,error"; } // This method will collect the words given to it. When the stream is closed // by the client, this method will return the a concatenation of the strings // passed to it. This method showcases client-side streaming RPCs. rpc Collect(stream EchoRequest) returns (EchoResponse) { option (google.api.http) = { post: "/v1beta1/echo:collect" body: "*" }; } // This method, upon receiving a request on the stream, will pass the same // content back on the stream. This method showcases bidirectional // streaming RPCs. rpc Chat(stream EchoRequest) returns (stream EchoResponse); // This is similar to the Expand method but instead of returning a stream of // expanded words, this method returns a paged list of expanded words. rpc PagedExpand(PagedExpandRequest) returns (PagedExpandResponse) { option (google.api.http) = { post: "/v1beta1/echo:pagedExpand" body: "*" }; } // This is similar to the PagedExpand except that it uses // max_results instead of page_size, as some legacy APIs still // do. New APIs should NOT use this pattern. rpc PagedExpandLegacy(PagedExpandLegacyRequest) returns (PagedExpandResponse) { option (google.api.http) = { post: "/v1beta1/echo:pagedExpandLegacy" body: "*" }; } // This method returns a map containing lists of words that appear in the input, keyed by their // initial character. The only words returned are the ones included in the current page, // as determined by page_token and page_size, which both refer to the word indices in the // input. This paging result consisting of a map of lists is a pattern used by some legacy // APIs. New APIs should NOT use this pattern. rpc PagedExpandLegacyMapped(PagedExpandRequest) returns (PagedExpandLegacyMappedResponse) { option (google.api.http) = { post: "/v1beta1/echo:pagedExpandLegacyMapped" body: "*" }; } // This method will wait for the requested amount of time and then return. // This method showcases how a client handles a request timeout. rpc Wait(WaitRequest) returns (google.longrunning.Operation) { option (google.api.http) = { post: "/v1beta1/echo:wait" body: "*" }; option (google.longrunning.operation_info) = { response_type: "WaitResponse" metadata_type: "WaitMetadata" }; } // This method will block (wait) for the requested amount of time // and then return the response or error. // This method showcases how a client handles delays or retries. rpc Block(BlockRequest) returns (BlockResponse) { option (google.api.http) = { post: "/v1beta1/echo:block" body: "*" }; }; } // A severity enum used to test enum capabilities in GAPIC surfaces. enum Severity { UNNECESSARY = 0; NECESSARY = 1; URGENT = 2; CRITICAL = 3; } // The request message used for the Echo, Collect and Chat methods. // If content or opt are set in this message then the request will succeed. // If status is set in this message then the status will be returned as an // error. message EchoRequest { oneof response { // The content to be echoed by the server. string content = 1; // The error to be thrown by the server. google.rpc.Status error = 2; } // The severity to be echoed by the server. Severity severity = 3; // Optional. This field can be set to test the routing annotation on the Echo method. string header = 4; // Optional. This field can be set to test the routing annotation on the Echo method. string other_header = 5; // To facilitate testing of https://google.aip.dev/client-libraries/4235 string request_id = 7 [ (google.api.field_info).format = UUID4 ]; // To facilitate testing of https://google.aip.dev/client-libraries/4235 optional string other_request_id = 8 [ (google.api.field_info).format = UUID4 ]; } // The response message for the Echo methods. message EchoResponse { // The content specified in the request. string content = 1; // The severity specified in the request. Severity severity = 2; // The request ID specified or autopopulated in the request. string request_id = 3; // The other request ID specified or autopopulated in the request. string other_request_id = 4; } // The request message used for the EchoErrorDetails method. message EchoErrorDetailsRequest { // Content to return in a singular `*.error.details` field of type // `google.protobuf.Any` string single_detail_text = 1; // Content to return in a repeated `*.error.details` field of type // `google.protobuf.Any` repeated string multi_detail_text = 2; } // The response message used for the EchoErrorDetails method. message EchoErrorDetailsResponse { message SingleDetail { ErrorWithSingleDetail error = 1; } message MultipleDetails { ErrorWithMultipleDetails error = 1; } SingleDetail single_detail = 1; MultipleDetails multiple_details = 2; } message ErrorWithSingleDetail { google.protobuf.Any details = 1; } message ErrorWithMultipleDetails { repeated google.protobuf.Any details = 1; } // The custom error detail to be included in the error response from the // FailEchoWithDetails method. Client libraries should be able to // surface this custom error detail. message PoetryError { string poem = 1; } // The request message used for the FailEchoWithDetails method. message FailEchoWithDetailsRequest { // Optional message to echo back in the PoetryError. If empty, a value will be // provided. string message = 1; } // The response message declared (but never used) for the FailEchoWithDetails // method. message FailEchoWithDetailsResponse {} // The request message for the Expand method. message ExpandRequest { // The content that will be split into words and returned on the stream. string content = 1; // The error that is thrown after all words are sent on the stream. google.rpc.Status error = 2; //The wait time between each server streaming messages google.protobuf.Duration stream_wait_time = 3; } // The request for the PagedExpand method. message PagedExpandRequest { // The string to expand. string content = 1 [(google.api.field_behavior) = REQUIRED]; // The number of words to returned in each page. int32 page_size = 2; // The position of the page to be returned. string page_token = 3; } // The request for the PagedExpandLegacy method. This is a pattern used by some legacy APIs. New // APIs should NOT use this pattern, but rather something like PagedExpandRequest which conforms to // aip.dev/158. message PagedExpandLegacyRequest { // The string to expand. string content = 1 [(google.api.field_behavior) = REQUIRED]; // The number of words to returned in each page. // (-- aip.dev/not-precedent: This is a legacy, non-standard pattern that // violates aip.dev/158. Ordinarily, this should be page_size. --) int32 max_results = 2; // The position of the page to be returned. string page_token = 3; } // The response for the PagedExpand method. message PagedExpandResponse { // The words that were expanded. repeated EchoResponse responses = 1; // The next page token. string next_page_token = 2; } // A list of words. message PagedExpandResponseList { repeated string words = 1; } message PagedExpandLegacyMappedResponse { // The words that were expanded, indexed by their initial character. // (-- aip.dev/not-precedent: This is a legacy, non-standard pattern that violates // aip.dev/158. Ordinarily, this should be a `repeated` field, as in PagedExpandResponse. --) map alphabetized = 1; // The next page token. string next_page_token = 2; } // The request for Wait method. message WaitRequest { oneof end { // The time that this operation will complete. google.protobuf.Timestamp end_time = 1; // The duration of this operation. google.protobuf.Duration ttl = 4; } oneof response { // The error that will be returned by the server. If this code is specified // to be the OK rpc code, an empty response will be returned. google.rpc.Status error = 2; // The response to be returned on operation completion. WaitResponse success = 3; } } // The result of the Wait operation. message WaitResponse { // This content of the result. string content = 1; } // The metadata for Wait operation. message WaitMetadata { // The time that this operation will complete. google.protobuf.Timestamp end_time =1; } // The request for Block method. message BlockRequest { // The amount of time to block before returning a response. google.protobuf.Duration response_delay = 1; oneof response { // The error that will be returned by the server. If this code is specified // to be the OK rpc code, an empty response will be returned. google.rpc.Status error = 2; // The response to be returned that will signify successful method call. BlockResponse success = 3; } } // The response for Block method. message BlockResponse { // This content can contain anything, the server will not depend on a value // here. string content = 1; } ================================================ FILE: schema/google/showcase/v1beta1/identity.proto ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. syntax = "proto3"; import "google/api/annotations.proto"; import "google/api/client.proto"; import "google/api/field_behavior.proto"; import "google/api/resource.proto"; import "google/protobuf/empty.proto"; import "google/protobuf/field_mask.proto"; import "google/protobuf/timestamp.proto"; package google.showcase.v1beta1; option go_package = "github.com/googleapis/gapic-showcase/server/genproto"; option java_package = "com.google.showcase.v1beta1"; option java_multiple_files = true; option ruby_package = "Google::Showcase::V1beta1"; // A simple identity service. service Identity { // This service is meant to only run locally on the port 7469 (keypad digits // for "show"). option (google.api.default_host) = "localhost:7469"; // Creates a user. rpc CreateUser(CreateUserRequest) returns (User) { option (google.api.http) = { post: "/v1beta1/users" body: "*" }; option (google.api.method_signature) = "user.display_name,user.email"; option (google.api.method_signature) = "user.display_name,user.email,user.age,user.nickname,user.enable_notifications,user.height_feet"; } // Retrieves the User with the given uri. rpc GetUser(GetUserRequest) returns (User) { option (google.api.http) = { get: "/v1beta1/{name=users/*}" }; option (google.api.method_signature) = "name"; } // Updates a user. rpc UpdateUser(UpdateUserRequest) returns (User) { option (google.api.http) = { patch: "/v1beta1/{user.name=users/*}" body: "user" }; } // Deletes a user, their profile, and all of their authored messages. rpc DeleteUser(DeleteUserRequest) returns (google.protobuf.Empty) { option (google.api.http) = { delete: "/v1beta1/{name=users/*}" }; option (google.api.method_signature) = "name"; } // Lists all users. rpc ListUsers(ListUsersRequest) returns (ListUsersResponse) { option (google.api.http) = { get: "/v1beta1/users" }; } } // A user. message User { option (google.api.resource) = { type: "showcase.googleapis.com/User" pattern: "users/{user}" }; // The resource name of the user. string name = 1; // The display_name of the user. string display_name = 2 [(google.api.field_behavior) = REQUIRED]; // The email address of the user. string email = 3 [(google.api.field_behavior) = REQUIRED]; // The timestamp at which the user was created. google.protobuf.Timestamp create_time = 4 [(google.api.field_behavior) = OUTPUT_ONLY]; // The latest timestamp at which the user was updated. google.protobuf.Timestamp update_time = 5 [(google.api.field_behavior) = OUTPUT_ONLY]; // The age of the user in years. optional int32 age = 6; // The height of the user in feet. optional double height_feet = 7; // The nickname of the user. // // (-- aip.dev/not-precedent: An empty string is a valid nickname. // Ordinarily, proto3_optional should not be used on a `string` field. --) optional string nickname = 8; // Enables the receiving of notifications. The default is true if unset. // // (-- aip.dev/not-precedent: The default for the feature is true. // Ordinarily, the default for a `bool` field should be false. --) optional bool enable_notifications = 9; } // The request message for the google.showcase.v1beta1.Identity\CreateUser // method. message CreateUserRequest { // The user to create. User user = 1; } // The request message for the google.showcase.v1beta1.Identity\GetUser // method. message GetUserRequest { // The resource name of the requested user. string name = 1 [ (google.api.resource_reference).type = "showcase.googleapis.com/User", (google.api.field_behavior) = REQUIRED ]; } // The request message for the google.showcase.v1beta1.Identity\UpdateUser // method. message UpdateUserRequest { // The user to update. User user = 1; // The field mask to determine which fields are to be updated. If empty, the // server will assume all fields are to be updated. google.protobuf.FieldMask update_mask = 2; } // The request message for the google.showcase.v1beta1.Identity\DeleteUser // method. message DeleteUserRequest { // The resource name of the user to delete. string name = 1 [ (google.api.resource_reference).type = "showcase.googleapis.com/User", (google.api.field_behavior) = REQUIRED ]; } // The request message for the google.showcase.v1beta1.Identity\ListUsers // method. message ListUsersRequest { // The maximum number of users to return. Server may return fewer users // than requested. If unspecified, server will pick an appropriate default. int32 page_size = 1; // The value of google.showcase.v1beta1.ListUsersResponse.next_page_token // returned from the previous call to // `google.showcase.v1beta1.Identity\ListUsers` method. string page_token = 2; } // The response message for the google.showcase.v1beta1.Identity\ListUsers // method. message ListUsersResponse { // The list of users. repeated User users = 1; // A token to retrieve next page of results. // Pass this value in ListUsersRequest.page_token field in the subsequent // call to `google.showcase.v1beta1.Message\ListUsers` method to retrieve the // next page of results. string next_page_token = 2; } ================================================ FILE: schema/google/showcase/v1beta1/messaging.proto ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. syntax = "proto3"; import "google/api/annotations.proto"; import "google/api/client.proto"; import "google/api/field_behavior.proto"; import "google/api/resource.proto"; import "google/longrunning/operations.proto"; import "google/protobuf/empty.proto"; import "google/protobuf/field_mask.proto"; import "google/protobuf/timestamp.proto"; import "google/rpc/error_details.proto"; package google.showcase.v1beta1; option go_package = "github.com/googleapis/gapic-showcase/server/genproto"; option java_package = "com.google.showcase.v1beta1"; option java_multiple_files = true; option ruby_package = "Google::Showcase::V1beta1"; // A simple messaging service that implements chat rooms and profile posts. // // This messaging service showcases the features that API clients // generated by gapic-generators implement. service Messaging { // This service is meant to only run locally on the port 7469 (keypad digits // for "show"). option (google.api.default_host) = "localhost:7469"; // Creates a room. rpc CreateRoom(CreateRoomRequest) returns (Room) { option (google.api.http) = { post: "/v1beta1/rooms" body: "*" }; option (google.api.method_signature) = "room.display_name,room.description"; } // Retrieves the Room with the given resource name. rpc GetRoom(GetRoomRequest) returns (Room) { option (google.api.http) = { get: "/v1beta1/{name=rooms/*}" }; option (google.api.method_signature) = "name"; } // Updates a room. rpc UpdateRoom(UpdateRoomRequest) returns (Room) { option (google.api.http) = { patch: "/v1beta1/{room.name=rooms/*}" body: "room" }; } // Deletes a room and all of its blurbs. rpc DeleteRoom(DeleteRoomRequest) returns (google.protobuf.Empty) { option (google.api.http) = { delete: "/v1beta1/{name=rooms/*}" }; option (google.api.method_signature) = "name"; } // Lists all chat rooms. rpc ListRooms(ListRoomsRequest) returns (ListRoomsResponse) { option (google.api.http) = { get: "/v1beta1/rooms" }; } // Creates a blurb. If the parent is a room, the blurb is understood to be a // message in that room. If the parent is a profile, the blurb is understood // to be a post on the profile. rpc CreateBlurb(CreateBlurbRequest) returns (Blurb) { option (google.api.http) = { post: "/v1beta1/{parent=rooms/*}/blurbs" body: "*" additional_bindings: { post: "/v1beta1/{parent=users/*/profile}/blurbs" body: "*" } }; option (google.api.method_signature) = "parent,blurb.user,blurb.text"; option (google.api.method_signature) = "parent,blurb.user,blurb.image"; } // Retrieves the Blurb with the given resource name. rpc GetBlurb(GetBlurbRequest) returns (Blurb) { option (google.api.http) = { get: "/v1beta1/{name=rooms/*/blurbs/*}" additional_bindings: { get: "/v1beta1/{name=users/*/profile/blurbs/*}" } }; option (google.api.method_signature) = "name"; } // Updates a blurb. rpc UpdateBlurb(UpdateBlurbRequest) returns (Blurb) { option (google.api.http) = { patch: "/v1beta1/{blurb.name=rooms/*/blurbs/*}" body: "blurb" additional_bindings: { patch: "/v1beta1/{blurb.name=users/*/profile/blurbs/*}" body: "blurb" } }; } // Deletes a blurb. rpc DeleteBlurb(DeleteBlurbRequest) returns (google.protobuf.Empty) { option (google.api.http) = { delete: "/v1beta1/{name=rooms/*/blurbs/*}" additional_bindings: { delete: "/v1beta1/{name=users/*/profile/blurbs/*}" } }; option (google.api.method_signature) = "name"; } // Lists blurbs for a specific chat room or user profile depending on the // parent resource name. rpc ListBlurbs(ListBlurbsRequest) returns (ListBlurbsResponse) { option (google.api.http) = { get: "/v1beta1/{parent=rooms/*}/blurbs" additional_bindings: { get: "/v1beta1/{parent=users/*/profile}/blurbs" } }; option (google.api.method_signature) = "parent"; } // This method searches through all blurbs across all rooms and profiles // for blurbs containing to words found in the query. Only posts that // contain an exact match of a queried word will be returned. rpc SearchBlurbs(SearchBlurbsRequest) returns (google.longrunning.Operation) { option (google.api.http) = { post: "/v1beta1/{parent=rooms/*}/blurbs:search" body: "*" additional_bindings: { post: "/v1beta1/{parent=users/*/profile}/blurbs:search" } }; option (google.longrunning.operation_info) = { response_type: "SearchBlurbsResponse" metadata_type: "SearchBlurbsMetadata" }; option (google.api.method_signature) = "parent,query"; } // This returns a stream that emits the blurbs that are created for a // particular chat room or user profile. rpc StreamBlurbs(StreamBlurbsRequest) returns (stream StreamBlurbsResponse) { option (google.api.http) = { post: "/v1beta1/{name=rooms/*}/blurbs:stream" body: "*" additional_bindings: { post: "/v1beta1/{name=users/*/profile}/blurbs:stream" body: "*" } }; } // This is a stream to create multiple blurbs. If an invalid blurb is // requested to be created, the stream will close with an error. rpc SendBlurbs(stream CreateBlurbRequest) returns (SendBlurbsResponse) { option (google.api.http) = { post: "/v1beta1/{parent=rooms/*}/blurbs:send" body: "*" additional_bindings: { post: "/v1beta1/{parent=users/*/profile}/blurbs:send" body: "*" } }; } // This method starts a bidirectional stream that receives all blurbs that // are being created after the stream has started and sends requests to create // blurbs. If an invalid blurb is requested to be created, the stream will // close with an error. rpc Connect(stream ConnectRequest) returns (stream StreamBlurbsResponse); } // A chat room. message Room { option (google.api.resource) = { type: "showcase.googleapis.com/Room" pattern: "rooms/{room}" }; // The resource name of the chat room. string name = 1; // The human readable name of the chat room. string display_name = 2 [(google.api.field_behavior) = REQUIRED]; // The description of the chat room. string description = 3; // The timestamp at which the room was created. google.protobuf.Timestamp create_time = 4 [(google.api.field_behavior) = OUTPUT_ONLY]; // The latest timestamp at which the room was updated. google.protobuf.Timestamp update_time = 5 [(google.api.field_behavior) = OUTPUT_ONLY]; } // The request message for the google.showcase.v1beta1.Messaging\CreateRoom // method. message CreateRoomRequest { // The room to create. Room room = 1; } // The request message for the google.showcase.v1beta1.Messaging\GetRoom // method. message GetRoomRequest { // The resource name of the requested room. string name = 1 [ (google.api.resource_reference).type = "showcase.googleapis.com/Room", (google.api.field_behavior) = REQUIRED ]; } // The request message for the google.showcase.v1beta1.Messaging\UpdateRoom // method. message UpdateRoomRequest { // The room to update. Room room = 1; // The field mask to determine which fields are to be updated. If empty, the // server will assume all fields are to be updated. google.protobuf.FieldMask update_mask = 2; } // The request message for the google.showcase.v1beta1.Messaging\DeleteRoom // method. message DeleteRoomRequest { // The resource name of the requested room. string name = 1 [ (google.api.resource_reference).type = "showcase.googleapis.com/Room", (google.api.field_behavior) = REQUIRED ]; } // The request message for the google.showcase.v1beta1.Messaging\ListRooms // method. message ListRoomsRequest { // The maximum number of rooms return. Server may return fewer rooms // than requested. If unspecified, server will pick an appropriate default. int32 page_size = 1; // The value of google.showcase.v1beta1.ListRoomsResponse.next_page_token // returned from the previous call to // `google.showcase.v1beta1.Messaging\ListRooms` method. string page_token = 2; } // The response message for the google.showcase.v1beta1.Messaging\ListRooms // method. message ListRoomsResponse { // The list of rooms. repeated Room rooms = 1; // A token to retrieve next page of results. // Pass this value in ListRoomsRequest.page_token field in the subsequent // call to `google.showcase.v1beta1.Messaging\ListRooms` method to retrieve // the next page of results. string next_page_token = 2; } // This protocol buffer message represents a blurb sent to a chat room or // posted on a user profile. message Blurb { option (google.api.resource) = { type: "showcase.googleapis.com/Blurb" pattern: "users/{user}/profile/blurbs/legacy/{legacy_user}~{blurb}" pattern: "users/{user}/profile/blurbs/{blurb}" pattern: "rooms/{room}/blurbs/{blurb}" pattern: "rooms/{room}/blurbs/legacy/{legacy_room}.{blurb}" }; // The resource name of the chat room. string name = 1; // The resource name of the blurb's author. string user = 2 [ (google.api.resource_reference).type = "showcase.googleapis.com/User", (google.api.field_behavior) = REQUIRED ]; oneof content { // The textual content of this blurb. string text = 3; // The image content of this blurb. bytes image = 4; } // The timestamp at which the blurb was created. google.protobuf.Timestamp create_time = 5 [(google.api.field_behavior) = OUTPUT_ONLY]; // The latest timestamp at which the blurb was updated. google.protobuf.Timestamp update_time = 6 [(google.api.field_behavior) = OUTPUT_ONLY]; // (-- aip.dev/not-precedent: This is designed for testing non-slash // resource patterns. Ordinarily, non-slash separators are discouraged. // --) oneof legacy_id { // The legacy id of the room. This field is used to signal // the use of the compound resource pattern // `rooms/{room}/blurbs/legacy/{legacy_room}.{blurb}` string legacy_room_id = 7; // The legacy id of the user. This field is used to signal // the use of the compound resource pattern // `users/{user}/profile/blurbs/legacy/{legacy_user}~{blurb}` string legacy_user_id = 8; } } // The request message for the google.showcase.v1beta1.Messaging\CreateBlurb // method. message CreateBlurbRequest { // The resource name of the chat room or user profile that this blurb will // be tied to. string parent = 1 [ (google.api.resource_reference).child_type = "showcase.googleapis.com/Blurb", (google.api.field_behavior) = REQUIRED ]; // The blurb to create. Blurb blurb = 2; } // The request message for the google.showcase.v1beta1.Messaging\GetBlurb // method. message GetBlurbRequest { // The resource name of the requested blurb. string name = 1 [ (google.api.resource_reference).type = "showcase.googleapis.com/Blurb", (google.api.field_behavior) = REQUIRED ]; } // The request message for the google.showcase.v1beta1.Messaging\UpdateBlurb // method. message UpdateBlurbRequest { // The blurb to update. Blurb blurb = 1; // The field mask to determine which fields are to be updated. If empty, the // server will assume all fields are to be updated. google.protobuf.FieldMask update_mask = 2; } // The request message for the google.showcase.v1beta1.Messaging\DeleteBlurb // method. message DeleteBlurbRequest { // The resource name of the requested blurb. string name = 1 [ (google.api.resource_reference).type = "showcase.googleapis.com/Blurb", (google.api.field_behavior) = REQUIRED ]; } // The request message for the google.showcase.v1beta1.Messaging\ListBlurbs // method. message ListBlurbsRequest { // The resource name of the requested room or profile who blurbs to list. string parent = 1 [ (google.api.resource_reference).child_type = "showcase.googleapis.com/Blurb", (google.api.field_behavior) = REQUIRED ]; // The maximum number of blurbs to return. Server may return fewer // blurbs than requested. If unspecified, server will pick an appropriate // default. int32 page_size = 2; // The value of google.showcase.v1beta1.ListBlurbsResponse.next_page_token // returned from the previous call to // `google.showcase.v1beta1.Messaging\ListBlurbs` method. string page_token = 3; } // The response message for the google.showcase.v1beta1.Messaging\ListBlurbs // method. message ListBlurbsResponse { // The list of blurbs. repeated Blurb blurbs = 1; // A token to retrieve next page of results. // Pass this value in ListBlurbsRequest.page_token field in the subsequent // call to `google.showcase.v1beta1.Blurb\ListBlurbs` method to retrieve // the next page of results. string next_page_token = 2; } // The request message for the google.showcase.v1beta1.Messaging\SearchBlurbs // method. message SearchBlurbsRequest { // The query used to search for blurbs containing to words of this string. // Only posts that contain an exact match of a queried word will be returned. string query = 1 [(google.api.field_behavior) = REQUIRED]; // The rooms or profiles to search. If unset, `SearchBlurbs` will search all // rooms and all profiles. string parent = 2 [(google.api.resource_reference).child_type = "showcase.googleapis.com/Blurb"]; // The maximum number of blurbs return. Server may return fewer // blurbs than requested. If unspecified, server will pick an appropriate // default. int32 page_size = 3; // The value of // google.showcase.v1beta1.SearchBlurbsResponse.next_page_token // returned from the previous call to // `google.showcase.v1beta1.Messaging\SearchBlurbs` method. string page_token = 4; } // The operation metadata message for the // google.showcase.v1beta1.Messaging\SearchBlurbs method. message SearchBlurbsMetadata { // This signals to the client when to next poll for response. google.rpc.RetryInfo retry_info = 1; } // The operation response message for the // google.showcase.v1beta1.Messaging\SearchBlurbs method. message SearchBlurbsResponse { // Blurbs that matched the search query. repeated Blurb blurbs = 1; // A token to retrieve next page of results. // Pass this value in SearchBlurbsRequest.page_token field in the subsequent // call to `google.showcase.v1beta1.Blurb\SearchBlurbs` method to // retrieve the next page of results. string next_page_token = 2; } // The request message for the google.showcase.v1beta1.Messaging\StreamBlurbs // method. message StreamBlurbsRequest { // The resource name of a chat room or user profile whose blurbs to stream. string name = 1 [ (google.api.resource_reference).child_type = "showcase.googleapis.com/Blurb", (google.api.field_behavior) = REQUIRED ]; // The time at which this stream will close. google.protobuf.Timestamp expire_time = 2 [(google.api.field_behavior) = REQUIRED]; } // The response message for the google.showcase.v1beta1.Messaging\StreamBlurbs // method. message StreamBlurbsResponse { // The blurb that was either created, updated, or deleted. Blurb blurb = 1; // The action that triggered the blurb to be returned. enum Action { ACTION_UNSPECIFIED = 0; // Specifies that the blurb was created. CREATE = 1; // Specifies that the blurb was updated. UPDATE = 2; // Specifies that the blurb was deleted. DELETE = 3; } // The action that triggered the blurb to be returned. Action action = 2; } // The response message for the google.showcase.v1beta1.Messaging\SendBlurbs // method. message SendBlurbsResponse { // The names of successful blurb creations. repeated string names = 1; } // The request message for the google.showcase.v1beta1.Messaging\Connect // method. message ConnectRequest { message ConnectConfig { // The room or profile to follow and create messages for. string parent = 1 [(google.api.resource_reference).child_type = "showcase.googleapis.com/Blurb"]; } oneof request { // Provides information that specifies how to process subsequent requests. // The first `ConnectRequest` message must contain a `config` message. ConnectConfig config = 1; // The blurb to be created. Blurb blurb = 2; } } ================================================ FILE: schema/google/showcase/v1beta1/rest_error.proto ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. syntax = "proto3"; import "google/protobuf/any.proto"; import "google/rpc/code.proto"; package google.showcase.v1beta1; option go_package = "github.com/googleapis/gapic-showcase/server/genproto"; option java_package = "com.google.showcase.v1beta1"; option java_multiple_files = true; option ruby_package = "Google::Showcase::V1beta1"; // HTTP/JSON error representation as defined in // https://google.aip.dev/193#http11json-representation, message RestError { message Status { // The HTTP status code that corresponds to `google.rpc.Status.code`. int32 code = 1; // This corresponds to `google.rpc.Status.message`. string message = 2; // This is the enum version for `google.rpc.Status.code`. google.rpc.Code status = 4; // This corresponds to `google.rpc.Status.details`. repeated google.protobuf.Any details = 5; } Status error = 1; } ================================================ FILE: schema/google/showcase/v1beta1/sequence.proto ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. syntax = "proto3"; import "google/api/annotations.proto"; import "google/api/client.proto"; import "google/api/field_behavior.proto"; import "google/api/resource.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/empty.proto"; import "google/protobuf/timestamp.proto"; import "google/rpc/status.proto"; package google.showcase.v1beta1; option go_package = "github.com/googleapis/gapic-showcase/server/genproto"; option java_package = "com.google.showcase.v1beta1"; option java_multiple_files = true; option ruby_package = "Google::Showcase::V1beta1"; // A service that enables testing of unary and server streaming calls // by specifying a specific, predictable sequence of responses from the service service SequenceService { // This service is meant to only run locally on the port 7469 (keypad digits // for "show"). option (google.api.default_host) = "localhost:7469"; // Create a sequence of responses to be returned as unary calls rpc CreateSequence(CreateSequenceRequest) returns (Sequence) { option (google.api.http) = { post: "/v1beta1/sequences" body: "sequence" }; option (google.api.method_signature) = "sequence"; }; // Creates a sequence of responses to be returned in a server streaming call rpc CreateStreamingSequence(CreateStreamingSequenceRequest) returns (StreamingSequence) { option (google.api.http) = { post: "/v1beta1/streamingSequences" body: "streaming_sequence" }; option (google.api.method_signature) = "streaming_sequence"; }; // Retrieves a sequence report which can be used to retrieve information about a // sequence of unary calls. rpc GetSequenceReport(GetSequenceReportRequest) returns (SequenceReport) { option (google.api.http) = { get: "/v1beta1/{name=sequences/*/sequenceReport}" }; option (google.api.method_signature) = "name"; }; // Retrieves a sequence report which can be used to retrieve information // about a sequences of responses in a server streaming call. rpc GetStreamingSequenceReport(GetStreamingSequenceReportRequest) returns (StreamingSequenceReport) { option (google.api.http) = { get: "/v1beta1/{name=streamingSequences/*/streamingSequenceReport}" }; option (google.api.method_signature) = "name"; }; // Attempts a sequence of unary responses. rpc AttemptSequence(AttemptSequenceRequest) returns (google.protobuf.Empty) { option (google.api.http) = { post: "/v1beta1/{name=sequences/*}" body: "*" }; option (google.api.method_signature) = "name"; }; // Attempts a server streaming call with a sequence of responses // Can be used to test retries and stream resumption logic // May not function as expected in HTTP mode due to when http statuses are sent // See https://github.com/googleapis/gapic-showcase/issues/1377 for more details rpc AttemptStreamingSequence(AttemptStreamingSequenceRequest) returns (stream AttemptStreamingSequenceResponse) { option (google.api.http) = { post: "/v1beta1/{name=streamingSequences/*}:stream" body: "*" }; option (google.api.method_signature) = "name"; }; } // A sequence of responses to be returned in order for each unary call attempt message Sequence { option (google.api.resource) = { type: "showcase.googleapis.com/Sequence" pattern: "sequences/{sequence}" }; string name = 1 [(google.api.field_behavior) = OUTPUT_ONLY]; // A server response to an RPC Attempt in a sequence. message Response { // The status to return for an individual attempt. google.rpc.Status status = 1; // The amount of time to delay sending the response. google.protobuf.Duration delay = 2; } // Sequence of responses to return in order for each attempt. If empty, the // default response is an immediate OK. repeated Response responses = 2; } // A sequence of responses to be returned in order at the delay specified // as part of the server streaming call message StreamingSequence { option (google.api.resource) = { type: "showcase.googleapis.com/StreamingSequence" pattern: "streamingSequences/{streaming_sequence}" }; // The name of the streaming sequence. string name = 1 [(google.api.field_behavior) = OUTPUT_ONLY]; // The content that the stream will send // this was specified when the sequence was created string content = 2; // A server response to an RPC Attempt in a sequence. message Response { // The status to return for an individual attempt. google.rpc.Status status = 1; // The amount of time to delay sending the response. google.protobuf.Duration delay = 2; // The index that the status should be sent at int32 response_index = 3; } // Sequence of responses to return in order for each attempt. If empty, the // default response is an immediate OK. repeated Response responses = 3; } // A report of the results of a streaming sequence. message StreamingSequenceReport { option (google.api.resource) = { type: "showcase.googleapis.com/StreamingSequenceReport" pattern: "streamingSequences/{streaming_sequence}/streamingSequenceReport" }; string name = 1 [(google.api.field_behavior) = OUTPUT_ONLY]; // Contains metrics on individual RPC Attempts in a sequence. message Attempt { // The attempt number - starting at 0. int32 attempt_number = 1; // The deadline dictated by the attempt to the server. google.protobuf.Timestamp attempt_deadline = 2; // The time that the server responded to the RPC attempt. Used for // calculating attempt_delay. google.protobuf.Timestamp response_time = 3; // The server perceived delay between sending the last response and // receiving this attempt. Used for validating attempt delay backoff. google.protobuf.Duration attempt_delay = 4; // The status returned to the attempt. google.rpc.Status status = 5; } // The set of RPC attempts received by the server for a Sequence. repeated Attempt attempts = 2; } // A report of the results of a sequence of unary responses message SequenceReport { option (google.api.resource) = { type: "showcase.googleapis.com/SequenceReport" pattern: "sequences/{sequence}/sequenceReport" }; string name = 1 [(google.api.field_behavior) = OUTPUT_ONLY]; // Contains metrics on individual RPC Attempts in a sequence. message Attempt { // The attempt number - starting at 0. int32 attempt_number = 1; // The deadline dictated by the attempt to the server. google.protobuf.Timestamp attempt_deadline = 2; // The time that the server responded to the RPC attempt. Used for // calculating attempt_delay. google.protobuf.Timestamp response_time = 3; // The server perceived delay between sending the last response and // receiving this attempt. Used for validating attempt delay backoff. google.protobuf.Duration attempt_delay = 4; // The status returned to the attempt. google.rpc.Status status = 5; } // The set of RPC attempts received by the server for a Sequence. repeated Attempt attempts = 2; } // Request message for creating a sequence of unary calls message CreateSequenceRequest { Sequence sequence = 1; } // Request message for the sequences of responses to be sent in a server streaming call message CreateStreamingSequenceRequest { StreamingSequence streaming_sequence = 1; } // Request message for the unary AttemptSequence method message AttemptSequenceRequest { string name = 1 [ (google.api.resource_reference).type = "showcase.googleapis.com/Sequence", (google.api.field_behavior) = REQUIRED ]; } // Request message for the AttemptStreamingSequence method. message AttemptStreamingSequenceRequest { string name = 1 [ (google.api.resource_reference).type = "showcase.googleapis.com/StreamingSequence", (google.api.field_behavior) = REQUIRED ]; // used to send the index of the last failed message // in the string "content" of an AttemptStreamingSequenceResponse // needed for stream resumption logic testing int32 last_fail_index = 2 [ (google.api.field_behavior) = OPTIONAL ]; } // The response message for the AttemptStreamingSequence method. message AttemptStreamingSequenceResponse { // The content specified in the request. string content = 1; } message GetSequenceReportRequest { string name = 1 [ (google.api.resource_reference).type = "showcase.googleapis.com/SequenceReport", (google.api.field_behavior) = REQUIRED ]; } message GetStreamingSequenceReportRequest { string name = 1 [ (google.api.resource_reference).type = "showcase.googleapis.com/StreamingSequenceReport", (google.api.field_behavior) = REQUIRED ]; } ================================================ FILE: schema/google/showcase/v1beta1/showcase_grpc_service_config.json ================================================ { "methodConfig": [ { "name": [ {"service": "google.showcase.v1beta1.Echo"}, {"service": "google.showcase.v1beta1.Messaging"}, {"service": "google.showcase.v1beta1.SequenceService"} ], "timeout": "5s" }, { "name": [ { "service": "google.showcase.v1beta1.Echo", "method": "Echo" }, { "service": "google.showcase.v1beta1.Echo", "method": "Expand" }, { "service": "google.showcase.v1beta1.Echo", "method": "PagedExpand" }, { "service": "google.showcase.v1beta1.Messaging", "method": "GetRoom" }, { "service": "google.showcase.v1beta1.Messaging", "method": "ListRooms" }, { "service": "google.showcase.v1beta1.Messaging", "method": "GetBlurb" }, { "service": "google.showcase.v1beta1.Messaging", "method": "ListBlurbs" }, { "service": "google.showcase.v1beta1.Messaging", "method": "SearchBlurbs" }, { "service": "google.showcase.v1beta1.Messaging", "method": "Connect" }, { "service": "google.showcase.v1beta1.SequenceService", "method": "AttemptSequence" } ], "retryPolicy": { "maxAttempts": 3, "maxBackoff": "3s", "initialBackoff": "0.1s", "backoffMultiplier": 2, "retryableStatusCodes": [ "UNAVAILABLE", "UNKNOWN" ] }, "timeout": "10s" }, { "name": [ { "service": "google.showcase.v1beta1.Identity", "method": "GetUser" }, { "service": "google.showcase.v1beta1.Identity", "method": "ListUsers" } ], "retryPolicy": { "maxAttempts": 5, "maxBackoff": "3s", "initialBackoff": "0.2s", "backoffMultiplier": 2, "retryableStatusCodes": [ "UNAVAILABLE", "UNKNOWN" ] }, "timeout": "5s" } ] } ================================================ FILE: schema/google/showcase/v1beta1/showcase_v1beta1.yaml ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. type: google.api.Service config_version: 3 name: showcase.googleapis.com title: Client Libraries Showcase API apis: - name: google.showcase.v1beta1.Compliance - name: google.showcase.v1beta1.Echo - name: google.showcase.v1beta1.Identity - name: google.showcase.v1beta1.Messaging - name: google.showcase.v1beta1.SequenceService - name: google.showcase.v1beta1.Testing # Mix-in services - name: 'google.cloud.location.Locations' - name: 'google.iam.v1.IAMPolicy' - name: 'google.longrunning.Operations' documentation: summary: |- Showcase represents both a model API and an integration testing surface for client library generator consumption. backend: rules: - selector: 'google.cloud.location.Locations.*' deadline: 60.0 - selector: 'google.iam.v1.IAMPolicy.*' deadline: 60.0 - selector: 'google.longrunning.Operations.*' deadline: 60.0 http: rules: - selector: google.cloud.location.Locations.ListLocations get: '/v1beta1/{name=projects/*}/locations' - selector: google.cloud.location.Locations.GetLocation get: '/v1beta1/{name=projects/*/locations/*}' - selector: google.iam.v1.IAMPolicy.SetIamPolicy post: '/v1beta1/{resource=users/*}:setIamPolicy' body: '*' additional_bindings: - post: '/v1beta1/{resource=rooms/*}:setIamPolicy' body: '*' - post: '/v1beta1/{resource=rooms/*/blurbs/*}:setIamPolicy' body: '*' - post: '/v1beta1/{resource=sequences/*}:setIamPolicy' body: '*' - selector: google.iam.v1.IAMPolicy.GetIamPolicy get: '/v1beta1/{resource=users/*}:getIamPolicy' additional_bindings: - get: '/v1beta1/{resource=rooms/*}:getIamPolicy' - get: '/v1beta1/{resource=rooms/*/blurbs/*}:getIamPolicy' - get: '/v1beta1/{resource=sequences/*}:getIamPolicy' - selector: google.iam.v1.IAMPolicy.TestIamPermissions post: '/v1beta1/{resource=users/*}:testIamPermissions' body: '*' additional_bindings: - post: '/v1beta1/{resource=rooms/*}:testIamPermissions' body: '*' - post: '/v1beta1/{resource=rooms/*/blurbs/*}:testIamPermissions' body: '*' - post: '/v1beta1/{resource=sequences/*}:testIamPermissions' body: '*' - selector: google.longrunning.Operations.ListOperations get: '/v1beta1/operations' - selector: google.longrunning.Operations.GetOperation get: '/v1beta1/{name=operations/**}' - selector: google.longrunning.Operations.DeleteOperation delete: '/v1beta1/{name=operations/**}' - selector: google.longrunning.Operations.CancelOperation post: '/v1beta1/{name=operations/**}:cancel' publishing: method_settings: - selector: google.showcase.v1beta1.Echo.Echo auto_populated_fields: - request_id - other_request_id ================================================ FILE: schema/google/showcase/v1beta1/testing.proto ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. syntax = "proto3"; import "google/api/annotations.proto"; import "google/api/client.proto"; import "google/api/resource.proto"; import "google/protobuf/empty.proto"; package google.showcase.v1beta1; option go_package = "github.com/googleapis/gapic-showcase/server/genproto"; option java_package = "com.google.showcase.v1beta1"; option java_multiple_files = true; option ruby_package = "Google::Showcase::V1beta1"; // A service to facilitate running discrete sets of tests // against Showcase. // Adding this comment with special characters for comment formatting tests: // 1. (abra->kadabra->alakazam) // 2) [Nonsense][]: `pokemon/*/psychic/*` service Testing { // This service is meant to only run locally on the port 7469 (keypad digits // for "show"). option (google.api.default_host) = "localhost:7469"; // Creates a new testing session. // Adding this comment with special characters for comment formatting tests: // 1. (abra->kadabra->alakazam) // 2) [Nonsense][]: `pokemon/*/psychic/*` rpc CreateSession(CreateSessionRequest) returns (Session) { option (google.api.http) = { post: "/v1beta1/sessions" body: "session" }; } // Gets a testing session. rpc GetSession(GetSessionRequest) returns (Session) { option (google.api.http) = { get: "/v1beta1/{name=sessions/*}" }; } // Lists the current test sessions. rpc ListSessions(ListSessionsRequest) returns (ListSessionsResponse) { option (google.api.http) = { get: "/v1beta1/sessions" }; } // Delete a test session. rpc DeleteSession(DeleteSessionRequest) returns (google.protobuf.Empty) { option (google.api.http) = { delete: "/v1beta1/{name=sessions/*}" }; } // Report on the status of a session. // This generates a report detailing which tests have been completed, // and an overall rollup. rpc ReportSession(ReportSessionRequest) returns (ReportSessionResponse) { option (google.api.http) = { post: "/v1beta1/{name=sessions/*}:report" }; } // List the tests of a sessesion. rpc ListTests(ListTestsRequest) returns (ListTestsResponse) { option (google.api.http) = { get: "/v1beta1/{parent=sessions/*}/tests" }; } // Explicitly decline to implement a test. // // This removes the test from subsequent `ListTests` calls, and // attempting to do the test will error. // // This method will error if attempting to delete a required test. rpc DeleteTest(DeleteTestRequest) returns (google.protobuf.Empty) { option (google.api.http) = { delete: "/v1beta1/{name=sessions/*/tests/*}" }; } // Register a response to a test. // // In cases where a test involves registering a final answer at the // end of the test, this method provides the means to do so. rpc VerifyTest(VerifyTestRequest) returns (VerifyTestResponse) { option (google.api.http) = { post: "/v1beta1/{name=sessions/*/tests/*}:check" }; } } // A session is a suite of tests, generally being made in the context // of testing code generation. // // A session defines tests it may expect, based on which version of the // code generation spec is in use. message Session { option (google.api.resource) = { type: "showcase.googleapis.com/Session" pattern: "sessions/{session}" }; // The name of the session. The ID must conform to ^[a-z]+$ // If this is not provided, Showcase chooses one at random. string name = 1; // The specification versions understood by Showcase. enum Version { // Unspecified version. If passed on creation, the session will default // to using the latest stable release. VERSION_UNSPECIFIED = 0; // The latest v1. Currently, this is v1.0. V1_LATEST = 1; // v1.0. (Until the spec is "GA", this will be a moving target.) V1_0 = 2; } // Required. The version this session is using. Version version = 2; } // The request for the CreateSession method. message CreateSessionRequest { // The session to be created. // Sessions are immutable once they are created (although they can // be deleted). Session session = 1; } // The request for the GetSession method. message GetSessionRequest { // The session to be retrieved. string name = 1 [ (google.api.resource_reference).type = "showcase.googleapis.com/Session"]; } // The request for the ListSessions method. message ListSessionsRequest { // The maximum number of sessions to return per page. int32 page_size = 1; // The page token, for retrieving subsequent pages. string page_token = 2; } // Response for the ListSessions method. message ListSessionsResponse { // The sessions being returned. repeated Session sessions = 1; // The next page token, if any. // An empty value here means the last page has been reached. string next_page_token = 2; } // Request for the DeleteSession method. message DeleteSessionRequest { // The session to be deleted. string name = 1 [ (google.api.resource_reference).type = "showcase.googleapis.com/Session"]; } // Request message for reporting on a session. message ReportSessionRequest { // The session to be reported on. string name = 1 [ (google.api.resource_reference).type = "showcase.googleapis.com/Session"]; } // Response message for reporting on a session. message ReportSessionResponse { // The topline state of the report. enum Result { RESULT_UNSPECIFIED = 0; // The session is complete, and everything passed. PASSED = 1; // The session had an explicit failure. FAILED = 2; // The session is incomplete. This is a failure response. INCOMPLETE = 3; } // The state of the report. Result result = 1; // The test runs of this session. repeated TestRun test_runs = 2; } message Test { option (google.api.resource) = { type: "showcase.googleapis.com/Test" pattern: "sessions/{session}/tests/{test}" }; // The name of the test. // The tests/* portion of the names are hard-coded, and do not change // from session to session. string name = 1; // Whether or not a test is required, recommended, or optional. enum ExpectationLevel { EXPECTATION_LEVEL_UNSPECIFIED = 0; // This test is strictly required. REQUIRED = 1; // This test is recommended. // // If a generator explicitly ignores a recommended test (see `DeleteTest`), // then the report may still pass, but with a warning. // // If a generator skips a recommended test and does not explicitly // express that intention, the report will fail. RECOMMENDED = 2; // This test is optional. // // If a generator explicitly ignores an optional test (see `DeleteTest`), // then the report may still pass, and no warning will be issued. // // If a generator skips an optional test and does not explicitly // express that intention, the report may still pass, but with a // warning. OPTIONAL = 3; } // The expectation level for this test. ExpectationLevel expectation_level = 2; // A description of the test. string description = 3; // A blueprint is an explicit definition of methods and requests that are needed // to be made to test this specific test case. Ideally this would be represented // by something more robust like CEL, but as of writing this, I am unsure if CEL // is ready. message Blueprint { option (google.api.resource) = { type: "showcase.googleapis.com/Blueprint" pattern: "sessions/{session}/tests/{test}/blueprints/{blueprint}" }; // The name of this blueprint. string name = 1; // A description of this blueprint. string description = 2; // A message representing a method invocation. message Invocation { // The fully qualified name of the showcase method to be invoked. string method = 1; // The request to be made if a specific request is necessary. bytes serialized_request = 2; } // The initial request to trigger this test. Invocation request = 3; // An ordered list of method calls that can be called to trigger this test. repeated Invocation additional_requests = 4; } // The blueprints that will satisfy this test. There may be multiple blueprints // that can signal to the server that this test case is being exercised. Although // multiple blueprints are specified, only a single blueprint needs to be run to // signal that the test case was exercised. repeated Blueprint blueprints = 4; } // An issue found in the test. message Issue { // The different potential types of issues. enum Type { TYPE_UNSPECIFIED = 0; // The test was never instrumented. SKIPPED = 1; // The test was started but never confirmed. PENDING = 2; // The test was instrumented, but Showcase got an unexpected // value when the generator tried to confirm success. INCORRECT_CONFIRMATION = 3; } // The type of the issue. Type type = 1; // Severity levels. enum Severity { SEVERITY_UNSPECIFIED = 0; // Errors. ERROR = 1; // Warnings. WARNING = 2; } // The severity of the issue. Severity severity = 2; // A description of the issue. string description = 3; } // The request for the ListTests method. message ListTestsRequest { // The session. string parent = 1 [ (google.api.resource_reference).type = "showcase.googleapis.com/Session"]; // The maximum number of tests to return per page. int32 page_size = 2; // The page token, for retrieving subsequent pages. string page_token = 3; } // The response for the ListTests method. message ListTestsResponse { // The tests being returned. repeated Test tests = 1; // The next page token, if any. // An empty value here means the last page has been reached. string next_page_token = 2; } // A TestRun is the result of running a Test. message TestRun { // The name of the test. // The tests/* portion of the names are hard-coded, and do not change // from session to session. string test = 1 [ (google.api.resource_reference).type = "showcase.googleapis.com/Test"]; // An issue found with the test run. If empty, this test run was successful. Issue issue = 2; } // Request message for deleting a test. message DeleteTestRequest { // The test to be deleted. string name = 1 [ (google.api.resource_reference).type = "showcase.googleapis.com/Test"]; } message VerifyTestRequest { // The test to have an answer registered to it. string name = 1 [ (google.api.resource_reference).type = "showcase.googleapis.com/Test"]; // The answer from the test. bytes answer = 2; // The answers from the test if multiple are to be checked repeated bytes answers = 3; } message VerifyTestResponse { // An issue if check answer was unsuccessful. This will be empty if the check answer succeeded. Issue issue = 1; } ================================================ FILE: server/genproto/compliance.pb.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.33.0 // protoc v3.20.3 // source: google/showcase/v1beta1/compliance.proto package genproto import ( context "context" _ "google.golang.org/genproto/googleapis/api/annotations" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" 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) ) type Continent int32 const ( Continent_CONTINENT_UNSPECIFIED Continent = 0 Continent_AFRICA Continent = 1 Continent_AMERICA Continent = 2 Continent_ANTARTICA Continent = 3 Continent_AUSTRALIA Continent = 4 Continent_EUROPE Continent = 5 ) // Enum value maps for Continent. var ( Continent_name = map[int32]string{ 0: "CONTINENT_UNSPECIFIED", 1: "AFRICA", 2: "AMERICA", 3: "ANTARTICA", 4: "AUSTRALIA", 5: "EUROPE", } Continent_value = map[string]int32{ "CONTINENT_UNSPECIFIED": 0, "AFRICA": 1, "AMERICA": 2, "ANTARTICA": 3, "AUSTRALIA": 4, "EUROPE": 5, } ) func (x Continent) Enum() *Continent { p := new(Continent) *p = x return p } func (x Continent) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (Continent) Descriptor() protoreflect.EnumDescriptor { return file_google_showcase_v1beta1_compliance_proto_enumTypes[0].Descriptor() } func (Continent) Type() protoreflect.EnumType { return &file_google_showcase_v1beta1_compliance_proto_enumTypes[0] } func (x Continent) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use Continent.Descriptor instead. func (Continent) EnumDescriptor() ([]byte, []int) { return file_google_showcase_v1beta1_compliance_proto_rawDescGZIP(), []int{0} } type ComplianceData_LifeKingdom int32 const ( ComplianceData_LIFE_KINGDOM_UNSPECIFIED ComplianceData_LifeKingdom = 0 ComplianceData_ARCHAEBACTERIA ComplianceData_LifeKingdom = 1 ComplianceData_EUBACTERIA ComplianceData_LifeKingdom = 2 ComplianceData_PROTISTA ComplianceData_LifeKingdom = 3 ComplianceData_FUNGI ComplianceData_LifeKingdom = 4 ComplianceData_PLANTAE ComplianceData_LifeKingdom = 5 ComplianceData_ANIMALIA ComplianceData_LifeKingdom = 6 ) // Enum value maps for ComplianceData_LifeKingdom. var ( ComplianceData_LifeKingdom_name = map[int32]string{ 0: "LIFE_KINGDOM_UNSPECIFIED", 1: "ARCHAEBACTERIA", 2: "EUBACTERIA", 3: "PROTISTA", 4: "FUNGI", 5: "PLANTAE", 6: "ANIMALIA", } ComplianceData_LifeKingdom_value = map[string]int32{ "LIFE_KINGDOM_UNSPECIFIED": 0, "ARCHAEBACTERIA": 1, "EUBACTERIA": 2, "PROTISTA": 3, "FUNGI": 4, "PLANTAE": 5, "ANIMALIA": 6, } ) func (x ComplianceData_LifeKingdom) Enum() *ComplianceData_LifeKingdom { p := new(ComplianceData_LifeKingdom) *p = x return p } func (x ComplianceData_LifeKingdom) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (ComplianceData_LifeKingdom) Descriptor() protoreflect.EnumDescriptor { return file_google_showcase_v1beta1_compliance_proto_enumTypes[1].Descriptor() } func (ComplianceData_LifeKingdom) Type() protoreflect.EnumType { return &file_google_showcase_v1beta1_compliance_proto_enumTypes[1] } func (x ComplianceData_LifeKingdom) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use ComplianceData_LifeKingdom.Descriptor instead. func (ComplianceData_LifeKingdom) EnumDescriptor() ([]byte, []int) { return file_google_showcase_v1beta1_compliance_proto_rawDescGZIP(), []int{4, 0} } type RepeatRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` Info *ComplianceData `protobuf:"bytes,2,opt,name=info,proto3" json:"info,omitempty"` // If true, the server will verify that the received request matches // the request with the same name in the compliance test suite. ServerVerify bool `protobuf:"varint,3,opt,name=server_verify,json=serverVerify,proto3" json:"server_verify,omitempty"` // The URI template this request is expected to be bound to server-side. IntendedBindingUri *string `protobuf:"bytes,10,opt,name=intended_binding_uri,json=intendedBindingUri,proto3,oneof" json:"intended_binding_uri,omitempty"` // Some top level fields, to test that these are encoded correctly // in query params. FInt32 int32 `protobuf:"varint,4,opt,name=f_int32,json=fInt32,proto3" json:"f_int32,omitempty"` FInt64 int64 `protobuf:"varint,5,opt,name=f_int64,json=fInt64,proto3" json:"f_int64,omitempty"` FDouble float64 `protobuf:"fixed64,6,opt,name=f_double,json=fDouble,proto3" json:"f_double,omitempty"` PInt32 *int32 `protobuf:"varint,7,opt,name=p_int32,json=pInt32,proto3,oneof" json:"p_int32,omitempty"` PInt64 *int64 `protobuf:"varint,8,opt,name=p_int64,json=pInt64,proto3,oneof" json:"p_int64,omitempty"` PDouble *float64 `protobuf:"fixed64,9,opt,name=p_double,json=pDouble,proto3,oneof" json:"p_double,omitempty"` } func (x *RepeatRequest) Reset() { *x = RepeatRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_compliance_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *RepeatRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*RepeatRequest) ProtoMessage() {} func (x *RepeatRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_compliance_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 RepeatRequest.ProtoReflect.Descriptor instead. func (*RepeatRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_compliance_proto_rawDescGZIP(), []int{0} } func (x *RepeatRequest) GetName() string { if x != nil { return x.Name } return "" } func (x *RepeatRequest) GetInfo() *ComplianceData { if x != nil { return x.Info } return nil } func (x *RepeatRequest) GetServerVerify() bool { if x != nil { return x.ServerVerify } return false } func (x *RepeatRequest) GetIntendedBindingUri() string { if x != nil && x.IntendedBindingUri != nil { return *x.IntendedBindingUri } return "" } func (x *RepeatRequest) GetFInt32() int32 { if x != nil { return x.FInt32 } return 0 } func (x *RepeatRequest) GetFInt64() int64 { if x != nil { return x.FInt64 } return 0 } func (x *RepeatRequest) GetFDouble() float64 { if x != nil { return x.FDouble } return 0 } func (x *RepeatRequest) GetPInt32() int32 { if x != nil && x.PInt32 != nil { return *x.PInt32 } return 0 } func (x *RepeatRequest) GetPInt64() int64 { if x != nil && x.PInt64 != nil { return *x.PInt64 } return 0 } func (x *RepeatRequest) GetPDouble() float64 { if x != nil && x.PDouble != nil { return *x.PDouble } return 0 } type RepeatResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Request *RepeatRequest `protobuf:"bytes,1,opt,name=request,proto3" json:"request,omitempty"` // The URI template the request was bound to server-side. BindingUri string `protobuf:"bytes,2,opt,name=binding_uri,json=bindingUri,proto3" json:"binding_uri,omitempty"` } func (x *RepeatResponse) Reset() { *x = RepeatResponse{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_compliance_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *RepeatResponse) String() string { return protoimpl.X.MessageStringOf(x) } func (*RepeatResponse) ProtoMessage() {} func (x *RepeatResponse) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_compliance_proto_msgTypes[1] 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 RepeatResponse.ProtoReflect.Descriptor instead. func (*RepeatResponse) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_compliance_proto_rawDescGZIP(), []int{1} } func (x *RepeatResponse) GetRequest() *RepeatRequest { if x != nil { return x.Request } return nil } func (x *RepeatResponse) GetBindingUri() string { if x != nil { return x.BindingUri } return "" } // ComplianceSuite contains a set of requests that microgenerators should issue // over REST to the Compliance service to test their gRPC-to-REST transcoding // implementation. type ComplianceSuite struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Group []*ComplianceGroup `protobuf:"bytes,1,rep,name=group,proto3" json:"group,omitempty"` } func (x *ComplianceSuite) Reset() { *x = ComplianceSuite{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_compliance_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ComplianceSuite) String() string { return protoimpl.X.MessageStringOf(x) } func (*ComplianceSuite) ProtoMessage() {} func (x *ComplianceSuite) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_compliance_proto_msgTypes[2] 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 ComplianceSuite.ProtoReflect.Descriptor instead. func (*ComplianceSuite) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_compliance_proto_rawDescGZIP(), []int{2} } func (x *ComplianceSuite) GetGroup() []*ComplianceGroup { if x != nil { return x.Group } return nil } // ComplianceGroups encapsulates a group of RPC requests to the Compliance // server: one request for each combination of elements of `rpcs` and of // `requests`. type ComplianceGroup struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` Rpcs []string `protobuf:"bytes,2,rep,name=rpcs,proto3" json:"rpcs,omitempty"` Requests []*RepeatRequest `protobuf:"bytes,3,rep,name=requests,proto3" json:"requests,omitempty"` } func (x *ComplianceGroup) Reset() { *x = ComplianceGroup{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_compliance_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ComplianceGroup) String() string { return protoimpl.X.MessageStringOf(x) } func (*ComplianceGroup) ProtoMessage() {} func (x *ComplianceGroup) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_compliance_proto_msgTypes[3] 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 ComplianceGroup.ProtoReflect.Descriptor instead. func (*ComplianceGroup) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_compliance_proto_rawDescGZIP(), []int{3} } func (x *ComplianceGroup) GetName() string { if x != nil { return x.Name } return "" } func (x *ComplianceGroup) GetRpcs() []string { if x != nil { return x.Rpcs } return nil } func (x *ComplianceGroup) GetRequests() []*RepeatRequest { if x != nil { return x.Requests } return nil } // ComplianceData is a message used for testing REST transcoding of // different data types. type ComplianceData struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields FString string `protobuf:"bytes,1,opt,name=f_string,json=fString,proto3" json:"f_string,omitempty"` FInt32 int32 `protobuf:"varint,2,opt,name=f_int32,json=fInt32,proto3" json:"f_int32,omitempty"` FSint32 int32 `protobuf:"zigzag32,3,opt,name=f_sint32,json=fSint32,proto3" json:"f_sint32,omitempty"` FSfixed32 int32 `protobuf:"fixed32,4,opt,name=f_sfixed32,json=fSfixed32,proto3" json:"f_sfixed32,omitempty"` FUint32 uint32 `protobuf:"varint,5,opt,name=f_uint32,json=fUint32,proto3" json:"f_uint32,omitempty"` FFixed32 uint32 `protobuf:"fixed32,6,opt,name=f_fixed32,json=fFixed32,proto3" json:"f_fixed32,omitempty"` FInt64 int64 `protobuf:"varint,7,opt,name=f_int64,json=fInt64,proto3" json:"f_int64,omitempty"` FSint64 int64 `protobuf:"zigzag64,8,opt,name=f_sint64,json=fSint64,proto3" json:"f_sint64,omitempty"` FSfixed64 int64 `protobuf:"fixed64,9,opt,name=f_sfixed64,json=fSfixed64,proto3" json:"f_sfixed64,omitempty"` FUint64 uint64 `protobuf:"varint,10,opt,name=f_uint64,json=fUint64,proto3" json:"f_uint64,omitempty"` FFixed64 uint64 `protobuf:"fixed64,11,opt,name=f_fixed64,json=fFixed64,proto3" json:"f_fixed64,omitempty"` FDouble float64 `protobuf:"fixed64,12,opt,name=f_double,json=fDouble,proto3" json:"f_double,omitempty"` FFloat float32 `protobuf:"fixed32,13,opt,name=f_float,json=fFloat,proto3" json:"f_float,omitempty"` FBool bool `protobuf:"varint,14,opt,name=f_bool,json=fBool,proto3" json:"f_bool,omitempty"` FBytes []byte `protobuf:"bytes,15,opt,name=f_bytes,json=fBytes,proto3" json:"f_bytes,omitempty"` FKingdom ComplianceData_LifeKingdom `protobuf:"varint,22,opt,name=f_kingdom,json=fKingdom,proto3,enum=google.showcase.v1beta1.ComplianceData_LifeKingdom" json:"f_kingdom,omitempty"` FChild *ComplianceDataChild `protobuf:"bytes,16,opt,name=f_child,json=fChild,proto3" json:"f_child,omitempty"` PString *string `protobuf:"bytes,17,opt,name=p_string,json=pString,proto3,oneof" json:"p_string,omitempty"` PInt32 *int32 `protobuf:"varint,18,opt,name=p_int32,json=pInt32,proto3,oneof" json:"p_int32,omitempty"` PSint32 *int32 `protobuf:"zigzag32,39,opt,name=p_sint32,json=pSint32,proto3,oneof" json:"p_sint32,omitempty"` PSfixed32 *int32 `protobuf:"fixed32,40,opt,name=p_sfixed32,json=pSfixed32,proto3,oneof" json:"p_sfixed32,omitempty"` PUint32 *uint32 `protobuf:"varint,41,opt,name=p_uint32,json=pUint32,proto3,oneof" json:"p_uint32,omitempty"` PFixed32 *uint32 `protobuf:"fixed32,42,opt,name=p_fixed32,json=pFixed32,proto3,oneof" json:"p_fixed32,omitempty"` PInt64 *int64 `protobuf:"varint,43,opt,name=p_int64,json=pInt64,proto3,oneof" json:"p_int64,omitempty"` PSint64 *int64 `protobuf:"zigzag64,44,opt,name=p_sint64,json=pSint64,proto3,oneof" json:"p_sint64,omitempty"` PSfixed64 *int64 `protobuf:"fixed64,45,opt,name=p_sfixed64,json=pSfixed64,proto3,oneof" json:"p_sfixed64,omitempty"` PUint64 *uint64 `protobuf:"varint,46,opt,name=p_uint64,json=pUint64,proto3,oneof" json:"p_uint64,omitempty"` PFixed64 *uint64 `protobuf:"fixed64,47,opt,name=p_fixed64,json=pFixed64,proto3,oneof" json:"p_fixed64,omitempty"` PFloat *float32 `protobuf:"fixed32,48,opt,name=p_float,json=pFloat,proto3,oneof" json:"p_float,omitempty"` PDouble *float64 `protobuf:"fixed64,19,opt,name=p_double,json=pDouble,proto3,oneof" json:"p_double,omitempty"` PBool *bool `protobuf:"varint,20,opt,name=p_bool,json=pBool,proto3,oneof" json:"p_bool,omitempty"` PKingdom *ComplianceData_LifeKingdom `protobuf:"varint,23,opt,name=p_kingdom,json=pKingdom,proto3,enum=google.showcase.v1beta1.ComplianceData_LifeKingdom,oneof" json:"p_kingdom,omitempty"` PChild *ComplianceDataChild `protobuf:"bytes,21,opt,name=p_child,json=pChild,proto3,oneof" json:"p_child,omitempty"` } func (x *ComplianceData) Reset() { *x = ComplianceData{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_compliance_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ComplianceData) String() string { return protoimpl.X.MessageStringOf(x) } func (*ComplianceData) ProtoMessage() {} func (x *ComplianceData) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_compliance_proto_msgTypes[4] 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 ComplianceData.ProtoReflect.Descriptor instead. func (*ComplianceData) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_compliance_proto_rawDescGZIP(), []int{4} } func (x *ComplianceData) GetFString() string { if x != nil { return x.FString } return "" } func (x *ComplianceData) GetFInt32() int32 { if x != nil { return x.FInt32 } return 0 } func (x *ComplianceData) GetFSint32() int32 { if x != nil { return x.FSint32 } return 0 } func (x *ComplianceData) GetFSfixed32() int32 { if x != nil { return x.FSfixed32 } return 0 } func (x *ComplianceData) GetFUint32() uint32 { if x != nil { return x.FUint32 } return 0 } func (x *ComplianceData) GetFFixed32() uint32 { if x != nil { return x.FFixed32 } return 0 } func (x *ComplianceData) GetFInt64() int64 { if x != nil { return x.FInt64 } return 0 } func (x *ComplianceData) GetFSint64() int64 { if x != nil { return x.FSint64 } return 0 } func (x *ComplianceData) GetFSfixed64() int64 { if x != nil { return x.FSfixed64 } return 0 } func (x *ComplianceData) GetFUint64() uint64 { if x != nil { return x.FUint64 } return 0 } func (x *ComplianceData) GetFFixed64() uint64 { if x != nil { return x.FFixed64 } return 0 } func (x *ComplianceData) GetFDouble() float64 { if x != nil { return x.FDouble } return 0 } func (x *ComplianceData) GetFFloat() float32 { if x != nil { return x.FFloat } return 0 } func (x *ComplianceData) GetFBool() bool { if x != nil { return x.FBool } return false } func (x *ComplianceData) GetFBytes() []byte { if x != nil { return x.FBytes } return nil } func (x *ComplianceData) GetFKingdom() ComplianceData_LifeKingdom { if x != nil { return x.FKingdom } return ComplianceData_LIFE_KINGDOM_UNSPECIFIED } func (x *ComplianceData) GetFChild() *ComplianceDataChild { if x != nil { return x.FChild } return nil } func (x *ComplianceData) GetPString() string { if x != nil && x.PString != nil { return *x.PString } return "" } func (x *ComplianceData) GetPInt32() int32 { if x != nil && x.PInt32 != nil { return *x.PInt32 } return 0 } func (x *ComplianceData) GetPSint32() int32 { if x != nil && x.PSint32 != nil { return *x.PSint32 } return 0 } func (x *ComplianceData) GetPSfixed32() int32 { if x != nil && x.PSfixed32 != nil { return *x.PSfixed32 } return 0 } func (x *ComplianceData) GetPUint32() uint32 { if x != nil && x.PUint32 != nil { return *x.PUint32 } return 0 } func (x *ComplianceData) GetPFixed32() uint32 { if x != nil && x.PFixed32 != nil { return *x.PFixed32 } return 0 } func (x *ComplianceData) GetPInt64() int64 { if x != nil && x.PInt64 != nil { return *x.PInt64 } return 0 } func (x *ComplianceData) GetPSint64() int64 { if x != nil && x.PSint64 != nil { return *x.PSint64 } return 0 } func (x *ComplianceData) GetPSfixed64() int64 { if x != nil && x.PSfixed64 != nil { return *x.PSfixed64 } return 0 } func (x *ComplianceData) GetPUint64() uint64 { if x != nil && x.PUint64 != nil { return *x.PUint64 } return 0 } func (x *ComplianceData) GetPFixed64() uint64 { if x != nil && x.PFixed64 != nil { return *x.PFixed64 } return 0 } func (x *ComplianceData) GetPFloat() float32 { if x != nil && x.PFloat != nil { return *x.PFloat } return 0 } func (x *ComplianceData) GetPDouble() float64 { if x != nil && x.PDouble != nil { return *x.PDouble } return 0 } func (x *ComplianceData) GetPBool() bool { if x != nil && x.PBool != nil { return *x.PBool } return false } func (x *ComplianceData) GetPKingdom() ComplianceData_LifeKingdom { if x != nil && x.PKingdom != nil { return *x.PKingdom } return ComplianceData_LIFE_KINGDOM_UNSPECIFIED } func (x *ComplianceData) GetPChild() *ComplianceDataChild { if x != nil { return x.PChild } return nil } type ComplianceDataChild struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields FString string `protobuf:"bytes,1,opt,name=f_string,json=fString,proto3" json:"f_string,omitempty"` FFloat float32 `protobuf:"fixed32,2,opt,name=f_float,json=fFloat,proto3" json:"f_float,omitempty"` FDouble float64 `protobuf:"fixed64,3,opt,name=f_double,json=fDouble,proto3" json:"f_double,omitempty"` FBool bool `protobuf:"varint,4,opt,name=f_bool,json=fBool,proto3" json:"f_bool,omitempty"` FContinent Continent `protobuf:"varint,11,opt,name=f_continent,json=fContinent,proto3,enum=google.showcase.v1beta1.Continent" json:"f_continent,omitempty"` FChild *ComplianceDataGrandchild `protobuf:"bytes,5,opt,name=f_child,json=fChild,proto3" json:"f_child,omitempty"` PString *string `protobuf:"bytes,6,opt,name=p_string,json=pString,proto3,oneof" json:"p_string,omitempty"` PFloat *float32 `protobuf:"fixed32,7,opt,name=p_float,json=pFloat,proto3,oneof" json:"p_float,omitempty"` PDouble *float64 `protobuf:"fixed64,8,opt,name=p_double,json=pDouble,proto3,oneof" json:"p_double,omitempty"` PBool *bool `protobuf:"varint,9,opt,name=p_bool,json=pBool,proto3,oneof" json:"p_bool,omitempty"` PContinent Continent `protobuf:"varint,12,opt,name=p_continent,json=pContinent,proto3,enum=google.showcase.v1beta1.Continent" json:"p_continent,omitempty"` PChild *ComplianceDataGrandchild `protobuf:"bytes,10,opt,name=p_child,json=pChild,proto3,oneof" json:"p_child,omitempty"` } func (x *ComplianceDataChild) Reset() { *x = ComplianceDataChild{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_compliance_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ComplianceDataChild) String() string { return protoimpl.X.MessageStringOf(x) } func (*ComplianceDataChild) ProtoMessage() {} func (x *ComplianceDataChild) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_compliance_proto_msgTypes[5] 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 ComplianceDataChild.ProtoReflect.Descriptor instead. func (*ComplianceDataChild) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_compliance_proto_rawDescGZIP(), []int{5} } func (x *ComplianceDataChild) GetFString() string { if x != nil { return x.FString } return "" } func (x *ComplianceDataChild) GetFFloat() float32 { if x != nil { return x.FFloat } return 0 } func (x *ComplianceDataChild) GetFDouble() float64 { if x != nil { return x.FDouble } return 0 } func (x *ComplianceDataChild) GetFBool() bool { if x != nil { return x.FBool } return false } func (x *ComplianceDataChild) GetFContinent() Continent { if x != nil { return x.FContinent } return Continent_CONTINENT_UNSPECIFIED } func (x *ComplianceDataChild) GetFChild() *ComplianceDataGrandchild { if x != nil { return x.FChild } return nil } func (x *ComplianceDataChild) GetPString() string { if x != nil && x.PString != nil { return *x.PString } return "" } func (x *ComplianceDataChild) GetPFloat() float32 { if x != nil && x.PFloat != nil { return *x.PFloat } return 0 } func (x *ComplianceDataChild) GetPDouble() float64 { if x != nil && x.PDouble != nil { return *x.PDouble } return 0 } func (x *ComplianceDataChild) GetPBool() bool { if x != nil && x.PBool != nil { return *x.PBool } return false } func (x *ComplianceDataChild) GetPContinent() Continent { if x != nil { return x.PContinent } return Continent_CONTINENT_UNSPECIFIED } func (x *ComplianceDataChild) GetPChild() *ComplianceDataGrandchild { if x != nil { return x.PChild } return nil } type ComplianceDataGrandchild struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields FString string `protobuf:"bytes,1,opt,name=f_string,json=fString,proto3" json:"f_string,omitempty"` FDouble float64 `protobuf:"fixed64,2,opt,name=f_double,json=fDouble,proto3" json:"f_double,omitempty"` FBool bool `protobuf:"varint,3,opt,name=f_bool,json=fBool,proto3" json:"f_bool,omitempty"` } func (x *ComplianceDataGrandchild) Reset() { *x = ComplianceDataGrandchild{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_compliance_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ComplianceDataGrandchild) String() string { return protoimpl.X.MessageStringOf(x) } func (*ComplianceDataGrandchild) ProtoMessage() {} func (x *ComplianceDataGrandchild) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_compliance_proto_msgTypes[6] 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 ComplianceDataGrandchild.ProtoReflect.Descriptor instead. func (*ComplianceDataGrandchild) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_compliance_proto_rawDescGZIP(), []int{6} } func (x *ComplianceDataGrandchild) GetFString() string { if x != nil { return x.FString } return "" } func (x *ComplianceDataGrandchild) GetFDouble() float64 { if x != nil { return x.FDouble } return 0 } func (x *ComplianceDataGrandchild) GetFBool() bool { if x != nil { return x.FBool } return false } type EnumRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Whether the client is requesting a new, unknown enum value or a known enum value already declared in this proto file. UnknownEnum bool `protobuf:"varint,1,opt,name=unknown_enum,json=unknownEnum,proto3" json:"unknown_enum,omitempty"` } func (x *EnumRequest) Reset() { *x = EnumRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_compliance_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EnumRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*EnumRequest) ProtoMessage() {} func (x *EnumRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_compliance_proto_msgTypes[7] 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 EnumRequest.ProtoReflect.Descriptor instead. func (*EnumRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_compliance_proto_rawDescGZIP(), []int{7} } func (x *EnumRequest) GetUnknownEnum() bool { if x != nil { return x.UnknownEnum } return false } type EnumResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The original request for a known or unknown enum from the server. Request *EnumRequest `protobuf:"bytes,1,opt,name=request,proto3" json:"request,omitempty"` // The actual enum the server provided. Continent Continent `protobuf:"varint,2,opt,name=continent,proto3,enum=google.showcase.v1beta1.Continent" json:"continent,omitempty"` } func (x *EnumResponse) Reset() { *x = EnumResponse{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_compliance_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EnumResponse) String() string { return protoimpl.X.MessageStringOf(x) } func (*EnumResponse) ProtoMessage() {} func (x *EnumResponse) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_compliance_proto_msgTypes[8] 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 EnumResponse.ProtoReflect.Descriptor instead. func (*EnumResponse) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_compliance_proto_rawDescGZIP(), []int{8} } func (x *EnumResponse) GetRequest() *EnumRequest { if x != nil { return x.Request } return nil } func (x *EnumResponse) GetContinent() Continent { if x != nil { return x.Continent } return Continent_CONTINENT_UNSPECIFIED } var File_google_showcase_v1beta1_compliance_proto protoreflect.FileDescriptor var file_google_showcase_v1beta1_compliance_proto_rawDesc = []byte{ 0x0a, 0x28, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x17, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa3, 0x03, 0x0a, 0x0d, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x12, 0x35, 0x0a, 0x14, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x12, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x55, 0x72, 0x69, 0x88, 0x01, 0x01, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x66, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x5f, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x66, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x5f, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x07, 0x66, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x12, 0x1c, 0x0a, 0x07, 0x70, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x48, 0x01, 0x52, 0x06, 0x70, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x88, 0x01, 0x01, 0x12, 0x1c, 0x0a, 0x07, 0x70, 0x5f, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x48, 0x02, 0x52, 0x06, 0x70, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x88, 0x01, 0x01, 0x12, 0x1e, 0x0a, 0x08, 0x70, 0x5f, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x01, 0x48, 0x03, 0x52, 0x07, 0x70, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x88, 0x01, 0x01, 0x42, 0x17, 0x0a, 0x15, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x75, 0x72, 0x69, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x70, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x70, 0x5f, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x5f, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x22, 0x73, 0x0a, 0x0e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x55, 0x72, 0x69, 0x22, 0x51, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x75, 0x69, 0x74, 0x65, 0x12, 0x3e, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x7d, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x70, 0x63, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x72, 0x70, 0x63, 0x73, 0x12, 0x42, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x22, 0xfa, 0x0b, 0x0a, 0x0e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x66, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x66, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x5f, 0x73, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x03, 0x20, 0x01, 0x28, 0x11, 0x52, 0x07, 0x66, 0x53, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x5f, 0x73, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0f, 0x52, 0x09, 0x66, 0x53, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x66, 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x18, 0x06, 0x20, 0x01, 0x28, 0x07, 0x52, 0x08, 0x66, 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x5f, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x66, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x5f, 0x73, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x08, 0x20, 0x01, 0x28, 0x12, 0x52, 0x07, 0x66, 0x53, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x5f, 0x73, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x18, 0x09, 0x20, 0x01, 0x28, 0x10, 0x52, 0x09, 0x66, 0x53, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x66, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x06, 0x52, 0x08, 0x66, 0x46, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x5f, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x01, 0x52, 0x07, 0x66, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x02, 0x52, 0x06, 0x66, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x66, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x42, 0x6f, 0x6f, 0x6c, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x66, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x50, 0x0a, 0x09, 0x66, 0x5f, 0x6b, 0x69, 0x6e, 0x67, 0x64, 0x6f, 0x6d, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x33, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x4c, 0x69, 0x66, 0x65, 0x4b, 0x69, 0x6e, 0x67, 0x64, 0x6f, 0x6d, 0x52, 0x08, 0x66, 0x4b, 0x69, 0x6e, 0x67, 0x64, 0x6f, 0x6d, 0x12, 0x45, 0x0a, 0x07, 0x66, 0x5f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x52, 0x06, 0x66, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x12, 0x1e, 0x0a, 0x08, 0x70, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x07, 0x70, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x88, 0x01, 0x01, 0x12, 0x1c, 0x0a, 0x07, 0x70, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x12, 0x20, 0x01, 0x28, 0x05, 0x48, 0x01, 0x52, 0x06, 0x70, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x88, 0x01, 0x01, 0x12, 0x1e, 0x0a, 0x08, 0x70, 0x5f, 0x73, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x27, 0x20, 0x01, 0x28, 0x11, 0x48, 0x02, 0x52, 0x07, 0x70, 0x53, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x88, 0x01, 0x01, 0x12, 0x22, 0x0a, 0x0a, 0x70, 0x5f, 0x73, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0f, 0x48, 0x03, 0x52, 0x09, 0x70, 0x53, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x88, 0x01, 0x01, 0x12, 0x1e, 0x0a, 0x08, 0x70, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x29, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x04, 0x52, 0x07, 0x70, 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x70, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x18, 0x2a, 0x20, 0x01, 0x28, 0x07, 0x48, 0x05, 0x52, 0x08, 0x70, 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x88, 0x01, 0x01, 0x12, 0x1c, 0x0a, 0x07, 0x70, 0x5f, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x2b, 0x20, 0x01, 0x28, 0x03, 0x48, 0x06, 0x52, 0x06, 0x70, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x88, 0x01, 0x01, 0x12, 0x1e, 0x0a, 0x08, 0x70, 0x5f, 0x73, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x2c, 0x20, 0x01, 0x28, 0x12, 0x48, 0x07, 0x52, 0x07, 0x70, 0x53, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x88, 0x01, 0x01, 0x12, 0x22, 0x0a, 0x0a, 0x70, 0x5f, 0x73, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x18, 0x2d, 0x20, 0x01, 0x28, 0x10, 0x48, 0x08, 0x52, 0x09, 0x70, 0x53, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x88, 0x01, 0x01, 0x12, 0x1e, 0x0a, 0x08, 0x70, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x2e, 0x20, 0x01, 0x28, 0x04, 0x48, 0x09, 0x52, 0x07, 0x70, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x70, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x18, 0x2f, 0x20, 0x01, 0x28, 0x06, 0x48, 0x0a, 0x52, 0x08, 0x70, 0x46, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x88, 0x01, 0x01, 0x12, 0x1c, 0x0a, 0x07, 0x70, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x18, 0x30, 0x20, 0x01, 0x28, 0x02, 0x48, 0x0b, 0x52, 0x06, 0x70, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x88, 0x01, 0x01, 0x12, 0x1e, 0x0a, 0x08, 0x70, 0x5f, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x01, 0x48, 0x0c, 0x52, 0x07, 0x70, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x88, 0x01, 0x01, 0x12, 0x1a, 0x0a, 0x06, 0x70, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, 0x48, 0x0d, 0x52, 0x05, 0x70, 0x42, 0x6f, 0x6f, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x55, 0x0a, 0x09, 0x70, 0x5f, 0x6b, 0x69, 0x6e, 0x67, 0x64, 0x6f, 0x6d, 0x18, 0x17, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x33, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x4c, 0x69, 0x66, 0x65, 0x4b, 0x69, 0x6e, 0x67, 0x64, 0x6f, 0x6d, 0x48, 0x0e, 0x52, 0x08, 0x70, 0x4b, 0x69, 0x6e, 0x67, 0x64, 0x6f, 0x6d, 0x88, 0x01, 0x01, 0x12, 0x4a, 0x0a, 0x07, 0x70, 0x5f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x48, 0x0f, 0x52, 0x06, 0x70, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x88, 0x01, 0x01, 0x22, 0x83, 0x01, 0x0a, 0x0b, 0x4c, 0x69, 0x66, 0x65, 0x4b, 0x69, 0x6e, 0x67, 0x64, 0x6f, 0x6d, 0x12, 0x1c, 0x0a, 0x18, 0x4c, 0x49, 0x46, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x47, 0x44, 0x4f, 0x4d, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x41, 0x52, 0x43, 0x48, 0x41, 0x45, 0x42, 0x41, 0x43, 0x54, 0x45, 0x52, 0x49, 0x41, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x45, 0x55, 0x42, 0x41, 0x43, 0x54, 0x45, 0x52, 0x49, 0x41, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x50, 0x52, 0x4f, 0x54, 0x49, 0x53, 0x54, 0x41, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x46, 0x55, 0x4e, 0x47, 0x49, 0x10, 0x04, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x4c, 0x41, 0x4e, 0x54, 0x41, 0x45, 0x10, 0x05, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x4e, 0x49, 0x4d, 0x41, 0x4c, 0x49, 0x41, 0x10, 0x06, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x70, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x5f, 0x73, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x70, 0x5f, 0x73, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x70, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x70, 0x5f, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x5f, 0x73, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x70, 0x5f, 0x73, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x70, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x70, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x5f, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x70, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x70, 0x5f, 0x6b, 0x69, 0x6e, 0x67, 0x64, 0x6f, 0x6d, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x70, 0x5f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x22, 0xd9, 0x04, 0x0a, 0x13, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x66, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x06, 0x66, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x5f, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x07, 0x66, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x66, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x42, 0x6f, 0x6f, 0x6c, 0x12, 0x43, 0x0a, 0x0b, 0x66, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x52, 0x0a, 0x66, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x12, 0x4a, 0x0a, 0x07, 0x66, 0x5f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x47, 0x72, 0x61, 0x6e, 0x64, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x52, 0x06, 0x66, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x12, 0x1e, 0x0a, 0x08, 0x70, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x07, 0x70, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x88, 0x01, 0x01, 0x12, 0x1c, 0x0a, 0x07, 0x70, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x02, 0x48, 0x01, 0x52, 0x06, 0x70, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x88, 0x01, 0x01, 0x12, 0x1e, 0x0a, 0x08, 0x70, 0x5f, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x01, 0x48, 0x02, 0x52, 0x07, 0x70, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x88, 0x01, 0x01, 0x12, 0x1a, 0x0a, 0x06, 0x70, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x48, 0x03, 0x52, 0x05, 0x70, 0x42, 0x6f, 0x6f, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x43, 0x0a, 0x0b, 0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x52, 0x0a, 0x70, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x12, 0x4f, 0x0a, 0x07, 0x70, 0x5f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x47, 0x72, 0x61, 0x6e, 0x64, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x48, 0x04, 0x52, 0x06, 0x70, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x70, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x5f, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x70, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x70, 0x5f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x22, 0x67, 0x0a, 0x18, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x47, 0x72, 0x61, 0x6e, 0x64, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x66, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x5f, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x07, 0x66, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x66, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x42, 0x6f, 0x6f, 0x6c, 0x22, 0x30, 0x0a, 0x0b, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x22, 0x90, 0x01, 0x0a, 0x0c, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x2a, 0x69, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x0a, 0x15, 0x43, 0x4f, 0x4e, 0x54, 0x49, 0x4e, 0x45, 0x4e, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x46, 0x52, 0x49, 0x43, 0x41, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x4d, 0x45, 0x52, 0x49, 0x43, 0x41, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x41, 0x4e, 0x54, 0x41, 0x52, 0x54, 0x49, 0x43, 0x41, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x41, 0x55, 0x53, 0x54, 0x52, 0x41, 0x4c, 0x49, 0x41, 0x10, 0x04, 0x12, 0x0a, 0x0a, 0x06, 0x45, 0x55, 0x52, 0x4f, 0x50, 0x45, 0x10, 0x05, 0x32, 0xd8, 0x0d, 0x0a, 0x0a, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x82, 0x01, 0x0a, 0x0e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x44, 0x61, 0x74, 0x61, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x3a, 0x01, 0x2a, 0x22, 0x14, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x3a, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x8d, 0x01, 0x0a, 0x12, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x44, 0x61, 0x74, 0x61, 0x42, 0x6f, 0x64, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x22, 0x18, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x3a, 0x62, 0x6f, 0x64, 0x79, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x81, 0x01, 0x0a, 0x0f, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x44, 0x61, 0x74, 0x61, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x3a, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0xd9, 0x01, 0x0a, 0x14, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x44, 0x61, 0x74, 0x61, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x70, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x6a, 0x12, 0x68, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x2f, 0x7b, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x66, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x7d, 0x2f, 0x7b, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x66, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x7d, 0x2f, 0x7b, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x66, 0x5f, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x7d, 0x2f, 0x7b, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x66, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x7d, 0x2f, 0x7b, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x66, 0x5f, 0x6b, 0x69, 0x6e, 0x67, 0x64, 0x6f, 0x6d, 0x7d, 0x3a, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x70, 0x61, 0x74, 0x68, 0x12, 0xd3, 0x02, 0x0a, 0x16, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x44, 0x61, 0x74, 0x61, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xe7, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0xe0, 0x01, 0x5a, 0x74, 0x12, 0x72, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x2f, 0x7b, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x66, 0x5f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x2e, 0x66, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3d, 0x66, 0x69, 0x72, 0x73, 0x74, 0x2f, 0x2a, 0x7d, 0x2f, 0x7b, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x66, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x2f, 0x2a, 0x7d, 0x2f, 0x62, 0x6f, 0x6f, 0x6c, 0x2f, 0x7b, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x66, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x7d, 0x3a, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x66, 0x69, 0x72, 0x73, 0x74, 0x70, 0x61, 0x74, 0x68, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x68, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x2f, 0x7b, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x66, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3d, 0x66, 0x69, 0x72, 0x73, 0x74, 0x2f, 0x2a, 0x7d, 0x2f, 0x7b, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x66, 0x5f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x2e, 0x66, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x2f, 0x2a, 0x7d, 0x2f, 0x62, 0x6f, 0x6f, 0x6c, 0x2f, 0x7b, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x66, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x7d, 0x3a, 0x70, 0x61, 0x74, 0x68, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0xd9, 0x01, 0x0a, 0x1e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x44, 0x61, 0x74, 0x61, 0x50, 0x61, 0x74, 0x68, 0x54, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x66, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x60, 0x12, 0x5e, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x2f, 0x7b, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x66, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3d, 0x66, 0x69, 0x72, 0x73, 0x74, 0x2f, 0x2a, 0x7d, 0x2f, 0x7b, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x66, 0x5f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x2e, 0x66, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x2f, 0x2a, 0x2a, 0x7d, 0x3a, 0x70, 0x61, 0x74, 0x68, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x88, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x44, 0x61, 0x74, 0x61, 0x42, 0x6f, 0x64, 0x79, 0x50, 0x75, 0x74, 0x12, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x3a, 0x01, 0x2a, 0x1a, 0x17, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x3a, 0x62, 0x6f, 0x64, 0x79, 0x70, 0x75, 0x74, 0x12, 0x8c, 0x01, 0x0a, 0x13, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x44, 0x61, 0x74, 0x61, 0x42, 0x6f, 0x64, 0x79, 0x50, 0x61, 0x74, 0x63, 0x68, 0x12, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x3a, 0x01, 0x2a, 0x32, 0x19, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x3a, 0x62, 0x6f, 0x64, 0x79, 0x70, 0x61, 0x74, 0x63, 0x68, 0x12, 0x78, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x2f, 0x65, 0x6e, 0x75, 0x6d, 0x12, 0x7c, 0x0a, 0x0a, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x22, 0x18, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x2f, 0x65, 0x6e, 0x75, 0x6d, 0x1a, 0x11, 0xca, 0x41, 0x0e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x3a, 0x37, 0x34, 0x36, 0x39, 0x42, 0x71, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x50, 0x01, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x67, 0x61, 0x70, 0x69, 0x63, 0x2d, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x65, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xea, 0x02, 0x19, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x3a, 0x3a, 0x53, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_google_showcase_v1beta1_compliance_proto_rawDescOnce sync.Once file_google_showcase_v1beta1_compliance_proto_rawDescData = file_google_showcase_v1beta1_compliance_proto_rawDesc ) func file_google_showcase_v1beta1_compliance_proto_rawDescGZIP() []byte { file_google_showcase_v1beta1_compliance_proto_rawDescOnce.Do(func() { file_google_showcase_v1beta1_compliance_proto_rawDescData = protoimpl.X.CompressGZIP(file_google_showcase_v1beta1_compliance_proto_rawDescData) }) return file_google_showcase_v1beta1_compliance_proto_rawDescData } var file_google_showcase_v1beta1_compliance_proto_enumTypes = make([]protoimpl.EnumInfo, 2) var file_google_showcase_v1beta1_compliance_proto_msgTypes = make([]protoimpl.MessageInfo, 9) var file_google_showcase_v1beta1_compliance_proto_goTypes = []interface{}{ (Continent)(0), // 0: google.showcase.v1beta1.Continent (ComplianceData_LifeKingdom)(0), // 1: google.showcase.v1beta1.ComplianceData.LifeKingdom (*RepeatRequest)(nil), // 2: google.showcase.v1beta1.RepeatRequest (*RepeatResponse)(nil), // 3: google.showcase.v1beta1.RepeatResponse (*ComplianceSuite)(nil), // 4: google.showcase.v1beta1.ComplianceSuite (*ComplianceGroup)(nil), // 5: google.showcase.v1beta1.ComplianceGroup (*ComplianceData)(nil), // 6: google.showcase.v1beta1.ComplianceData (*ComplianceDataChild)(nil), // 7: google.showcase.v1beta1.ComplianceDataChild (*ComplianceDataGrandchild)(nil), // 8: google.showcase.v1beta1.ComplianceDataGrandchild (*EnumRequest)(nil), // 9: google.showcase.v1beta1.EnumRequest (*EnumResponse)(nil), // 10: google.showcase.v1beta1.EnumResponse } var file_google_showcase_v1beta1_compliance_proto_depIdxs = []int32{ 6, // 0: google.showcase.v1beta1.RepeatRequest.info:type_name -> google.showcase.v1beta1.ComplianceData 2, // 1: google.showcase.v1beta1.RepeatResponse.request:type_name -> google.showcase.v1beta1.RepeatRequest 5, // 2: google.showcase.v1beta1.ComplianceSuite.group:type_name -> google.showcase.v1beta1.ComplianceGroup 2, // 3: google.showcase.v1beta1.ComplianceGroup.requests:type_name -> google.showcase.v1beta1.RepeatRequest 1, // 4: google.showcase.v1beta1.ComplianceData.f_kingdom:type_name -> google.showcase.v1beta1.ComplianceData.LifeKingdom 7, // 5: google.showcase.v1beta1.ComplianceData.f_child:type_name -> google.showcase.v1beta1.ComplianceDataChild 1, // 6: google.showcase.v1beta1.ComplianceData.p_kingdom:type_name -> google.showcase.v1beta1.ComplianceData.LifeKingdom 7, // 7: google.showcase.v1beta1.ComplianceData.p_child:type_name -> google.showcase.v1beta1.ComplianceDataChild 0, // 8: google.showcase.v1beta1.ComplianceDataChild.f_continent:type_name -> google.showcase.v1beta1.Continent 8, // 9: google.showcase.v1beta1.ComplianceDataChild.f_child:type_name -> google.showcase.v1beta1.ComplianceDataGrandchild 0, // 10: google.showcase.v1beta1.ComplianceDataChild.p_continent:type_name -> google.showcase.v1beta1.Continent 8, // 11: google.showcase.v1beta1.ComplianceDataChild.p_child:type_name -> google.showcase.v1beta1.ComplianceDataGrandchild 9, // 12: google.showcase.v1beta1.EnumResponse.request:type_name -> google.showcase.v1beta1.EnumRequest 0, // 13: google.showcase.v1beta1.EnumResponse.continent:type_name -> google.showcase.v1beta1.Continent 2, // 14: google.showcase.v1beta1.Compliance.RepeatDataBody:input_type -> google.showcase.v1beta1.RepeatRequest 2, // 15: google.showcase.v1beta1.Compliance.RepeatDataBodyInfo:input_type -> google.showcase.v1beta1.RepeatRequest 2, // 16: google.showcase.v1beta1.Compliance.RepeatDataQuery:input_type -> google.showcase.v1beta1.RepeatRequest 2, // 17: google.showcase.v1beta1.Compliance.RepeatDataSimplePath:input_type -> google.showcase.v1beta1.RepeatRequest 2, // 18: google.showcase.v1beta1.Compliance.RepeatDataPathResource:input_type -> google.showcase.v1beta1.RepeatRequest 2, // 19: google.showcase.v1beta1.Compliance.RepeatDataPathTrailingResource:input_type -> google.showcase.v1beta1.RepeatRequest 2, // 20: google.showcase.v1beta1.Compliance.RepeatDataBodyPut:input_type -> google.showcase.v1beta1.RepeatRequest 2, // 21: google.showcase.v1beta1.Compliance.RepeatDataBodyPatch:input_type -> google.showcase.v1beta1.RepeatRequest 9, // 22: google.showcase.v1beta1.Compliance.GetEnum:input_type -> google.showcase.v1beta1.EnumRequest 10, // 23: google.showcase.v1beta1.Compliance.VerifyEnum:input_type -> google.showcase.v1beta1.EnumResponse 3, // 24: google.showcase.v1beta1.Compliance.RepeatDataBody:output_type -> google.showcase.v1beta1.RepeatResponse 3, // 25: google.showcase.v1beta1.Compliance.RepeatDataBodyInfo:output_type -> google.showcase.v1beta1.RepeatResponse 3, // 26: google.showcase.v1beta1.Compliance.RepeatDataQuery:output_type -> google.showcase.v1beta1.RepeatResponse 3, // 27: google.showcase.v1beta1.Compliance.RepeatDataSimplePath:output_type -> google.showcase.v1beta1.RepeatResponse 3, // 28: google.showcase.v1beta1.Compliance.RepeatDataPathResource:output_type -> google.showcase.v1beta1.RepeatResponse 3, // 29: google.showcase.v1beta1.Compliance.RepeatDataPathTrailingResource:output_type -> google.showcase.v1beta1.RepeatResponse 3, // 30: google.showcase.v1beta1.Compliance.RepeatDataBodyPut:output_type -> google.showcase.v1beta1.RepeatResponse 3, // 31: google.showcase.v1beta1.Compliance.RepeatDataBodyPatch:output_type -> google.showcase.v1beta1.RepeatResponse 10, // 32: google.showcase.v1beta1.Compliance.GetEnum:output_type -> google.showcase.v1beta1.EnumResponse 10, // 33: google.showcase.v1beta1.Compliance.VerifyEnum:output_type -> google.showcase.v1beta1.EnumResponse 24, // [24:34] is the sub-list for method output_type 14, // [14:24] is the sub-list for method input_type 14, // [14:14] is the sub-list for extension type_name 14, // [14:14] is the sub-list for extension extendee 0, // [0:14] is the sub-list for field type_name } func init() { file_google_showcase_v1beta1_compliance_proto_init() } func file_google_showcase_v1beta1_compliance_proto_init() { if File_google_showcase_v1beta1_compliance_proto != nil { return } if !protoimpl.UnsafeEnabled { file_google_showcase_v1beta1_compliance_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RepeatRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_compliance_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RepeatResponse); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_compliance_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ComplianceSuite); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_compliance_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ComplianceGroup); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_compliance_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ComplianceData); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_compliance_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ComplianceDataChild); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_compliance_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ComplianceDataGrandchild); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_compliance_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EnumRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_compliance_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EnumResponse); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } file_google_showcase_v1beta1_compliance_proto_msgTypes[0].OneofWrappers = []interface{}{} file_google_showcase_v1beta1_compliance_proto_msgTypes[4].OneofWrappers = []interface{}{} file_google_showcase_v1beta1_compliance_proto_msgTypes[5].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_google_showcase_v1beta1_compliance_proto_rawDesc, NumEnums: 2, NumMessages: 9, NumExtensions: 0, NumServices: 1, }, GoTypes: file_google_showcase_v1beta1_compliance_proto_goTypes, DependencyIndexes: file_google_showcase_v1beta1_compliance_proto_depIdxs, EnumInfos: file_google_showcase_v1beta1_compliance_proto_enumTypes, MessageInfos: file_google_showcase_v1beta1_compliance_proto_msgTypes, }.Build() File_google_showcase_v1beta1_compliance_proto = out.File file_google_showcase_v1beta1_compliance_proto_rawDesc = nil file_google_showcase_v1beta1_compliance_proto_goTypes = nil file_google_showcase_v1beta1_compliance_proto_depIdxs = nil } // Reference imports to suppress errors if they are not otherwise used. var _ context.Context var _ grpc.ClientConnInterface // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. const _ = grpc.SupportPackageIsVersion6 // ComplianceClient is the client API for Compliance service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type ComplianceClient interface { // This method echoes the ComplianceData request. This method exercises // sending the entire request object in the REST body. RepeatDataBody(ctx context.Context, in *RepeatRequest, opts ...grpc.CallOption) (*RepeatResponse, error) // This method echoes the ComplianceData request. This method exercises // sending the a message-type field in the REST body. Per AIP-127, only // top-level, non-repeated fields can be sent this way. RepeatDataBodyInfo(ctx context.Context, in *RepeatRequest, opts ...grpc.CallOption) (*RepeatResponse, error) // This method echoes the ComplianceData request. This method exercises // sending all request fields as query parameters. RepeatDataQuery(ctx context.Context, in *RepeatRequest, opts ...grpc.CallOption) (*RepeatResponse, error) // This method echoes the ComplianceData request. This method exercises // sending some parameters as "simple" path variables (i.e., of the form // "/bar/{foo}" rather than "/{foo=bar/*}"), and the rest as query parameters. RepeatDataSimplePath(ctx context.Context, in *RepeatRequest, opts ...grpc.CallOption) (*RepeatResponse, error) // Same as RepeatDataSimplePath, but with a path resource. RepeatDataPathResource(ctx context.Context, in *RepeatRequest, opts ...grpc.CallOption) (*RepeatResponse, error) // Same as RepeatDataSimplePath, but with a trailing resource. RepeatDataPathTrailingResource(ctx context.Context, in *RepeatRequest, opts ...grpc.CallOption) (*RepeatResponse, error) // This method echoes the ComplianceData request, using the HTTP PUT method. RepeatDataBodyPut(ctx context.Context, in *RepeatRequest, opts ...grpc.CallOption) (*RepeatResponse, error) // This method echoes the ComplianceData request, using the HTTP PATCH method. RepeatDataBodyPatch(ctx context.Context, in *RepeatRequest, opts ...grpc.CallOption) (*RepeatResponse, error) // This method requests an enum value from the server. Depending on the contents of EnumRequest, the enum value returned will be a known enum declared in the // .proto file, or a made-up enum value the is unknown to the client. To verify that clients can round-trip unknown enum values they receive, use the // response from this RPC as the request to VerifyEnum() // // The values of enums sent by the server when a known or unknown value is requested will be the same within a single Showcase server run (this is needed for // VerifyEnum() to work) but are not guaranteed to be the same across separate Showcase server runs. GetEnum(ctx context.Context, in *EnumRequest, opts ...grpc.CallOption) (*EnumResponse, error) // This method is used to verify that clients can round-trip enum values, which is particularly important for unknown enum values over REST. VerifyEnum() // verifies that its request, which is presumably the response that the client previously got to a GetEnum(), contains the correct data. If so, it responds // with the same EnumResponse; otherwise, the RPC errors. // // This works because the values of enums sent by the server when a known or unknown value is requested will be the same within a single Showcase server run, // although they are not guaranteed to be the same across separate Showcase server runs. VerifyEnum(ctx context.Context, in *EnumResponse, opts ...grpc.CallOption) (*EnumResponse, error) } type complianceClient struct { cc grpc.ClientConnInterface } func NewComplianceClient(cc grpc.ClientConnInterface) ComplianceClient { return &complianceClient{cc} } func (c *complianceClient) RepeatDataBody(ctx context.Context, in *RepeatRequest, opts ...grpc.CallOption) (*RepeatResponse, error) { out := new(RepeatResponse) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Compliance/RepeatDataBody", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *complianceClient) RepeatDataBodyInfo(ctx context.Context, in *RepeatRequest, opts ...grpc.CallOption) (*RepeatResponse, error) { out := new(RepeatResponse) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Compliance/RepeatDataBodyInfo", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *complianceClient) RepeatDataQuery(ctx context.Context, in *RepeatRequest, opts ...grpc.CallOption) (*RepeatResponse, error) { out := new(RepeatResponse) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Compliance/RepeatDataQuery", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *complianceClient) RepeatDataSimplePath(ctx context.Context, in *RepeatRequest, opts ...grpc.CallOption) (*RepeatResponse, error) { out := new(RepeatResponse) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Compliance/RepeatDataSimplePath", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *complianceClient) RepeatDataPathResource(ctx context.Context, in *RepeatRequest, opts ...grpc.CallOption) (*RepeatResponse, error) { out := new(RepeatResponse) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Compliance/RepeatDataPathResource", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *complianceClient) RepeatDataPathTrailingResource(ctx context.Context, in *RepeatRequest, opts ...grpc.CallOption) (*RepeatResponse, error) { out := new(RepeatResponse) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Compliance/RepeatDataPathTrailingResource", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *complianceClient) RepeatDataBodyPut(ctx context.Context, in *RepeatRequest, opts ...grpc.CallOption) (*RepeatResponse, error) { out := new(RepeatResponse) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Compliance/RepeatDataBodyPut", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *complianceClient) RepeatDataBodyPatch(ctx context.Context, in *RepeatRequest, opts ...grpc.CallOption) (*RepeatResponse, error) { out := new(RepeatResponse) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Compliance/RepeatDataBodyPatch", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *complianceClient) GetEnum(ctx context.Context, in *EnumRequest, opts ...grpc.CallOption) (*EnumResponse, error) { out := new(EnumResponse) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Compliance/GetEnum", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *complianceClient) VerifyEnum(ctx context.Context, in *EnumResponse, opts ...grpc.CallOption) (*EnumResponse, error) { out := new(EnumResponse) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Compliance/VerifyEnum", in, out, opts...) if err != nil { return nil, err } return out, nil } // ComplianceServer is the server API for Compliance service. type ComplianceServer interface { // This method echoes the ComplianceData request. This method exercises // sending the entire request object in the REST body. RepeatDataBody(context.Context, *RepeatRequest) (*RepeatResponse, error) // This method echoes the ComplianceData request. This method exercises // sending the a message-type field in the REST body. Per AIP-127, only // top-level, non-repeated fields can be sent this way. RepeatDataBodyInfo(context.Context, *RepeatRequest) (*RepeatResponse, error) // This method echoes the ComplianceData request. This method exercises // sending all request fields as query parameters. RepeatDataQuery(context.Context, *RepeatRequest) (*RepeatResponse, error) // This method echoes the ComplianceData request. This method exercises // sending some parameters as "simple" path variables (i.e., of the form // "/bar/{foo}" rather than "/{foo=bar/*}"), and the rest as query parameters. RepeatDataSimplePath(context.Context, *RepeatRequest) (*RepeatResponse, error) // Same as RepeatDataSimplePath, but with a path resource. RepeatDataPathResource(context.Context, *RepeatRequest) (*RepeatResponse, error) // Same as RepeatDataSimplePath, but with a trailing resource. RepeatDataPathTrailingResource(context.Context, *RepeatRequest) (*RepeatResponse, error) // This method echoes the ComplianceData request, using the HTTP PUT method. RepeatDataBodyPut(context.Context, *RepeatRequest) (*RepeatResponse, error) // This method echoes the ComplianceData request, using the HTTP PATCH method. RepeatDataBodyPatch(context.Context, *RepeatRequest) (*RepeatResponse, error) // This method requests an enum value from the server. Depending on the contents of EnumRequest, the enum value returned will be a known enum declared in the // .proto file, or a made-up enum value the is unknown to the client. To verify that clients can round-trip unknown enum values they receive, use the // response from this RPC as the request to VerifyEnum() // // The values of enums sent by the server when a known or unknown value is requested will be the same within a single Showcase server run (this is needed for // VerifyEnum() to work) but are not guaranteed to be the same across separate Showcase server runs. GetEnum(context.Context, *EnumRequest) (*EnumResponse, error) // This method is used to verify that clients can round-trip enum values, which is particularly important for unknown enum values over REST. VerifyEnum() // verifies that its request, which is presumably the response that the client previously got to a GetEnum(), contains the correct data. If so, it responds // with the same EnumResponse; otherwise, the RPC errors. // // This works because the values of enums sent by the server when a known or unknown value is requested will be the same within a single Showcase server run, // although they are not guaranteed to be the same across separate Showcase server runs. VerifyEnum(context.Context, *EnumResponse) (*EnumResponse, error) } // UnimplementedComplianceServer can be embedded to have forward compatible implementations. type UnimplementedComplianceServer struct { } func (*UnimplementedComplianceServer) RepeatDataBody(context.Context, *RepeatRequest) (*RepeatResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method RepeatDataBody not implemented") } func (*UnimplementedComplianceServer) RepeatDataBodyInfo(context.Context, *RepeatRequest) (*RepeatResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method RepeatDataBodyInfo not implemented") } func (*UnimplementedComplianceServer) RepeatDataQuery(context.Context, *RepeatRequest) (*RepeatResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method RepeatDataQuery not implemented") } func (*UnimplementedComplianceServer) RepeatDataSimplePath(context.Context, *RepeatRequest) (*RepeatResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method RepeatDataSimplePath not implemented") } func (*UnimplementedComplianceServer) RepeatDataPathResource(context.Context, *RepeatRequest) (*RepeatResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method RepeatDataPathResource not implemented") } func (*UnimplementedComplianceServer) RepeatDataPathTrailingResource(context.Context, *RepeatRequest) (*RepeatResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method RepeatDataPathTrailingResource not implemented") } func (*UnimplementedComplianceServer) RepeatDataBodyPut(context.Context, *RepeatRequest) (*RepeatResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method RepeatDataBodyPut not implemented") } func (*UnimplementedComplianceServer) RepeatDataBodyPatch(context.Context, *RepeatRequest) (*RepeatResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method RepeatDataBodyPatch not implemented") } func (*UnimplementedComplianceServer) GetEnum(context.Context, *EnumRequest) (*EnumResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetEnum not implemented") } func (*UnimplementedComplianceServer) VerifyEnum(context.Context, *EnumResponse) (*EnumResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method VerifyEnum not implemented") } func RegisterComplianceServer(s *grpc.Server, srv ComplianceServer) { s.RegisterService(&_Compliance_serviceDesc, srv) } func _Compliance_RepeatDataBody_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(RepeatRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(ComplianceServer).RepeatDataBody(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Compliance/RepeatDataBody", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ComplianceServer).RepeatDataBody(ctx, req.(*RepeatRequest)) } return interceptor(ctx, in, info, handler) } func _Compliance_RepeatDataBodyInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(RepeatRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(ComplianceServer).RepeatDataBodyInfo(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Compliance/RepeatDataBodyInfo", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ComplianceServer).RepeatDataBodyInfo(ctx, req.(*RepeatRequest)) } return interceptor(ctx, in, info, handler) } func _Compliance_RepeatDataQuery_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(RepeatRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(ComplianceServer).RepeatDataQuery(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Compliance/RepeatDataQuery", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ComplianceServer).RepeatDataQuery(ctx, req.(*RepeatRequest)) } return interceptor(ctx, in, info, handler) } func _Compliance_RepeatDataSimplePath_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(RepeatRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(ComplianceServer).RepeatDataSimplePath(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Compliance/RepeatDataSimplePath", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ComplianceServer).RepeatDataSimplePath(ctx, req.(*RepeatRequest)) } return interceptor(ctx, in, info, handler) } func _Compliance_RepeatDataPathResource_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(RepeatRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(ComplianceServer).RepeatDataPathResource(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Compliance/RepeatDataPathResource", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ComplianceServer).RepeatDataPathResource(ctx, req.(*RepeatRequest)) } return interceptor(ctx, in, info, handler) } func _Compliance_RepeatDataPathTrailingResource_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(RepeatRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(ComplianceServer).RepeatDataPathTrailingResource(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Compliance/RepeatDataPathTrailingResource", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ComplianceServer).RepeatDataPathTrailingResource(ctx, req.(*RepeatRequest)) } return interceptor(ctx, in, info, handler) } func _Compliance_RepeatDataBodyPut_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(RepeatRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(ComplianceServer).RepeatDataBodyPut(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Compliance/RepeatDataBodyPut", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ComplianceServer).RepeatDataBodyPut(ctx, req.(*RepeatRequest)) } return interceptor(ctx, in, info, handler) } func _Compliance_RepeatDataBodyPatch_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(RepeatRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(ComplianceServer).RepeatDataBodyPatch(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Compliance/RepeatDataBodyPatch", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ComplianceServer).RepeatDataBodyPatch(ctx, req.(*RepeatRequest)) } return interceptor(ctx, in, info, handler) } func _Compliance_GetEnum_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(EnumRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(ComplianceServer).GetEnum(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Compliance/GetEnum", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ComplianceServer).GetEnum(ctx, req.(*EnumRequest)) } return interceptor(ctx, in, info, handler) } func _Compliance_VerifyEnum_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(EnumResponse) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(ComplianceServer).VerifyEnum(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Compliance/VerifyEnum", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ComplianceServer).VerifyEnum(ctx, req.(*EnumResponse)) } return interceptor(ctx, in, info, handler) } var _Compliance_serviceDesc = grpc.ServiceDesc{ ServiceName: "google.showcase.v1beta1.Compliance", HandlerType: (*ComplianceServer)(nil), Methods: []grpc.MethodDesc{ { MethodName: "RepeatDataBody", Handler: _Compliance_RepeatDataBody_Handler, }, { MethodName: "RepeatDataBodyInfo", Handler: _Compliance_RepeatDataBodyInfo_Handler, }, { MethodName: "RepeatDataQuery", Handler: _Compliance_RepeatDataQuery_Handler, }, { MethodName: "RepeatDataSimplePath", Handler: _Compliance_RepeatDataSimplePath_Handler, }, { MethodName: "RepeatDataPathResource", Handler: _Compliance_RepeatDataPathResource_Handler, }, { MethodName: "RepeatDataPathTrailingResource", Handler: _Compliance_RepeatDataPathTrailingResource_Handler, }, { MethodName: "RepeatDataBodyPut", Handler: _Compliance_RepeatDataBodyPut_Handler, }, { MethodName: "RepeatDataBodyPatch", Handler: _Compliance_RepeatDataBodyPatch_Handler, }, { MethodName: "GetEnum", Handler: _Compliance_GetEnum_Handler, }, { MethodName: "VerifyEnum", Handler: _Compliance_VerifyEnum_Handler, }, }, Streams: []grpc.StreamDesc{}, Metadata: "google/showcase/v1beta1/compliance.proto", } ================================================ FILE: server/genproto/echo.pb.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.33.0 // protoc v3.20.3 // source: google/showcase/v1beta1/echo.proto package genproto import ( longrunningpb "cloud.google.com/go/longrunning/autogen/longrunningpb" context "context" _ "google.golang.org/genproto/googleapis/api/annotations" status "google.golang.org/genproto/googleapis/rpc/status" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status1 "google.golang.org/grpc/status" 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" timestamppb "google.golang.org/protobuf/types/known/timestamppb" 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) ) // A severity enum used to test enum capabilities in GAPIC surfaces. type Severity int32 const ( Severity_UNNECESSARY Severity = 0 Severity_NECESSARY Severity = 1 Severity_URGENT Severity = 2 Severity_CRITICAL Severity = 3 ) // Enum value maps for Severity. var ( Severity_name = map[int32]string{ 0: "UNNECESSARY", 1: "NECESSARY", 2: "URGENT", 3: "CRITICAL", } Severity_value = map[string]int32{ "UNNECESSARY": 0, "NECESSARY": 1, "URGENT": 2, "CRITICAL": 3, } ) func (x Severity) Enum() *Severity { p := new(Severity) *p = x return p } func (x Severity) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (Severity) Descriptor() protoreflect.EnumDescriptor { return file_google_showcase_v1beta1_echo_proto_enumTypes[0].Descriptor() } func (Severity) Type() protoreflect.EnumType { return &file_google_showcase_v1beta1_echo_proto_enumTypes[0] } func (x Severity) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use Severity.Descriptor instead. func (Severity) EnumDescriptor() ([]byte, []int) { return file_google_showcase_v1beta1_echo_proto_rawDescGZIP(), []int{0} } // The request message used for the Echo, Collect and Chat methods. // If content or opt are set in this message then the request will succeed. // If status is set in this message then the status will be returned as an // error. type EchoRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Types that are assignable to Response: // // *EchoRequest_Content // *EchoRequest_Error Response isEchoRequest_Response `protobuf_oneof:"response"` // The severity to be echoed by the server. Severity Severity `protobuf:"varint,3,opt,name=severity,proto3,enum=google.showcase.v1beta1.Severity" json:"severity,omitempty"` // Optional. This field can be set to test the routing annotation on the Echo method. Header string `protobuf:"bytes,4,opt,name=header,proto3" json:"header,omitempty"` // Optional. This field can be set to test the routing annotation on the Echo method. OtherHeader string `protobuf:"bytes,5,opt,name=other_header,json=otherHeader,proto3" json:"other_header,omitempty"` // To facilitate testing of https://google.aip.dev/client-libraries/4235 RequestId string `protobuf:"bytes,7,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` // To facilitate testing of https://google.aip.dev/client-libraries/4235 OtherRequestId *string `protobuf:"bytes,8,opt,name=other_request_id,json=otherRequestId,proto3,oneof" json:"other_request_id,omitempty"` } func (x *EchoRequest) Reset() { *x = EchoRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EchoRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*EchoRequest) ProtoMessage() {} func (x *EchoRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_echo_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 EchoRequest.ProtoReflect.Descriptor instead. func (*EchoRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_echo_proto_rawDescGZIP(), []int{0} } func (m *EchoRequest) GetResponse() isEchoRequest_Response { if m != nil { return m.Response } return nil } func (x *EchoRequest) GetContent() string { if x, ok := x.GetResponse().(*EchoRequest_Content); ok { return x.Content } return "" } func (x *EchoRequest) GetError() *status.Status { if x, ok := x.GetResponse().(*EchoRequest_Error); ok { return x.Error } return nil } func (x *EchoRequest) GetSeverity() Severity { if x != nil { return x.Severity } return Severity_UNNECESSARY } func (x *EchoRequest) GetHeader() string { if x != nil { return x.Header } return "" } func (x *EchoRequest) GetOtherHeader() string { if x != nil { return x.OtherHeader } return "" } func (x *EchoRequest) GetRequestId() string { if x != nil { return x.RequestId } return "" } func (x *EchoRequest) GetOtherRequestId() string { if x != nil && x.OtherRequestId != nil { return *x.OtherRequestId } return "" } type isEchoRequest_Response interface { isEchoRequest_Response() } type EchoRequest_Content struct { // The content to be echoed by the server. Content string `protobuf:"bytes,1,opt,name=content,proto3,oneof"` } type EchoRequest_Error struct { // The error to be thrown by the server. Error *status.Status `protobuf:"bytes,2,opt,name=error,proto3,oneof"` } func (*EchoRequest_Content) isEchoRequest_Response() {} func (*EchoRequest_Error) isEchoRequest_Response() {} // The response message for the Echo methods. type EchoResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The content specified in the request. Content string `protobuf:"bytes,1,opt,name=content,proto3" json:"content,omitempty"` // The severity specified in the request. Severity Severity `protobuf:"varint,2,opt,name=severity,proto3,enum=google.showcase.v1beta1.Severity" json:"severity,omitempty"` // The request ID specified or autopopulated in the request. RequestId string `protobuf:"bytes,3,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` // The other request ID specified or autopopulated in the request. OtherRequestId string `protobuf:"bytes,4,opt,name=other_request_id,json=otherRequestId,proto3" json:"other_request_id,omitempty"` } func (x *EchoResponse) Reset() { *x = EchoResponse{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EchoResponse) String() string { return protoimpl.X.MessageStringOf(x) } func (*EchoResponse) ProtoMessage() {} func (x *EchoResponse) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[1] 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 EchoResponse.ProtoReflect.Descriptor instead. func (*EchoResponse) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_echo_proto_rawDescGZIP(), []int{1} } func (x *EchoResponse) GetContent() string { if x != nil { return x.Content } return "" } func (x *EchoResponse) GetSeverity() Severity { if x != nil { return x.Severity } return Severity_UNNECESSARY } func (x *EchoResponse) GetRequestId() string { if x != nil { return x.RequestId } return "" } func (x *EchoResponse) GetOtherRequestId() string { if x != nil { return x.OtherRequestId } return "" } // The request message used for the EchoErrorDetails method. type EchoErrorDetailsRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Content to return in a singular `*.error.details` field of type // `google.protobuf.Any` SingleDetailText string `protobuf:"bytes,1,opt,name=single_detail_text,json=singleDetailText,proto3" json:"single_detail_text,omitempty"` // Content to return in a repeated `*.error.details` field of type // `google.protobuf.Any` MultiDetailText []string `protobuf:"bytes,2,rep,name=multi_detail_text,json=multiDetailText,proto3" json:"multi_detail_text,omitempty"` } func (x *EchoErrorDetailsRequest) Reset() { *x = EchoErrorDetailsRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EchoErrorDetailsRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*EchoErrorDetailsRequest) ProtoMessage() {} func (x *EchoErrorDetailsRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[2] 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 EchoErrorDetailsRequest.ProtoReflect.Descriptor instead. func (*EchoErrorDetailsRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_echo_proto_rawDescGZIP(), []int{2} } func (x *EchoErrorDetailsRequest) GetSingleDetailText() string { if x != nil { return x.SingleDetailText } return "" } func (x *EchoErrorDetailsRequest) GetMultiDetailText() []string { if x != nil { return x.MultiDetailText } return nil } // The response message used for the EchoErrorDetails method. type EchoErrorDetailsResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields SingleDetail *EchoErrorDetailsResponse_SingleDetail `protobuf:"bytes,1,opt,name=single_detail,json=singleDetail,proto3" json:"single_detail,omitempty"` MultipleDetails *EchoErrorDetailsResponse_MultipleDetails `protobuf:"bytes,2,opt,name=multiple_details,json=multipleDetails,proto3" json:"multiple_details,omitempty"` } func (x *EchoErrorDetailsResponse) Reset() { *x = EchoErrorDetailsResponse{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EchoErrorDetailsResponse) String() string { return protoimpl.X.MessageStringOf(x) } func (*EchoErrorDetailsResponse) ProtoMessage() {} func (x *EchoErrorDetailsResponse) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[3] 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 EchoErrorDetailsResponse.ProtoReflect.Descriptor instead. func (*EchoErrorDetailsResponse) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_echo_proto_rawDescGZIP(), []int{3} } func (x *EchoErrorDetailsResponse) GetSingleDetail() *EchoErrorDetailsResponse_SingleDetail { if x != nil { return x.SingleDetail } return nil } func (x *EchoErrorDetailsResponse) GetMultipleDetails() *EchoErrorDetailsResponse_MultipleDetails { if x != nil { return x.MultipleDetails } return nil } type ErrorWithSingleDetail struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Details *anypb.Any `protobuf:"bytes,1,opt,name=details,proto3" json:"details,omitempty"` } func (x *ErrorWithSingleDetail) Reset() { *x = ErrorWithSingleDetail{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ErrorWithSingleDetail) String() string { return protoimpl.X.MessageStringOf(x) } func (*ErrorWithSingleDetail) ProtoMessage() {} func (x *ErrorWithSingleDetail) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[4] 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 ErrorWithSingleDetail.ProtoReflect.Descriptor instead. func (*ErrorWithSingleDetail) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_echo_proto_rawDescGZIP(), []int{4} } func (x *ErrorWithSingleDetail) GetDetails() *anypb.Any { if x != nil { return x.Details } return nil } type ErrorWithMultipleDetails struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Details []*anypb.Any `protobuf:"bytes,1,rep,name=details,proto3" json:"details,omitempty"` } func (x *ErrorWithMultipleDetails) Reset() { *x = ErrorWithMultipleDetails{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ErrorWithMultipleDetails) String() string { return protoimpl.X.MessageStringOf(x) } func (*ErrorWithMultipleDetails) ProtoMessage() {} func (x *ErrorWithMultipleDetails) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[5] 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 ErrorWithMultipleDetails.ProtoReflect.Descriptor instead. func (*ErrorWithMultipleDetails) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_echo_proto_rawDescGZIP(), []int{5} } func (x *ErrorWithMultipleDetails) GetDetails() []*anypb.Any { if x != nil { return x.Details } return nil } // The custom error detail to be included in the error response from the // FailEchoWithDetails method. Client libraries should be able to // surface this custom error detail. type PoetryError struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Poem string `protobuf:"bytes,1,opt,name=poem,proto3" json:"poem,omitempty"` } func (x *PoetryError) Reset() { *x = PoetryError{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *PoetryError) String() string { return protoimpl.X.MessageStringOf(x) } func (*PoetryError) ProtoMessage() {} func (x *PoetryError) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[6] 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 PoetryError.ProtoReflect.Descriptor instead. func (*PoetryError) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_echo_proto_rawDescGZIP(), []int{6} } func (x *PoetryError) GetPoem() string { if x != nil { return x.Poem } return "" } // The request message used for the FailEchoWithDetails method. type FailEchoWithDetailsRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Optional message to echo back in the PoetryError. If empty, a value will be // provided. Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` } func (x *FailEchoWithDetailsRequest) Reset() { *x = FailEchoWithDetailsRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *FailEchoWithDetailsRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*FailEchoWithDetailsRequest) ProtoMessage() {} func (x *FailEchoWithDetailsRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[7] 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 FailEchoWithDetailsRequest.ProtoReflect.Descriptor instead. func (*FailEchoWithDetailsRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_echo_proto_rawDescGZIP(), []int{7} } func (x *FailEchoWithDetailsRequest) GetMessage() string { if x != nil { return x.Message } return "" } // The response message declared (but never used) for the FailEchoWithDetails // method. type FailEchoWithDetailsResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields } func (x *FailEchoWithDetailsResponse) Reset() { *x = FailEchoWithDetailsResponse{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *FailEchoWithDetailsResponse) String() string { return protoimpl.X.MessageStringOf(x) } func (*FailEchoWithDetailsResponse) ProtoMessage() {} func (x *FailEchoWithDetailsResponse) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[8] 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 FailEchoWithDetailsResponse.ProtoReflect.Descriptor instead. func (*FailEchoWithDetailsResponse) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_echo_proto_rawDescGZIP(), []int{8} } // The request message for the Expand method. type ExpandRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The content that will be split into words and returned on the stream. Content string `protobuf:"bytes,1,opt,name=content,proto3" json:"content,omitempty"` // The error that is thrown after all words are sent on the stream. Error *status.Status `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` // The wait time between each server streaming messages StreamWaitTime *durationpb.Duration `protobuf:"bytes,3,opt,name=stream_wait_time,json=streamWaitTime,proto3" json:"stream_wait_time,omitempty"` } func (x *ExpandRequest) Reset() { *x = ExpandRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ExpandRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*ExpandRequest) ProtoMessage() {} func (x *ExpandRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[9] 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 ExpandRequest.ProtoReflect.Descriptor instead. func (*ExpandRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_echo_proto_rawDescGZIP(), []int{9} } func (x *ExpandRequest) GetContent() string { if x != nil { return x.Content } return "" } func (x *ExpandRequest) GetError() *status.Status { if x != nil { return x.Error } return nil } func (x *ExpandRequest) GetStreamWaitTime() *durationpb.Duration { if x != nil { return x.StreamWaitTime } return nil } // The request for the PagedExpand method. type PagedExpandRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The string to expand. Content string `protobuf:"bytes,1,opt,name=content,proto3" json:"content,omitempty"` // The number of words to returned in each page. PageSize int32 `protobuf:"varint,2,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` // The position of the page to be returned. PageToken string `protobuf:"bytes,3,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` } func (x *PagedExpandRequest) Reset() { *x = PagedExpandRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *PagedExpandRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*PagedExpandRequest) ProtoMessage() {} func (x *PagedExpandRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[10] 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 PagedExpandRequest.ProtoReflect.Descriptor instead. func (*PagedExpandRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_echo_proto_rawDescGZIP(), []int{10} } func (x *PagedExpandRequest) GetContent() string { if x != nil { return x.Content } return "" } func (x *PagedExpandRequest) GetPageSize() int32 { if x != nil { return x.PageSize } return 0 } func (x *PagedExpandRequest) GetPageToken() string { if x != nil { return x.PageToken } return "" } // The request for the PagedExpandLegacy method. This is a pattern used by some legacy APIs. New // APIs should NOT use this pattern, but rather something like PagedExpandRequest which conforms to // aip.dev/158. type PagedExpandLegacyRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The string to expand. Content string `protobuf:"bytes,1,opt,name=content,proto3" json:"content,omitempty"` // The number of words to returned in each page. // (-- aip.dev/not-precedent: This is a legacy, non-standard pattern that // // violates aip.dev/158. Ordinarily, this should be page_size. --) MaxResults int32 `protobuf:"varint,2,opt,name=max_results,json=maxResults,proto3" json:"max_results,omitempty"` // The position of the page to be returned. PageToken string `protobuf:"bytes,3,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` } func (x *PagedExpandLegacyRequest) Reset() { *x = PagedExpandLegacyRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *PagedExpandLegacyRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*PagedExpandLegacyRequest) ProtoMessage() {} func (x *PagedExpandLegacyRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[11] 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 PagedExpandLegacyRequest.ProtoReflect.Descriptor instead. func (*PagedExpandLegacyRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_echo_proto_rawDescGZIP(), []int{11} } func (x *PagedExpandLegacyRequest) GetContent() string { if x != nil { return x.Content } return "" } func (x *PagedExpandLegacyRequest) GetMaxResults() int32 { if x != nil { return x.MaxResults } return 0 } func (x *PagedExpandLegacyRequest) GetPageToken() string { if x != nil { return x.PageToken } return "" } // The response for the PagedExpand method. type PagedExpandResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The words that were expanded. Responses []*EchoResponse `protobuf:"bytes,1,rep,name=responses,proto3" json:"responses,omitempty"` // The next page token. NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` } func (x *PagedExpandResponse) Reset() { *x = PagedExpandResponse{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *PagedExpandResponse) String() string { return protoimpl.X.MessageStringOf(x) } func (*PagedExpandResponse) ProtoMessage() {} func (x *PagedExpandResponse) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[12] 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 PagedExpandResponse.ProtoReflect.Descriptor instead. func (*PagedExpandResponse) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_echo_proto_rawDescGZIP(), []int{12} } func (x *PagedExpandResponse) GetResponses() []*EchoResponse { if x != nil { return x.Responses } return nil } func (x *PagedExpandResponse) GetNextPageToken() string { if x != nil { return x.NextPageToken } return "" } // A list of words. type PagedExpandResponseList struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Words []string `protobuf:"bytes,1,rep,name=words,proto3" json:"words,omitempty"` } func (x *PagedExpandResponseList) Reset() { *x = PagedExpandResponseList{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *PagedExpandResponseList) String() string { return protoimpl.X.MessageStringOf(x) } func (*PagedExpandResponseList) ProtoMessage() {} func (x *PagedExpandResponseList) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[13] 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 PagedExpandResponseList.ProtoReflect.Descriptor instead. func (*PagedExpandResponseList) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_echo_proto_rawDescGZIP(), []int{13} } func (x *PagedExpandResponseList) GetWords() []string { if x != nil { return x.Words } return nil } type PagedExpandLegacyMappedResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The words that were expanded, indexed by their initial character. // (-- aip.dev/not-precedent: This is a legacy, non-standard pattern that violates // // aip.dev/158. Ordinarily, this should be a `repeated` field, as in PagedExpandResponse. --) Alphabetized map[string]*PagedExpandResponseList `protobuf:"bytes,1,rep,name=alphabetized,proto3" json:"alphabetized,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // The next page token. NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` } func (x *PagedExpandLegacyMappedResponse) Reset() { *x = PagedExpandLegacyMappedResponse{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *PagedExpandLegacyMappedResponse) String() string { return protoimpl.X.MessageStringOf(x) } func (*PagedExpandLegacyMappedResponse) ProtoMessage() {} func (x *PagedExpandLegacyMappedResponse) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[14] 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 PagedExpandLegacyMappedResponse.ProtoReflect.Descriptor instead. func (*PagedExpandLegacyMappedResponse) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_echo_proto_rawDescGZIP(), []int{14} } func (x *PagedExpandLegacyMappedResponse) GetAlphabetized() map[string]*PagedExpandResponseList { if x != nil { return x.Alphabetized } return nil } func (x *PagedExpandLegacyMappedResponse) GetNextPageToken() string { if x != nil { return x.NextPageToken } return "" } // The request for Wait method. type WaitRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Types that are assignable to End: // // *WaitRequest_EndTime // *WaitRequest_Ttl End isWaitRequest_End `protobuf_oneof:"end"` // Types that are assignable to Response: // // *WaitRequest_Error // *WaitRequest_Success Response isWaitRequest_Response `protobuf_oneof:"response"` } func (x *WaitRequest) Reset() { *x = WaitRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *WaitRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*WaitRequest) ProtoMessage() {} func (x *WaitRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[15] 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 WaitRequest.ProtoReflect.Descriptor instead. func (*WaitRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_echo_proto_rawDescGZIP(), []int{15} } func (m *WaitRequest) GetEnd() isWaitRequest_End { if m != nil { return m.End } return nil } func (x *WaitRequest) GetEndTime() *timestamppb.Timestamp { if x, ok := x.GetEnd().(*WaitRequest_EndTime); ok { return x.EndTime } return nil } func (x *WaitRequest) GetTtl() *durationpb.Duration { if x, ok := x.GetEnd().(*WaitRequest_Ttl); ok { return x.Ttl } return nil } func (m *WaitRequest) GetResponse() isWaitRequest_Response { if m != nil { return m.Response } return nil } func (x *WaitRequest) GetError() *status.Status { if x, ok := x.GetResponse().(*WaitRequest_Error); ok { return x.Error } return nil } func (x *WaitRequest) GetSuccess() *WaitResponse { if x, ok := x.GetResponse().(*WaitRequest_Success); ok { return x.Success } return nil } type isWaitRequest_End interface { isWaitRequest_End() } type WaitRequest_EndTime struct { // The time that this operation will complete. EndTime *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=end_time,json=endTime,proto3,oneof"` } type WaitRequest_Ttl struct { // The duration of this operation. Ttl *durationpb.Duration `protobuf:"bytes,4,opt,name=ttl,proto3,oneof"` } func (*WaitRequest_EndTime) isWaitRequest_End() {} func (*WaitRequest_Ttl) isWaitRequest_End() {} type isWaitRequest_Response interface { isWaitRequest_Response() } type WaitRequest_Error struct { // The error that will be returned by the server. If this code is specified // to be the OK rpc code, an empty response will be returned. Error *status.Status `protobuf:"bytes,2,opt,name=error,proto3,oneof"` } type WaitRequest_Success struct { // The response to be returned on operation completion. Success *WaitResponse `protobuf:"bytes,3,opt,name=success,proto3,oneof"` } func (*WaitRequest_Error) isWaitRequest_Response() {} func (*WaitRequest_Success) isWaitRequest_Response() {} // The result of the Wait operation. type WaitResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // This content of the result. Content string `protobuf:"bytes,1,opt,name=content,proto3" json:"content,omitempty"` } func (x *WaitResponse) Reset() { *x = WaitResponse{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *WaitResponse) String() string { return protoimpl.X.MessageStringOf(x) } func (*WaitResponse) ProtoMessage() {} func (x *WaitResponse) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[16] 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 WaitResponse.ProtoReflect.Descriptor instead. func (*WaitResponse) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_echo_proto_rawDescGZIP(), []int{16} } func (x *WaitResponse) GetContent() string { if x != nil { return x.Content } return "" } // The metadata for Wait operation. type WaitMetadata struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The time that this operation will complete. EndTime *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=end_time,json=endTime,proto3" json:"end_time,omitempty"` } func (x *WaitMetadata) Reset() { *x = WaitMetadata{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *WaitMetadata) String() string { return protoimpl.X.MessageStringOf(x) } func (*WaitMetadata) ProtoMessage() {} func (x *WaitMetadata) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[17] 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 WaitMetadata.ProtoReflect.Descriptor instead. func (*WaitMetadata) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_echo_proto_rawDescGZIP(), []int{17} } func (x *WaitMetadata) GetEndTime() *timestamppb.Timestamp { if x != nil { return x.EndTime } return nil } // The request for Block method. type BlockRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The amount of time to block before returning a response. ResponseDelay *durationpb.Duration `protobuf:"bytes,1,opt,name=response_delay,json=responseDelay,proto3" json:"response_delay,omitempty"` // Types that are assignable to Response: // // *BlockRequest_Error // *BlockRequest_Success Response isBlockRequest_Response `protobuf_oneof:"response"` } func (x *BlockRequest) Reset() { *x = BlockRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *BlockRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*BlockRequest) ProtoMessage() {} func (x *BlockRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[18] 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 BlockRequest.ProtoReflect.Descriptor instead. func (*BlockRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_echo_proto_rawDescGZIP(), []int{18} } func (x *BlockRequest) GetResponseDelay() *durationpb.Duration { if x != nil { return x.ResponseDelay } return nil } func (m *BlockRequest) GetResponse() isBlockRequest_Response { if m != nil { return m.Response } return nil } func (x *BlockRequest) GetError() *status.Status { if x, ok := x.GetResponse().(*BlockRequest_Error); ok { return x.Error } return nil } func (x *BlockRequest) GetSuccess() *BlockResponse { if x, ok := x.GetResponse().(*BlockRequest_Success); ok { return x.Success } return nil } type isBlockRequest_Response interface { isBlockRequest_Response() } type BlockRequest_Error struct { // The error that will be returned by the server. If this code is specified // to be the OK rpc code, an empty response will be returned. Error *status.Status `protobuf:"bytes,2,opt,name=error,proto3,oneof"` } type BlockRequest_Success struct { // The response to be returned that will signify successful method call. Success *BlockResponse `protobuf:"bytes,3,opt,name=success,proto3,oneof"` } func (*BlockRequest_Error) isBlockRequest_Response() {} func (*BlockRequest_Success) isBlockRequest_Response() {} // The response for Block method. type BlockResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // This content can contain anything, the server will not depend on a value // here. Content string `protobuf:"bytes,1,opt,name=content,proto3" json:"content,omitempty"` } func (x *BlockResponse) Reset() { *x = BlockResponse{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *BlockResponse) String() string { return protoimpl.X.MessageStringOf(x) } func (*BlockResponse) ProtoMessage() {} func (x *BlockResponse) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[19] 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 BlockResponse.ProtoReflect.Descriptor instead. func (*BlockResponse) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_echo_proto_rawDescGZIP(), []int{19} } func (x *BlockResponse) GetContent() string { if x != nil { return x.Content } return "" } type EchoErrorDetailsResponse_SingleDetail struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Error *ErrorWithSingleDetail `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` } func (x *EchoErrorDetailsResponse_SingleDetail) Reset() { *x = EchoErrorDetailsResponse_SingleDetail{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EchoErrorDetailsResponse_SingleDetail) String() string { return protoimpl.X.MessageStringOf(x) } func (*EchoErrorDetailsResponse_SingleDetail) ProtoMessage() {} func (x *EchoErrorDetailsResponse_SingleDetail) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[20] 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 EchoErrorDetailsResponse_SingleDetail.ProtoReflect.Descriptor instead. func (*EchoErrorDetailsResponse_SingleDetail) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_echo_proto_rawDescGZIP(), []int{3, 0} } func (x *EchoErrorDetailsResponse_SingleDetail) GetError() *ErrorWithSingleDetail { if x != nil { return x.Error } return nil } type EchoErrorDetailsResponse_MultipleDetails struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Error *ErrorWithMultipleDetails `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` } func (x *EchoErrorDetailsResponse_MultipleDetails) Reset() { *x = EchoErrorDetailsResponse_MultipleDetails{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EchoErrorDetailsResponse_MultipleDetails) String() string { return protoimpl.X.MessageStringOf(x) } func (*EchoErrorDetailsResponse_MultipleDetails) ProtoMessage() {} func (x *EchoErrorDetailsResponse_MultipleDetails) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_echo_proto_msgTypes[21] 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 EchoErrorDetailsResponse_MultipleDetails.ProtoReflect.Descriptor instead. func (*EchoErrorDetailsResponse_MultipleDetails) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_echo_proto_rawDescGZIP(), []int{3, 1} } func (x *EchoErrorDetailsResponse_MultipleDetails) GetError() *ErrorWithMultipleDetails { if x != nil { return x.Error } return nil } var File_google_showcase_v1beta1_echo_proto protoreflect.FileDescriptor var file_google_showcase_v1beta1_echo_proto_rawDesc = []byte{ 0x0a, 0x22, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x17, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x18, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x23, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x6c, 0x6f, 0x6e, 0x67, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x2f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 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, 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, 0x17, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd2, 0x02, 0x0a, 0x0b, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x48, 0x00, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x3d, 0x0a, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x27, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xe2, 0x8c, 0xcf, 0xd7, 0x08, 0x02, 0x08, 0x01, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x37, 0x0a, 0x10, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xe2, 0x8c, 0xcf, 0xd7, 0x08, 0x02, 0x08, 0x01, 0x48, 0x01, 0x52, 0x0e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x22, 0xb0, 0x01, 0x0a, 0x0c, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x3d, 0x0a, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x22, 0x73, 0x0a, 0x17, 0x45, 0x63, 0x68, 0x6f, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x54, 0x65, 0x78, 0x74, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x54, 0x65, 0x78, 0x74, 0x22, 0x9f, 0x03, 0x0a, 0x18, 0x45, 0x63, 0x68, 0x6f, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x0d, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x0c, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x6c, 0x0a, 0x10, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x1a, 0x54, 0x0a, 0x0c, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x44, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x57, 0x69, 0x74, 0x68, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x1a, 0x5a, 0x0a, 0x0f, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x47, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x57, 0x69, 0x74, 0x68, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x47, 0x0a, 0x15, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x57, 0x69, 0x74, 0x68, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x2e, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x01, 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, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x4a, 0x0a, 0x18, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x57, 0x69, 0x74, 0x68, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x2e, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 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, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x21, 0x0a, 0x0b, 0x50, 0x6f, 0x65, 0x74, 0x72, 0x79, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x6f, 0x65, 0x6d, 0x22, 0x36, 0x0a, 0x1a, 0x46, 0x61, 0x69, 0x6c, 0x45, 0x63, 0x68, 0x6f, 0x57, 0x69, 0x74, 0x68, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x1d, 0x0a, 0x1b, 0x46, 0x61, 0x69, 0x6c, 0x45, 0x63, 0x68, 0x6f, 0x57, 0x69, 0x74, 0x68, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x98, 0x01, 0x0a, 0x0d, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x43, 0x0a, 0x10, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x77, 0x61, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 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, 0x0e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x57, 0x61, 0x69, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x6f, 0x0a, 0x12, 0x50, 0x61, 0x67, 0x65, 0x64, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x79, 0x0a, 0x18, 0x50, 0x61, 0x67, 0x65, 0x64, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6d, 0x61, 0x78, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x82, 0x01, 0x0a, 0x13, 0x50, 0x61, 0x67, 0x65, 0x64, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x2f, 0x0a, 0x17, 0x50, 0x61, 0x67, 0x65, 0x64, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x22, 0xac, 0x02, 0x0a, 0x1f, 0x50, 0x61, 0x67, 0x65, 0x64, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0c, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x62, 0x65, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x4a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x64, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x62, 0x65, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x62, 0x65, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x1a, 0x71, 0x0a, 0x11, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x62, 0x65, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x46, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x64, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xf7, 0x01, 0x0a, 0x0b, 0x57, 0x61, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 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, 0x48, 0x00, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x2d, 0x0a, 0x03, 0x74, 0x74, 0x6c, 0x18, 0x04, 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, 0x48, 0x00, 0x52, 0x03, 0x74, 0x74, 0x6c, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x48, 0x01, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x41, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x57, 0x61, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x01, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x42, 0x05, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x0a, 0x0c, 0x57, 0x61, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x45, 0x0a, 0x0c, 0x57, 0x61, 0x69, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x35, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 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, 0x07, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x22, 0xcc, 0x01, 0x0a, 0x0c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 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, 0x0d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x48, 0x00, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x42, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x29, 0x0a, 0x0d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2a, 0x44, 0x0a, 0x08, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x4e, 0x45, 0x43, 0x45, 0x53, 0x53, 0x41, 0x52, 0x59, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x45, 0x43, 0x45, 0x53, 0x53, 0x41, 0x52, 0x59, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x52, 0x47, 0x45, 0x4e, 0x54, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x52, 0x49, 0x54, 0x49, 0x43, 0x41, 0x4c, 0x10, 0x03, 0x32, 0xdf, 0x0e, 0x0a, 0x04, 0x45, 0x63, 0x68, 0x6f, 0x12, 0x94, 0x03, 0x0a, 0x04, 0x45, 0x63, 0x68, 0x6f, 0x12, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xbe, 0x02, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x3a, 0x01, 0x2a, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x3a, 0x65, 0x63, 0x68, 0x6f, 0x8a, 0xd3, 0xe4, 0x93, 0x02, 0x9a, 0x02, 0x12, 0x08, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x19, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x0f, 0x7b, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x64, 0x3d, 0x2a, 0x2a, 0x7d, 0x12, 0x2b, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x21, 0x7b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x7a, 0x6f, 0x6e, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x2a, 0x2a, 0x7d, 0x12, 0x22, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x18, 0x7b, 0x73, 0x75, 0x70, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x2a, 0x2a, 0x12, 0x30, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x26, 0x7b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x2a, 0x2a, 0x7d, 0x12, 0x31, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x27, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x3d, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x2a, 0x2a, 0x12, 0x18, 0x0a, 0x0c, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x08, 0x7b, 0x62, 0x61, 0x7a, 0x3d, 0x2a, 0x2a, 0x7d, 0x12, 0x23, 0x0a, 0x0c, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x13, 0x7b, 0x71, 0x75, 0x78, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x2a, 0x2a, 0x12, 0x9f, 0x01, 0x0a, 0x10, 0x45, 0x63, 0x68, 0x6f, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x30, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x01, 0x2a, 0x22, 0x1b, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x3a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2d, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0xaa, 0x01, 0x0a, 0x13, 0x46, 0x61, 0x69, 0x6c, 0x45, 0x63, 0x68, 0x6f, 0x57, 0x69, 0x74, 0x68, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x33, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x45, 0x63, 0x68, 0x6f, 0x57, 0x69, 0x74, 0x68, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x45, 0x63, 0x68, 0x6f, 0x57, 0x69, 0x74, 0x68, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x3a, 0x01, 0x2a, 0x22, 0x1d, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x3a, 0x66, 0x61, 0x69, 0x6c, 0x57, 0x69, 0x74, 0x68, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x8a, 0x01, 0x0a, 0x06, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x12, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2f, 0xda, 0x41, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x3a, 0x01, 0x2a, 0x22, 0x14, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x3a, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x30, 0x01, 0x12, 0x7a, 0x0a, 0x07, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x12, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x3a, 0x01, 0x2a, 0x22, 0x15, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x3a, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x28, 0x01, 0x12, 0x57, 0x0a, 0x04, 0x43, 0x68, 0x61, 0x74, 0x12, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0x8e, 0x01, 0x0a, 0x0b, 0x50, 0x61, 0x67, 0x65, 0x64, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x12, 0x2b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x64, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x64, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x3a, 0x01, 0x2a, 0x22, 0x19, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x3a, 0x70, 0x61, 0x67, 0x65, 0x64, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x12, 0xa0, 0x01, 0x0a, 0x11, 0x50, 0x61, 0x67, 0x65, 0x64, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x12, 0x31, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x64, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x64, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x3a, 0x01, 0x2a, 0x22, 0x1f, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x3a, 0x70, 0x61, 0x67, 0x65, 0x64, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x12, 0xb2, 0x01, 0x0a, 0x17, 0x50, 0x61, 0x67, 0x65, 0x64, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x12, 0x2b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x64, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x64, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a, 0x3a, 0x01, 0x2a, 0x22, 0x25, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x3a, 0x70, 0x61, 0x67, 0x65, 0x64, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x12, 0x89, 0x01, 0x0a, 0x04, 0x57, 0x61, 0x69, 0x74, 0x12, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x57, 0x61, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x6c, 0x6f, 0x6e, 0x67, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3c, 0xca, 0x41, 0x1c, 0x0a, 0x0c, 0x57, 0x61, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0c, 0x57, 0x61, 0x69, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x3a, 0x01, 0x2a, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x3a, 0x77, 0x61, 0x69, 0x74, 0x12, 0x76, 0x0a, 0x05, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x3a, 0x01, 0x2a, 0x22, 0x13, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x3a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x1a, 0x22, 0xca, 0x41, 0x0e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x3a, 0x37, 0x34, 0x36, 0x39, 0x8a, 0xd4, 0xdb, 0xd2, 0x0f, 0x0b, 0x76, 0x31, 0x5f, 0x32, 0x30, 0x32, 0x34, 0x30, 0x34, 0x30, 0x38, 0x42, 0x71, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x50, 0x01, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x67, 0x61, 0x70, 0x69, 0x63, 0x2d, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x65, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xea, 0x02, 0x19, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x3a, 0x3a, 0x53, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_google_showcase_v1beta1_echo_proto_rawDescOnce sync.Once file_google_showcase_v1beta1_echo_proto_rawDescData = file_google_showcase_v1beta1_echo_proto_rawDesc ) func file_google_showcase_v1beta1_echo_proto_rawDescGZIP() []byte { file_google_showcase_v1beta1_echo_proto_rawDescOnce.Do(func() { file_google_showcase_v1beta1_echo_proto_rawDescData = protoimpl.X.CompressGZIP(file_google_showcase_v1beta1_echo_proto_rawDescData) }) return file_google_showcase_v1beta1_echo_proto_rawDescData } var file_google_showcase_v1beta1_echo_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_google_showcase_v1beta1_echo_proto_msgTypes = make([]protoimpl.MessageInfo, 23) var file_google_showcase_v1beta1_echo_proto_goTypes = []interface{}{ (Severity)(0), // 0: google.showcase.v1beta1.Severity (*EchoRequest)(nil), // 1: google.showcase.v1beta1.EchoRequest (*EchoResponse)(nil), // 2: google.showcase.v1beta1.EchoResponse (*EchoErrorDetailsRequest)(nil), // 3: google.showcase.v1beta1.EchoErrorDetailsRequest (*EchoErrorDetailsResponse)(nil), // 4: google.showcase.v1beta1.EchoErrorDetailsResponse (*ErrorWithSingleDetail)(nil), // 5: google.showcase.v1beta1.ErrorWithSingleDetail (*ErrorWithMultipleDetails)(nil), // 6: google.showcase.v1beta1.ErrorWithMultipleDetails (*PoetryError)(nil), // 7: google.showcase.v1beta1.PoetryError (*FailEchoWithDetailsRequest)(nil), // 8: google.showcase.v1beta1.FailEchoWithDetailsRequest (*FailEchoWithDetailsResponse)(nil), // 9: google.showcase.v1beta1.FailEchoWithDetailsResponse (*ExpandRequest)(nil), // 10: google.showcase.v1beta1.ExpandRequest (*PagedExpandRequest)(nil), // 11: google.showcase.v1beta1.PagedExpandRequest (*PagedExpandLegacyRequest)(nil), // 12: google.showcase.v1beta1.PagedExpandLegacyRequest (*PagedExpandResponse)(nil), // 13: google.showcase.v1beta1.PagedExpandResponse (*PagedExpandResponseList)(nil), // 14: google.showcase.v1beta1.PagedExpandResponseList (*PagedExpandLegacyMappedResponse)(nil), // 15: google.showcase.v1beta1.PagedExpandLegacyMappedResponse (*WaitRequest)(nil), // 16: google.showcase.v1beta1.WaitRequest (*WaitResponse)(nil), // 17: google.showcase.v1beta1.WaitResponse (*WaitMetadata)(nil), // 18: google.showcase.v1beta1.WaitMetadata (*BlockRequest)(nil), // 19: google.showcase.v1beta1.BlockRequest (*BlockResponse)(nil), // 20: google.showcase.v1beta1.BlockResponse (*EchoErrorDetailsResponse_SingleDetail)(nil), // 21: google.showcase.v1beta1.EchoErrorDetailsResponse.SingleDetail (*EchoErrorDetailsResponse_MultipleDetails)(nil), // 22: google.showcase.v1beta1.EchoErrorDetailsResponse.MultipleDetails nil, // 23: google.showcase.v1beta1.PagedExpandLegacyMappedResponse.AlphabetizedEntry (*status.Status)(nil), // 24: google.rpc.Status (*anypb.Any)(nil), // 25: google.protobuf.Any (*durationpb.Duration)(nil), // 26: google.protobuf.Duration (*timestamppb.Timestamp)(nil), // 27: google.protobuf.Timestamp (*longrunningpb.Operation)(nil), // 28: google.longrunning.Operation } var file_google_showcase_v1beta1_echo_proto_depIdxs = []int32{ 24, // 0: google.showcase.v1beta1.EchoRequest.error:type_name -> google.rpc.Status 0, // 1: google.showcase.v1beta1.EchoRequest.severity:type_name -> google.showcase.v1beta1.Severity 0, // 2: google.showcase.v1beta1.EchoResponse.severity:type_name -> google.showcase.v1beta1.Severity 21, // 3: google.showcase.v1beta1.EchoErrorDetailsResponse.single_detail:type_name -> google.showcase.v1beta1.EchoErrorDetailsResponse.SingleDetail 22, // 4: google.showcase.v1beta1.EchoErrorDetailsResponse.multiple_details:type_name -> google.showcase.v1beta1.EchoErrorDetailsResponse.MultipleDetails 25, // 5: google.showcase.v1beta1.ErrorWithSingleDetail.details:type_name -> google.protobuf.Any 25, // 6: google.showcase.v1beta1.ErrorWithMultipleDetails.details:type_name -> google.protobuf.Any 24, // 7: google.showcase.v1beta1.ExpandRequest.error:type_name -> google.rpc.Status 26, // 8: google.showcase.v1beta1.ExpandRequest.stream_wait_time:type_name -> google.protobuf.Duration 2, // 9: google.showcase.v1beta1.PagedExpandResponse.responses:type_name -> google.showcase.v1beta1.EchoResponse 23, // 10: google.showcase.v1beta1.PagedExpandLegacyMappedResponse.alphabetized:type_name -> google.showcase.v1beta1.PagedExpandLegacyMappedResponse.AlphabetizedEntry 27, // 11: google.showcase.v1beta1.WaitRequest.end_time:type_name -> google.protobuf.Timestamp 26, // 12: google.showcase.v1beta1.WaitRequest.ttl:type_name -> google.protobuf.Duration 24, // 13: google.showcase.v1beta1.WaitRequest.error:type_name -> google.rpc.Status 17, // 14: google.showcase.v1beta1.WaitRequest.success:type_name -> google.showcase.v1beta1.WaitResponse 27, // 15: google.showcase.v1beta1.WaitMetadata.end_time:type_name -> google.protobuf.Timestamp 26, // 16: google.showcase.v1beta1.BlockRequest.response_delay:type_name -> google.protobuf.Duration 24, // 17: google.showcase.v1beta1.BlockRequest.error:type_name -> google.rpc.Status 20, // 18: google.showcase.v1beta1.BlockRequest.success:type_name -> google.showcase.v1beta1.BlockResponse 5, // 19: google.showcase.v1beta1.EchoErrorDetailsResponse.SingleDetail.error:type_name -> google.showcase.v1beta1.ErrorWithSingleDetail 6, // 20: google.showcase.v1beta1.EchoErrorDetailsResponse.MultipleDetails.error:type_name -> google.showcase.v1beta1.ErrorWithMultipleDetails 14, // 21: google.showcase.v1beta1.PagedExpandLegacyMappedResponse.AlphabetizedEntry.value:type_name -> google.showcase.v1beta1.PagedExpandResponseList 1, // 22: google.showcase.v1beta1.Echo.Echo:input_type -> google.showcase.v1beta1.EchoRequest 3, // 23: google.showcase.v1beta1.Echo.EchoErrorDetails:input_type -> google.showcase.v1beta1.EchoErrorDetailsRequest 8, // 24: google.showcase.v1beta1.Echo.FailEchoWithDetails:input_type -> google.showcase.v1beta1.FailEchoWithDetailsRequest 10, // 25: google.showcase.v1beta1.Echo.Expand:input_type -> google.showcase.v1beta1.ExpandRequest 1, // 26: google.showcase.v1beta1.Echo.Collect:input_type -> google.showcase.v1beta1.EchoRequest 1, // 27: google.showcase.v1beta1.Echo.Chat:input_type -> google.showcase.v1beta1.EchoRequest 11, // 28: google.showcase.v1beta1.Echo.PagedExpand:input_type -> google.showcase.v1beta1.PagedExpandRequest 12, // 29: google.showcase.v1beta1.Echo.PagedExpandLegacy:input_type -> google.showcase.v1beta1.PagedExpandLegacyRequest 11, // 30: google.showcase.v1beta1.Echo.PagedExpandLegacyMapped:input_type -> google.showcase.v1beta1.PagedExpandRequest 16, // 31: google.showcase.v1beta1.Echo.Wait:input_type -> google.showcase.v1beta1.WaitRequest 19, // 32: google.showcase.v1beta1.Echo.Block:input_type -> google.showcase.v1beta1.BlockRequest 2, // 33: google.showcase.v1beta1.Echo.Echo:output_type -> google.showcase.v1beta1.EchoResponse 4, // 34: google.showcase.v1beta1.Echo.EchoErrorDetails:output_type -> google.showcase.v1beta1.EchoErrorDetailsResponse 9, // 35: google.showcase.v1beta1.Echo.FailEchoWithDetails:output_type -> google.showcase.v1beta1.FailEchoWithDetailsResponse 2, // 36: google.showcase.v1beta1.Echo.Expand:output_type -> google.showcase.v1beta1.EchoResponse 2, // 37: google.showcase.v1beta1.Echo.Collect:output_type -> google.showcase.v1beta1.EchoResponse 2, // 38: google.showcase.v1beta1.Echo.Chat:output_type -> google.showcase.v1beta1.EchoResponse 13, // 39: google.showcase.v1beta1.Echo.PagedExpand:output_type -> google.showcase.v1beta1.PagedExpandResponse 13, // 40: google.showcase.v1beta1.Echo.PagedExpandLegacy:output_type -> google.showcase.v1beta1.PagedExpandResponse 15, // 41: google.showcase.v1beta1.Echo.PagedExpandLegacyMapped:output_type -> google.showcase.v1beta1.PagedExpandLegacyMappedResponse 28, // 42: google.showcase.v1beta1.Echo.Wait:output_type -> google.longrunning.Operation 20, // 43: google.showcase.v1beta1.Echo.Block:output_type -> google.showcase.v1beta1.BlockResponse 33, // [33:44] is the sub-list for method output_type 22, // [22:33] is the sub-list for method input_type 22, // [22:22] is the sub-list for extension type_name 22, // [22:22] is the sub-list for extension extendee 0, // [0:22] is the sub-list for field type_name } func init() { file_google_showcase_v1beta1_echo_proto_init() } func file_google_showcase_v1beta1_echo_proto_init() { if File_google_showcase_v1beta1_echo_proto != nil { return } if !protoimpl.UnsafeEnabled { file_google_showcase_v1beta1_echo_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EchoRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_echo_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EchoResponse); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_echo_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EchoErrorDetailsRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_echo_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EchoErrorDetailsResponse); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_echo_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ErrorWithSingleDetail); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_echo_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ErrorWithMultipleDetails); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_echo_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PoetryError); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_echo_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FailEchoWithDetailsRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_echo_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FailEchoWithDetailsResponse); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_echo_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ExpandRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_echo_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PagedExpandRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_echo_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PagedExpandLegacyRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_echo_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PagedExpandResponse); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_echo_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PagedExpandResponseList); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_echo_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PagedExpandLegacyMappedResponse); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_echo_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*WaitRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_echo_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*WaitResponse); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_echo_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*WaitMetadata); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_echo_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BlockRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_echo_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BlockResponse); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_echo_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EchoErrorDetailsResponse_SingleDetail); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_echo_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EchoErrorDetailsResponse_MultipleDetails); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } file_google_showcase_v1beta1_echo_proto_msgTypes[0].OneofWrappers = []interface{}{ (*EchoRequest_Content)(nil), (*EchoRequest_Error)(nil), } file_google_showcase_v1beta1_echo_proto_msgTypes[15].OneofWrappers = []interface{}{ (*WaitRequest_EndTime)(nil), (*WaitRequest_Ttl)(nil), (*WaitRequest_Error)(nil), (*WaitRequest_Success)(nil), } file_google_showcase_v1beta1_echo_proto_msgTypes[18].OneofWrappers = []interface{}{ (*BlockRequest_Error)(nil), (*BlockRequest_Success)(nil), } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_google_showcase_v1beta1_echo_proto_rawDesc, NumEnums: 1, NumMessages: 23, NumExtensions: 0, NumServices: 1, }, GoTypes: file_google_showcase_v1beta1_echo_proto_goTypes, DependencyIndexes: file_google_showcase_v1beta1_echo_proto_depIdxs, EnumInfos: file_google_showcase_v1beta1_echo_proto_enumTypes, MessageInfos: file_google_showcase_v1beta1_echo_proto_msgTypes, }.Build() File_google_showcase_v1beta1_echo_proto = out.File file_google_showcase_v1beta1_echo_proto_rawDesc = nil file_google_showcase_v1beta1_echo_proto_goTypes = nil file_google_showcase_v1beta1_echo_proto_depIdxs = nil } // Reference imports to suppress errors if they are not otherwise used. var _ context.Context var _ grpc.ClientConnInterface // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. const _ = grpc.SupportPackageIsVersion6 // EchoClient is the client API for Echo service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type EchoClient interface { // This method simply echoes the request. This method showcases unary RPCs. Echo(ctx context.Context, in *EchoRequest, opts ...grpc.CallOption) (*EchoResponse, error) // This method returns error details in a repeated "google.protobuf.Any" // field. This method showcases handling errors thus encoded, particularly // over REST transport. Note that GAPICs only allow the type // "google.protobuf.Any" for field paths ending in "error.details", and, at // run-time, the actual types for these fields must be one of the types in // google/rpc/error_details.proto. EchoErrorDetails(ctx context.Context, in *EchoErrorDetailsRequest, opts ...grpc.CallOption) (*EchoErrorDetailsResponse, error) // This method always fails with a gRPC "Aborted" error status that contains // multiple error details. These include one instance of each of the standard // ones in error_details.proto // (https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto) // plus a custom, Showcase-defined PoetryError. The intent of this RPC is to // verify that GAPICs can process these various error details and surface them // to the user in an idiomatic form. FailEchoWithDetails(ctx context.Context, in *FailEchoWithDetailsRequest, opts ...grpc.CallOption) (*FailEchoWithDetailsResponse, error) // This method splits the given content into words and will pass each word back // through the stream. This method showcases server-side streaming RPCs. Expand(ctx context.Context, in *ExpandRequest, opts ...grpc.CallOption) (Echo_ExpandClient, error) // This method will collect the words given to it. When the stream is closed // by the client, this method will return the a concatenation of the strings // passed to it. This method showcases client-side streaming RPCs. Collect(ctx context.Context, opts ...grpc.CallOption) (Echo_CollectClient, error) // This method, upon receiving a request on the stream, will pass the same // content back on the stream. This method showcases bidirectional // streaming RPCs. Chat(ctx context.Context, opts ...grpc.CallOption) (Echo_ChatClient, error) // This is similar to the Expand method but instead of returning a stream of // expanded words, this method returns a paged list of expanded words. PagedExpand(ctx context.Context, in *PagedExpandRequest, opts ...grpc.CallOption) (*PagedExpandResponse, error) // This is similar to the PagedExpand except that it uses // max_results instead of page_size, as some legacy APIs still // do. New APIs should NOT use this pattern. PagedExpandLegacy(ctx context.Context, in *PagedExpandLegacyRequest, opts ...grpc.CallOption) (*PagedExpandResponse, error) // This method returns a map containing lists of words that appear in the input, keyed by their // initial character. The only words returned are the ones included in the current page, // as determined by page_token and page_size, which both refer to the word indices in the // input. This paging result consisting of a map of lists is a pattern used by some legacy // APIs. New APIs should NOT use this pattern. PagedExpandLegacyMapped(ctx context.Context, in *PagedExpandRequest, opts ...grpc.CallOption) (*PagedExpandLegacyMappedResponse, error) // This method will wait for the requested amount of time and then return. // This method showcases how a client handles a request timeout. Wait(ctx context.Context, in *WaitRequest, opts ...grpc.CallOption) (*longrunningpb.Operation, error) // This method will block (wait) for the requested amount of time // and then return the response or error. // This method showcases how a client handles delays or retries. Block(ctx context.Context, in *BlockRequest, opts ...grpc.CallOption) (*BlockResponse, error) } type echoClient struct { cc grpc.ClientConnInterface } func NewEchoClient(cc grpc.ClientConnInterface) EchoClient { return &echoClient{cc} } func (c *echoClient) Echo(ctx context.Context, in *EchoRequest, opts ...grpc.CallOption) (*EchoResponse, error) { out := new(EchoResponse) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Echo/Echo", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *echoClient) EchoErrorDetails(ctx context.Context, in *EchoErrorDetailsRequest, opts ...grpc.CallOption) (*EchoErrorDetailsResponse, error) { out := new(EchoErrorDetailsResponse) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Echo/EchoErrorDetails", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *echoClient) FailEchoWithDetails(ctx context.Context, in *FailEchoWithDetailsRequest, opts ...grpc.CallOption) (*FailEchoWithDetailsResponse, error) { out := new(FailEchoWithDetailsResponse) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Echo/FailEchoWithDetails", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *echoClient) Expand(ctx context.Context, in *ExpandRequest, opts ...grpc.CallOption) (Echo_ExpandClient, error) { stream, err := c.cc.NewStream(ctx, &_Echo_serviceDesc.Streams[0], "/google.showcase.v1beta1.Echo/Expand", opts...) if err != nil { return nil, err } x := &echoExpandClient{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 Echo_ExpandClient interface { Recv() (*EchoResponse, error) grpc.ClientStream } type echoExpandClient struct { grpc.ClientStream } func (x *echoExpandClient) Recv() (*EchoResponse, error) { m := new(EchoResponse) if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err } return m, nil } func (c *echoClient) Collect(ctx context.Context, opts ...grpc.CallOption) (Echo_CollectClient, error) { stream, err := c.cc.NewStream(ctx, &_Echo_serviceDesc.Streams[1], "/google.showcase.v1beta1.Echo/Collect", opts...) if err != nil { return nil, err } x := &echoCollectClient{stream} return x, nil } type Echo_CollectClient interface { Send(*EchoRequest) error CloseAndRecv() (*EchoResponse, error) grpc.ClientStream } type echoCollectClient struct { grpc.ClientStream } func (x *echoCollectClient) Send(m *EchoRequest) error { return x.ClientStream.SendMsg(m) } func (x *echoCollectClient) CloseAndRecv() (*EchoResponse, error) { if err := x.ClientStream.CloseSend(); err != nil { return nil, err } m := new(EchoResponse) if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err } return m, nil } func (c *echoClient) Chat(ctx context.Context, opts ...grpc.CallOption) (Echo_ChatClient, error) { stream, err := c.cc.NewStream(ctx, &_Echo_serviceDesc.Streams[2], "/google.showcase.v1beta1.Echo/Chat", opts...) if err != nil { return nil, err } x := &echoChatClient{stream} return x, nil } type Echo_ChatClient interface { Send(*EchoRequest) error Recv() (*EchoResponse, error) grpc.ClientStream } type echoChatClient struct { grpc.ClientStream } func (x *echoChatClient) Send(m *EchoRequest) error { return x.ClientStream.SendMsg(m) } func (x *echoChatClient) Recv() (*EchoResponse, error) { m := new(EchoResponse) if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err } return m, nil } func (c *echoClient) PagedExpand(ctx context.Context, in *PagedExpandRequest, opts ...grpc.CallOption) (*PagedExpandResponse, error) { out := new(PagedExpandResponse) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Echo/PagedExpand", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *echoClient) PagedExpandLegacy(ctx context.Context, in *PagedExpandLegacyRequest, opts ...grpc.CallOption) (*PagedExpandResponse, error) { out := new(PagedExpandResponse) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Echo/PagedExpandLegacy", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *echoClient) PagedExpandLegacyMapped(ctx context.Context, in *PagedExpandRequest, opts ...grpc.CallOption) (*PagedExpandLegacyMappedResponse, error) { out := new(PagedExpandLegacyMappedResponse) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Echo/PagedExpandLegacyMapped", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *echoClient) Wait(ctx context.Context, in *WaitRequest, opts ...grpc.CallOption) (*longrunningpb.Operation, error) { out := new(longrunningpb.Operation) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Echo/Wait", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *echoClient) Block(ctx context.Context, in *BlockRequest, opts ...grpc.CallOption) (*BlockResponse, error) { out := new(BlockResponse) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Echo/Block", in, out, opts...) if err != nil { return nil, err } return out, nil } // EchoServer is the server API for Echo service. type EchoServer interface { // This method simply echoes the request. This method showcases unary RPCs. Echo(context.Context, *EchoRequest) (*EchoResponse, error) // This method returns error details in a repeated "google.protobuf.Any" // field. This method showcases handling errors thus encoded, particularly // over REST transport. Note that GAPICs only allow the type // "google.protobuf.Any" for field paths ending in "error.details", and, at // run-time, the actual types for these fields must be one of the types in // google/rpc/error_details.proto. EchoErrorDetails(context.Context, *EchoErrorDetailsRequest) (*EchoErrorDetailsResponse, error) // This method always fails with a gRPC "Aborted" error status that contains // multiple error details. These include one instance of each of the standard // ones in error_details.proto // (https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto) // plus a custom, Showcase-defined PoetryError. The intent of this RPC is to // verify that GAPICs can process these various error details and surface them // to the user in an idiomatic form. FailEchoWithDetails(context.Context, *FailEchoWithDetailsRequest) (*FailEchoWithDetailsResponse, error) // This method splits the given content into words and will pass each word back // through the stream. This method showcases server-side streaming RPCs. Expand(*ExpandRequest, Echo_ExpandServer) error // This method will collect the words given to it. When the stream is closed // by the client, this method will return the a concatenation of the strings // passed to it. This method showcases client-side streaming RPCs. Collect(Echo_CollectServer) error // This method, upon receiving a request on the stream, will pass the same // content back on the stream. This method showcases bidirectional // streaming RPCs. Chat(Echo_ChatServer) error // This is similar to the Expand method but instead of returning a stream of // expanded words, this method returns a paged list of expanded words. PagedExpand(context.Context, *PagedExpandRequest) (*PagedExpandResponse, error) // This is similar to the PagedExpand except that it uses // max_results instead of page_size, as some legacy APIs still // do. New APIs should NOT use this pattern. PagedExpandLegacy(context.Context, *PagedExpandLegacyRequest) (*PagedExpandResponse, error) // This method returns a map containing lists of words that appear in the input, keyed by their // initial character. The only words returned are the ones included in the current page, // as determined by page_token and page_size, which both refer to the word indices in the // input. This paging result consisting of a map of lists is a pattern used by some legacy // APIs. New APIs should NOT use this pattern. PagedExpandLegacyMapped(context.Context, *PagedExpandRequest) (*PagedExpandLegacyMappedResponse, error) // This method will wait for the requested amount of time and then return. // This method showcases how a client handles a request timeout. Wait(context.Context, *WaitRequest) (*longrunningpb.Operation, error) // This method will block (wait) for the requested amount of time // and then return the response or error. // This method showcases how a client handles delays or retries. Block(context.Context, *BlockRequest) (*BlockResponse, error) } // UnimplementedEchoServer can be embedded to have forward compatible implementations. type UnimplementedEchoServer struct { } func (*UnimplementedEchoServer) Echo(context.Context, *EchoRequest) (*EchoResponse, error) { return nil, status1.Errorf(codes.Unimplemented, "method Echo not implemented") } func (*UnimplementedEchoServer) EchoErrorDetails(context.Context, *EchoErrorDetailsRequest) (*EchoErrorDetailsResponse, error) { return nil, status1.Errorf(codes.Unimplemented, "method EchoErrorDetails not implemented") } func (*UnimplementedEchoServer) FailEchoWithDetails(context.Context, *FailEchoWithDetailsRequest) (*FailEchoWithDetailsResponse, error) { return nil, status1.Errorf(codes.Unimplemented, "method FailEchoWithDetails not implemented") } func (*UnimplementedEchoServer) Expand(*ExpandRequest, Echo_ExpandServer) error { return status1.Errorf(codes.Unimplemented, "method Expand not implemented") } func (*UnimplementedEchoServer) Collect(Echo_CollectServer) error { return status1.Errorf(codes.Unimplemented, "method Collect not implemented") } func (*UnimplementedEchoServer) Chat(Echo_ChatServer) error { return status1.Errorf(codes.Unimplemented, "method Chat not implemented") } func (*UnimplementedEchoServer) PagedExpand(context.Context, *PagedExpandRequest) (*PagedExpandResponse, error) { return nil, status1.Errorf(codes.Unimplemented, "method PagedExpand not implemented") } func (*UnimplementedEchoServer) PagedExpandLegacy(context.Context, *PagedExpandLegacyRequest) (*PagedExpandResponse, error) { return nil, status1.Errorf(codes.Unimplemented, "method PagedExpandLegacy not implemented") } func (*UnimplementedEchoServer) PagedExpandLegacyMapped(context.Context, *PagedExpandRequest) (*PagedExpandLegacyMappedResponse, error) { return nil, status1.Errorf(codes.Unimplemented, "method PagedExpandLegacyMapped not implemented") } func (*UnimplementedEchoServer) Wait(context.Context, *WaitRequest) (*longrunningpb.Operation, error) { return nil, status1.Errorf(codes.Unimplemented, "method Wait not implemented") } func (*UnimplementedEchoServer) Block(context.Context, *BlockRequest) (*BlockResponse, error) { return nil, status1.Errorf(codes.Unimplemented, "method Block not implemented") } func RegisterEchoServer(s *grpc.Server, srv EchoServer) { s.RegisterService(&_Echo_serviceDesc, srv) } func _Echo_Echo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(EchoRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(EchoServer).Echo(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Echo/Echo", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(EchoServer).Echo(ctx, req.(*EchoRequest)) } return interceptor(ctx, in, info, handler) } func _Echo_EchoErrorDetails_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(EchoErrorDetailsRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(EchoServer).EchoErrorDetails(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Echo/EchoErrorDetails", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(EchoServer).EchoErrorDetails(ctx, req.(*EchoErrorDetailsRequest)) } return interceptor(ctx, in, info, handler) } func _Echo_FailEchoWithDetails_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(FailEchoWithDetailsRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(EchoServer).FailEchoWithDetails(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Echo/FailEchoWithDetails", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(EchoServer).FailEchoWithDetails(ctx, req.(*FailEchoWithDetailsRequest)) } return interceptor(ctx, in, info, handler) } func _Echo_Expand_Handler(srv interface{}, stream grpc.ServerStream) error { m := new(ExpandRequest) if err := stream.RecvMsg(m); err != nil { return err } return srv.(EchoServer).Expand(m, &echoExpandServer{stream}) } type Echo_ExpandServer interface { Send(*EchoResponse) error grpc.ServerStream } type echoExpandServer struct { grpc.ServerStream } func (x *echoExpandServer) Send(m *EchoResponse) error { return x.ServerStream.SendMsg(m) } func _Echo_Collect_Handler(srv interface{}, stream grpc.ServerStream) error { return srv.(EchoServer).Collect(&echoCollectServer{stream}) } type Echo_CollectServer interface { SendAndClose(*EchoResponse) error Recv() (*EchoRequest, error) grpc.ServerStream } type echoCollectServer struct { grpc.ServerStream } func (x *echoCollectServer) SendAndClose(m *EchoResponse) error { return x.ServerStream.SendMsg(m) } func (x *echoCollectServer) Recv() (*EchoRequest, error) { m := new(EchoRequest) if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err } return m, nil } func _Echo_Chat_Handler(srv interface{}, stream grpc.ServerStream) error { return srv.(EchoServer).Chat(&echoChatServer{stream}) } type Echo_ChatServer interface { Send(*EchoResponse) error Recv() (*EchoRequest, error) grpc.ServerStream } type echoChatServer struct { grpc.ServerStream } func (x *echoChatServer) Send(m *EchoResponse) error { return x.ServerStream.SendMsg(m) } func (x *echoChatServer) Recv() (*EchoRequest, error) { m := new(EchoRequest) if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err } return m, nil } func _Echo_PagedExpand_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(PagedExpandRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(EchoServer).PagedExpand(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Echo/PagedExpand", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(EchoServer).PagedExpand(ctx, req.(*PagedExpandRequest)) } return interceptor(ctx, in, info, handler) } func _Echo_PagedExpandLegacy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(PagedExpandLegacyRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(EchoServer).PagedExpandLegacy(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Echo/PagedExpandLegacy", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(EchoServer).PagedExpandLegacy(ctx, req.(*PagedExpandLegacyRequest)) } return interceptor(ctx, in, info, handler) } func _Echo_PagedExpandLegacyMapped_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(PagedExpandRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(EchoServer).PagedExpandLegacyMapped(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Echo/PagedExpandLegacyMapped", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(EchoServer).PagedExpandLegacyMapped(ctx, req.(*PagedExpandRequest)) } return interceptor(ctx, in, info, handler) } func _Echo_Wait_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(WaitRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(EchoServer).Wait(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Echo/Wait", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(EchoServer).Wait(ctx, req.(*WaitRequest)) } return interceptor(ctx, in, info, handler) } func _Echo_Block_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(BlockRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(EchoServer).Block(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Echo/Block", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(EchoServer).Block(ctx, req.(*BlockRequest)) } return interceptor(ctx, in, info, handler) } var _Echo_serviceDesc = grpc.ServiceDesc{ ServiceName: "google.showcase.v1beta1.Echo", HandlerType: (*EchoServer)(nil), Methods: []grpc.MethodDesc{ { MethodName: "Echo", Handler: _Echo_Echo_Handler, }, { MethodName: "EchoErrorDetails", Handler: _Echo_EchoErrorDetails_Handler, }, { MethodName: "FailEchoWithDetails", Handler: _Echo_FailEchoWithDetails_Handler, }, { MethodName: "PagedExpand", Handler: _Echo_PagedExpand_Handler, }, { MethodName: "PagedExpandLegacy", Handler: _Echo_PagedExpandLegacy_Handler, }, { MethodName: "PagedExpandLegacyMapped", Handler: _Echo_PagedExpandLegacyMapped_Handler, }, { MethodName: "Wait", Handler: _Echo_Wait_Handler, }, { MethodName: "Block", Handler: _Echo_Block_Handler, }, }, Streams: []grpc.StreamDesc{ { StreamName: "Expand", Handler: _Echo_Expand_Handler, ServerStreams: true, }, { StreamName: "Collect", Handler: _Echo_Collect_Handler, ClientStreams: true, }, { StreamName: "Chat", Handler: _Echo_Chat_Handler, ServerStreams: true, ClientStreams: true, }, }, Metadata: "google/showcase/v1beta1/echo.proto", } ================================================ FILE: server/genproto/identity.pb.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.33.0 // protoc v3.20.3 // source: google/showcase/v1beta1/identity.proto package genproto import ( context "context" _ "google.golang.org/genproto/googleapis/api/annotations" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" emptypb "google.golang.org/protobuf/types/known/emptypb" fieldmaskpb "google.golang.org/protobuf/types/known/fieldmaskpb" timestamppb "google.golang.org/protobuf/types/known/timestamppb" 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) ) // A user. type User struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The resource name of the user. Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // The display_name of the user. DisplayName string `protobuf:"bytes,2,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` // The email address of the user. Email string `protobuf:"bytes,3,opt,name=email,proto3" json:"email,omitempty"` // The timestamp at which the user was created. CreateTime *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=create_time,json=createTime,proto3" json:"create_time,omitempty"` // The latest timestamp at which the user was updated. UpdateTime *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=update_time,json=updateTime,proto3" json:"update_time,omitempty"` // The age of the user in years. Age *int32 `protobuf:"varint,6,opt,name=age,proto3,oneof" json:"age,omitempty"` // The height of the user in feet. HeightFeet *float64 `protobuf:"fixed64,7,opt,name=height_feet,json=heightFeet,proto3,oneof" json:"height_feet,omitempty"` // The nickname of the user. // // (-- aip.dev/not-precedent: An empty string is a valid nickname. // // Ordinarily, proto3_optional should not be used on a `string` field. --) Nickname *string `protobuf:"bytes,8,opt,name=nickname,proto3,oneof" json:"nickname,omitempty"` // Enables the receiving of notifications. The default is true if unset. // // (-- aip.dev/not-precedent: The default for the feature is true. // // Ordinarily, the default for a `bool` field should be false. --) EnableNotifications *bool `protobuf:"varint,9,opt,name=enable_notifications,json=enableNotifications,proto3,oneof" json:"enable_notifications,omitempty"` } func (x *User) Reset() { *x = User{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_identity_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *User) String() string { return protoimpl.X.MessageStringOf(x) } func (*User) ProtoMessage() {} func (x *User) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_identity_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 User.ProtoReflect.Descriptor instead. func (*User) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_identity_proto_rawDescGZIP(), []int{0} } func (x *User) GetName() string { if x != nil { return x.Name } return "" } func (x *User) GetDisplayName() string { if x != nil { return x.DisplayName } return "" } func (x *User) GetEmail() string { if x != nil { return x.Email } return "" } func (x *User) GetCreateTime() *timestamppb.Timestamp { if x != nil { return x.CreateTime } return nil } func (x *User) GetUpdateTime() *timestamppb.Timestamp { if x != nil { return x.UpdateTime } return nil } func (x *User) GetAge() int32 { if x != nil && x.Age != nil { return *x.Age } return 0 } func (x *User) GetHeightFeet() float64 { if x != nil && x.HeightFeet != nil { return *x.HeightFeet } return 0 } func (x *User) GetNickname() string { if x != nil && x.Nickname != nil { return *x.Nickname } return "" } func (x *User) GetEnableNotifications() bool { if x != nil && x.EnableNotifications != nil { return *x.EnableNotifications } return false } // The request message for the google.showcase.v1beta1.Identity\CreateUser // method. type CreateUserRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The user to create. User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` } func (x *CreateUserRequest) Reset() { *x = CreateUserRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_identity_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *CreateUserRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*CreateUserRequest) ProtoMessage() {} func (x *CreateUserRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_identity_proto_msgTypes[1] 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 CreateUserRequest.ProtoReflect.Descriptor instead. func (*CreateUserRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_identity_proto_rawDescGZIP(), []int{1} } func (x *CreateUserRequest) GetUser() *User { if x != nil { return x.User } return nil } // The request message for the google.showcase.v1beta1.Identity\GetUser // method. type GetUserRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The resource name of the requested user. Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` } func (x *GetUserRequest) Reset() { *x = GetUserRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_identity_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *GetUserRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*GetUserRequest) ProtoMessage() {} func (x *GetUserRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_identity_proto_msgTypes[2] 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 GetUserRequest.ProtoReflect.Descriptor instead. func (*GetUserRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_identity_proto_rawDescGZIP(), []int{2} } func (x *GetUserRequest) GetName() string { if x != nil { return x.Name } return "" } // The request message for the google.showcase.v1beta1.Identity\UpdateUser // method. type UpdateUserRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The user to update. User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` // The field mask to determine which fields are to be updated. If empty, the // server will assume all fields are to be updated. UpdateMask *fieldmaskpb.FieldMask `protobuf:"bytes,2,opt,name=update_mask,json=updateMask,proto3" json:"update_mask,omitempty"` } func (x *UpdateUserRequest) Reset() { *x = UpdateUserRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_identity_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *UpdateUserRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*UpdateUserRequest) ProtoMessage() {} func (x *UpdateUserRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_identity_proto_msgTypes[3] 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 UpdateUserRequest.ProtoReflect.Descriptor instead. func (*UpdateUserRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_identity_proto_rawDescGZIP(), []int{3} } func (x *UpdateUserRequest) GetUser() *User { if x != nil { return x.User } return nil } func (x *UpdateUserRequest) GetUpdateMask() *fieldmaskpb.FieldMask { if x != nil { return x.UpdateMask } return nil } // The request message for the google.showcase.v1beta1.Identity\DeleteUser // method. type DeleteUserRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The resource name of the user to delete. Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` } func (x *DeleteUserRequest) Reset() { *x = DeleteUserRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_identity_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *DeleteUserRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*DeleteUserRequest) ProtoMessage() {} func (x *DeleteUserRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_identity_proto_msgTypes[4] 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 DeleteUserRequest.ProtoReflect.Descriptor instead. func (*DeleteUserRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_identity_proto_rawDescGZIP(), []int{4} } func (x *DeleteUserRequest) GetName() string { if x != nil { return x.Name } return "" } // The request message for the google.showcase.v1beta1.Identity\ListUsers // method. type ListUsersRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The maximum number of users to return. Server may return fewer users // than requested. If unspecified, server will pick an appropriate default. PageSize int32 `protobuf:"varint,1,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` // The value of google.showcase.v1beta1.ListUsersResponse.next_page_token // returned from the previous call to // `google.showcase.v1beta1.Identity\ListUsers` method. PageToken string `protobuf:"bytes,2,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` } func (x *ListUsersRequest) Reset() { *x = ListUsersRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_identity_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ListUsersRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*ListUsersRequest) ProtoMessage() {} func (x *ListUsersRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_identity_proto_msgTypes[5] 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 ListUsersRequest.ProtoReflect.Descriptor instead. func (*ListUsersRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_identity_proto_rawDescGZIP(), []int{5} } func (x *ListUsersRequest) GetPageSize() int32 { if x != nil { return x.PageSize } return 0 } func (x *ListUsersRequest) GetPageToken() string { if x != nil { return x.PageToken } return "" } // The response message for the google.showcase.v1beta1.Identity\ListUsers // method. type ListUsersResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The list of users. Users []*User `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"` // A token to retrieve next page of results. // Pass this value in ListUsersRequest.page_token field in the subsequent // call to `google.showcase.v1beta1.Message\ListUsers` method to retrieve the // next page of results. NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` } func (x *ListUsersResponse) Reset() { *x = ListUsersResponse{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_identity_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ListUsersResponse) String() string { return protoimpl.X.MessageStringOf(x) } func (*ListUsersResponse) ProtoMessage() {} func (x *ListUsersResponse) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_identity_proto_msgTypes[6] 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 ListUsersResponse.ProtoReflect.Descriptor instead. func (*ListUsersResponse) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_identity_proto_rawDescGZIP(), []int{6} } func (x *ListUsersResponse) GetUsers() []*User { if x != nil { return x.Users } return nil } func (x *ListUsersResponse) GetNextPageToken() string { if x != nil { return x.NextPageToken } return "" } var File_google_showcase_v1beta1_identity_proto protoreflect.FileDescriptor var file_google_showcase_v1beta1_identity_proto_rawDesc = []byte{ 0x0a, 0x26, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x17, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 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, 0x22, 0xe6, 0x03, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x40, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 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, 0x42, 0x03, 0xe0, 0x41, 0x03, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x40, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, 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, 0x42, 0x03, 0xe0, 0x41, 0x03, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x15, 0x0a, 0x03, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, 0x03, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, 0x12, 0x24, 0x0a, 0x0b, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x66, 0x65, 0x65, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x01, 0x48, 0x01, 0x52, 0x0a, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x46, 0x65, 0x65, 0x74, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x08, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x08, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x36, 0x0a, 0x14, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x48, 0x03, 0x52, 0x13, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x88, 0x01, 0x01, 0x3a, 0x2f, 0xea, 0x41, 0x2c, 0x0a, 0x1c, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0c, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x75, 0x73, 0x65, 0x72, 0x7d, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x61, 0x67, 0x65, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x66, 0x65, 0x65, 0x74, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x17, 0x0a, 0x15, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x46, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x4a, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x24, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x1e, 0x0a, 0x1c, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x83, 0x01, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 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, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, 0x6b, 0x22, 0x4d, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x24, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x1e, 0x0a, 0x1c, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x4e, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x70, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x32, 0x8a, 0x06, 0x0a, 0x08, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0xf3, 0x01, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x22, 0x99, 0x01, 0xda, 0x41, 0x1c, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0xda, 0x41, 0x5e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x2c, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x2c, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x66, 0x65, 0x65, 0x74, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x22, 0x0e, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x12, 0x79, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x22, 0x26, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0x83, 0x01, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x3a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x32, 0x1c, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0x78, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x26, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x2a, 0x17, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0x7a, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x12, 0x0e, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x1a, 0x11, 0xca, 0x41, 0x0e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x3a, 0x37, 0x34, 0x36, 0x39, 0x42, 0x71, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x50, 0x01, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x67, 0x61, 0x70, 0x69, 0x63, 0x2d, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x65, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xea, 0x02, 0x19, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x3a, 0x3a, 0x53, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_google_showcase_v1beta1_identity_proto_rawDescOnce sync.Once file_google_showcase_v1beta1_identity_proto_rawDescData = file_google_showcase_v1beta1_identity_proto_rawDesc ) func file_google_showcase_v1beta1_identity_proto_rawDescGZIP() []byte { file_google_showcase_v1beta1_identity_proto_rawDescOnce.Do(func() { file_google_showcase_v1beta1_identity_proto_rawDescData = protoimpl.X.CompressGZIP(file_google_showcase_v1beta1_identity_proto_rawDescData) }) return file_google_showcase_v1beta1_identity_proto_rawDescData } var file_google_showcase_v1beta1_identity_proto_msgTypes = make([]protoimpl.MessageInfo, 7) var file_google_showcase_v1beta1_identity_proto_goTypes = []interface{}{ (*User)(nil), // 0: google.showcase.v1beta1.User (*CreateUserRequest)(nil), // 1: google.showcase.v1beta1.CreateUserRequest (*GetUserRequest)(nil), // 2: google.showcase.v1beta1.GetUserRequest (*UpdateUserRequest)(nil), // 3: google.showcase.v1beta1.UpdateUserRequest (*DeleteUserRequest)(nil), // 4: google.showcase.v1beta1.DeleteUserRequest (*ListUsersRequest)(nil), // 5: google.showcase.v1beta1.ListUsersRequest (*ListUsersResponse)(nil), // 6: google.showcase.v1beta1.ListUsersResponse (*timestamppb.Timestamp)(nil), // 7: google.protobuf.Timestamp (*fieldmaskpb.FieldMask)(nil), // 8: google.protobuf.FieldMask (*emptypb.Empty)(nil), // 9: google.protobuf.Empty } var file_google_showcase_v1beta1_identity_proto_depIdxs = []int32{ 7, // 0: google.showcase.v1beta1.User.create_time:type_name -> google.protobuf.Timestamp 7, // 1: google.showcase.v1beta1.User.update_time:type_name -> google.protobuf.Timestamp 0, // 2: google.showcase.v1beta1.CreateUserRequest.user:type_name -> google.showcase.v1beta1.User 0, // 3: google.showcase.v1beta1.UpdateUserRequest.user:type_name -> google.showcase.v1beta1.User 8, // 4: google.showcase.v1beta1.UpdateUserRequest.update_mask:type_name -> google.protobuf.FieldMask 0, // 5: google.showcase.v1beta1.ListUsersResponse.users:type_name -> google.showcase.v1beta1.User 1, // 6: google.showcase.v1beta1.Identity.CreateUser:input_type -> google.showcase.v1beta1.CreateUserRequest 2, // 7: google.showcase.v1beta1.Identity.GetUser:input_type -> google.showcase.v1beta1.GetUserRequest 3, // 8: google.showcase.v1beta1.Identity.UpdateUser:input_type -> google.showcase.v1beta1.UpdateUserRequest 4, // 9: google.showcase.v1beta1.Identity.DeleteUser:input_type -> google.showcase.v1beta1.DeleteUserRequest 5, // 10: google.showcase.v1beta1.Identity.ListUsers:input_type -> google.showcase.v1beta1.ListUsersRequest 0, // 11: google.showcase.v1beta1.Identity.CreateUser:output_type -> google.showcase.v1beta1.User 0, // 12: google.showcase.v1beta1.Identity.GetUser:output_type -> google.showcase.v1beta1.User 0, // 13: google.showcase.v1beta1.Identity.UpdateUser:output_type -> google.showcase.v1beta1.User 9, // 14: google.showcase.v1beta1.Identity.DeleteUser:output_type -> google.protobuf.Empty 6, // 15: google.showcase.v1beta1.Identity.ListUsers:output_type -> google.showcase.v1beta1.ListUsersResponse 11, // [11:16] is the sub-list for method output_type 6, // [6:11] is the sub-list for method input_type 6, // [6:6] is the sub-list for extension type_name 6, // [6:6] is the sub-list for extension extendee 0, // [0:6] is the sub-list for field type_name } func init() { file_google_showcase_v1beta1_identity_proto_init() } func file_google_showcase_v1beta1_identity_proto_init() { if File_google_showcase_v1beta1_identity_proto != nil { return } if !protoimpl.UnsafeEnabled { file_google_showcase_v1beta1_identity_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*User); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_identity_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateUserRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_identity_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetUserRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_identity_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UpdateUserRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_identity_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DeleteUserRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_identity_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListUsersRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_identity_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListUsersResponse); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } file_google_showcase_v1beta1_identity_proto_msgTypes[0].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_google_showcase_v1beta1_identity_proto_rawDesc, NumEnums: 0, NumMessages: 7, NumExtensions: 0, NumServices: 1, }, GoTypes: file_google_showcase_v1beta1_identity_proto_goTypes, DependencyIndexes: file_google_showcase_v1beta1_identity_proto_depIdxs, MessageInfos: file_google_showcase_v1beta1_identity_proto_msgTypes, }.Build() File_google_showcase_v1beta1_identity_proto = out.File file_google_showcase_v1beta1_identity_proto_rawDesc = nil file_google_showcase_v1beta1_identity_proto_goTypes = nil file_google_showcase_v1beta1_identity_proto_depIdxs = nil } // Reference imports to suppress errors if they are not otherwise used. var _ context.Context var _ grpc.ClientConnInterface // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. const _ = grpc.SupportPackageIsVersion6 // IdentityClient is the client API for Identity service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type IdentityClient interface { // Creates a user. CreateUser(ctx context.Context, in *CreateUserRequest, opts ...grpc.CallOption) (*User, error) // Retrieves the User with the given uri. GetUser(ctx context.Context, in *GetUserRequest, opts ...grpc.CallOption) (*User, error) // Updates a user. UpdateUser(ctx context.Context, in *UpdateUserRequest, opts ...grpc.CallOption) (*User, error) // Deletes a user, their profile, and all of their authored messages. DeleteUser(ctx context.Context, in *DeleteUserRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) // Lists all users. ListUsers(ctx context.Context, in *ListUsersRequest, opts ...grpc.CallOption) (*ListUsersResponse, error) } type identityClient struct { cc grpc.ClientConnInterface } func NewIdentityClient(cc grpc.ClientConnInterface) IdentityClient { return &identityClient{cc} } func (c *identityClient) CreateUser(ctx context.Context, in *CreateUserRequest, opts ...grpc.CallOption) (*User, error) { out := new(User) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Identity/CreateUser", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *identityClient) GetUser(ctx context.Context, in *GetUserRequest, opts ...grpc.CallOption) (*User, error) { out := new(User) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Identity/GetUser", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *identityClient) UpdateUser(ctx context.Context, in *UpdateUserRequest, opts ...grpc.CallOption) (*User, error) { out := new(User) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Identity/UpdateUser", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *identityClient) DeleteUser(ctx context.Context, in *DeleteUserRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Identity/DeleteUser", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *identityClient) ListUsers(ctx context.Context, in *ListUsersRequest, opts ...grpc.CallOption) (*ListUsersResponse, error) { out := new(ListUsersResponse) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Identity/ListUsers", in, out, opts...) if err != nil { return nil, err } return out, nil } // IdentityServer is the server API for Identity service. type IdentityServer interface { // Creates a user. CreateUser(context.Context, *CreateUserRequest) (*User, error) // Retrieves the User with the given uri. GetUser(context.Context, *GetUserRequest) (*User, error) // Updates a user. UpdateUser(context.Context, *UpdateUserRequest) (*User, error) // Deletes a user, their profile, and all of their authored messages. DeleteUser(context.Context, *DeleteUserRequest) (*emptypb.Empty, error) // Lists all users. ListUsers(context.Context, *ListUsersRequest) (*ListUsersResponse, error) } // UnimplementedIdentityServer can be embedded to have forward compatible implementations. type UnimplementedIdentityServer struct { } func (*UnimplementedIdentityServer) CreateUser(context.Context, *CreateUserRequest) (*User, error) { return nil, status.Errorf(codes.Unimplemented, "method CreateUser not implemented") } func (*UnimplementedIdentityServer) GetUser(context.Context, *GetUserRequest) (*User, error) { return nil, status.Errorf(codes.Unimplemented, "method GetUser not implemented") } func (*UnimplementedIdentityServer) UpdateUser(context.Context, *UpdateUserRequest) (*User, error) { return nil, status.Errorf(codes.Unimplemented, "method UpdateUser not implemented") } func (*UnimplementedIdentityServer) DeleteUser(context.Context, *DeleteUserRequest) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method DeleteUser not implemented") } func (*UnimplementedIdentityServer) ListUsers(context.Context, *ListUsersRequest) (*ListUsersResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListUsers not implemented") } func RegisterIdentityServer(s *grpc.Server, srv IdentityServer) { s.RegisterService(&_Identity_serviceDesc, srv) } func _Identity_CreateUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(CreateUserRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(IdentityServer).CreateUser(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Identity/CreateUser", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(IdentityServer).CreateUser(ctx, req.(*CreateUserRequest)) } return interceptor(ctx, in, info, handler) } func _Identity_GetUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetUserRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(IdentityServer).GetUser(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Identity/GetUser", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(IdentityServer).GetUser(ctx, req.(*GetUserRequest)) } return interceptor(ctx, in, info, handler) } func _Identity_UpdateUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(UpdateUserRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(IdentityServer).UpdateUser(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Identity/UpdateUser", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(IdentityServer).UpdateUser(ctx, req.(*UpdateUserRequest)) } return interceptor(ctx, in, info, handler) } func _Identity_DeleteUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(DeleteUserRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(IdentityServer).DeleteUser(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Identity/DeleteUser", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(IdentityServer).DeleteUser(ctx, req.(*DeleteUserRequest)) } return interceptor(ctx, in, info, handler) } func _Identity_ListUsers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ListUsersRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(IdentityServer).ListUsers(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Identity/ListUsers", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(IdentityServer).ListUsers(ctx, req.(*ListUsersRequest)) } return interceptor(ctx, in, info, handler) } var _Identity_serviceDesc = grpc.ServiceDesc{ ServiceName: "google.showcase.v1beta1.Identity", HandlerType: (*IdentityServer)(nil), Methods: []grpc.MethodDesc{ { MethodName: "CreateUser", Handler: _Identity_CreateUser_Handler, }, { MethodName: "GetUser", Handler: _Identity_GetUser_Handler, }, { MethodName: "UpdateUser", Handler: _Identity_UpdateUser_Handler, }, { MethodName: "DeleteUser", Handler: _Identity_DeleteUser_Handler, }, { MethodName: "ListUsers", Handler: _Identity_ListUsers_Handler, }, }, Streams: []grpc.StreamDesc{}, Metadata: "google/showcase/v1beta1/identity.proto", } ================================================ FILE: server/genproto/messaging.pb.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.33.0 // protoc v3.20.3 // source: google/showcase/v1beta1/messaging.proto package genproto import ( longrunningpb "cloud.google.com/go/longrunning/autogen/longrunningpb" context "context" _ "google.golang.org/genproto/googleapis/api/annotations" errdetails "google.golang.org/genproto/googleapis/rpc/errdetails" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" emptypb "google.golang.org/protobuf/types/known/emptypb" fieldmaskpb "google.golang.org/protobuf/types/known/fieldmaskpb" timestamppb "google.golang.org/protobuf/types/known/timestamppb" 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) ) // The action that triggered the blurb to be returned. type StreamBlurbsResponse_Action int32 const ( StreamBlurbsResponse_ACTION_UNSPECIFIED StreamBlurbsResponse_Action = 0 // Specifies that the blurb was created. StreamBlurbsResponse_CREATE StreamBlurbsResponse_Action = 1 // Specifies that the blurb was updated. StreamBlurbsResponse_UPDATE StreamBlurbsResponse_Action = 2 // Specifies that the blurb was deleted. StreamBlurbsResponse_DELETE StreamBlurbsResponse_Action = 3 ) // Enum value maps for StreamBlurbsResponse_Action. var ( StreamBlurbsResponse_Action_name = map[int32]string{ 0: "ACTION_UNSPECIFIED", 1: "CREATE", 2: "UPDATE", 3: "DELETE", } StreamBlurbsResponse_Action_value = map[string]int32{ "ACTION_UNSPECIFIED": 0, "CREATE": 1, "UPDATE": 2, "DELETE": 3, } ) func (x StreamBlurbsResponse_Action) Enum() *StreamBlurbsResponse_Action { p := new(StreamBlurbsResponse_Action) *p = x return p } func (x StreamBlurbsResponse_Action) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (StreamBlurbsResponse_Action) Descriptor() protoreflect.EnumDescriptor { return file_google_showcase_v1beta1_messaging_proto_enumTypes[0].Descriptor() } func (StreamBlurbsResponse_Action) Type() protoreflect.EnumType { return &file_google_showcase_v1beta1_messaging_proto_enumTypes[0] } func (x StreamBlurbsResponse_Action) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use StreamBlurbsResponse_Action.Descriptor instead. func (StreamBlurbsResponse_Action) EnumDescriptor() ([]byte, []int) { return file_google_showcase_v1beta1_messaging_proto_rawDescGZIP(), []int{18, 0} } // A chat room. type Room struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The resource name of the chat room. Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // The human readable name of the chat room. DisplayName string `protobuf:"bytes,2,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` // The description of the chat room. Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` // The timestamp at which the room was created. CreateTime *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=create_time,json=createTime,proto3" json:"create_time,omitempty"` // The latest timestamp at which the room was updated. UpdateTime *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=update_time,json=updateTime,proto3" json:"update_time,omitempty"` } func (x *Room) Reset() { *x = Room{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Room) String() string { return protoimpl.X.MessageStringOf(x) } func (*Room) ProtoMessage() {} func (x *Room) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_messaging_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 Room.ProtoReflect.Descriptor instead. func (*Room) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_messaging_proto_rawDescGZIP(), []int{0} } func (x *Room) GetName() string { if x != nil { return x.Name } return "" } func (x *Room) GetDisplayName() string { if x != nil { return x.DisplayName } return "" } func (x *Room) GetDescription() string { if x != nil { return x.Description } return "" } func (x *Room) GetCreateTime() *timestamppb.Timestamp { if x != nil { return x.CreateTime } return nil } func (x *Room) GetUpdateTime() *timestamppb.Timestamp { if x != nil { return x.UpdateTime } return nil } // The request message for the google.showcase.v1beta1.Messaging\CreateRoom // method. type CreateRoomRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The room to create. Room *Room `protobuf:"bytes,1,opt,name=room,proto3" json:"room,omitempty"` } func (x *CreateRoomRequest) Reset() { *x = CreateRoomRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *CreateRoomRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*CreateRoomRequest) ProtoMessage() {} func (x *CreateRoomRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[1] 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 CreateRoomRequest.ProtoReflect.Descriptor instead. func (*CreateRoomRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_messaging_proto_rawDescGZIP(), []int{1} } func (x *CreateRoomRequest) GetRoom() *Room { if x != nil { return x.Room } return nil } // The request message for the google.showcase.v1beta1.Messaging\GetRoom // method. type GetRoomRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The resource name of the requested room. Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` } func (x *GetRoomRequest) Reset() { *x = GetRoomRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *GetRoomRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*GetRoomRequest) ProtoMessage() {} func (x *GetRoomRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[2] 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 GetRoomRequest.ProtoReflect.Descriptor instead. func (*GetRoomRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_messaging_proto_rawDescGZIP(), []int{2} } func (x *GetRoomRequest) GetName() string { if x != nil { return x.Name } return "" } // The request message for the google.showcase.v1beta1.Messaging\UpdateRoom // method. type UpdateRoomRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The room to update. Room *Room `protobuf:"bytes,1,opt,name=room,proto3" json:"room,omitempty"` // The field mask to determine which fields are to be updated. If empty, the // server will assume all fields are to be updated. UpdateMask *fieldmaskpb.FieldMask `protobuf:"bytes,2,opt,name=update_mask,json=updateMask,proto3" json:"update_mask,omitempty"` } func (x *UpdateRoomRequest) Reset() { *x = UpdateRoomRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *UpdateRoomRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*UpdateRoomRequest) ProtoMessage() {} func (x *UpdateRoomRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[3] 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 UpdateRoomRequest.ProtoReflect.Descriptor instead. func (*UpdateRoomRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_messaging_proto_rawDescGZIP(), []int{3} } func (x *UpdateRoomRequest) GetRoom() *Room { if x != nil { return x.Room } return nil } func (x *UpdateRoomRequest) GetUpdateMask() *fieldmaskpb.FieldMask { if x != nil { return x.UpdateMask } return nil } // The request message for the google.showcase.v1beta1.Messaging\DeleteRoom // method. type DeleteRoomRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The resource name of the requested room. Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` } func (x *DeleteRoomRequest) Reset() { *x = DeleteRoomRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *DeleteRoomRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*DeleteRoomRequest) ProtoMessage() {} func (x *DeleteRoomRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[4] 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 DeleteRoomRequest.ProtoReflect.Descriptor instead. func (*DeleteRoomRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_messaging_proto_rawDescGZIP(), []int{4} } func (x *DeleteRoomRequest) GetName() string { if x != nil { return x.Name } return "" } // The request message for the google.showcase.v1beta1.Messaging\ListRooms // method. type ListRoomsRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The maximum number of rooms return. Server may return fewer rooms // than requested. If unspecified, server will pick an appropriate default. PageSize int32 `protobuf:"varint,1,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` // The value of google.showcase.v1beta1.ListRoomsResponse.next_page_token // returned from the previous call to // `google.showcase.v1beta1.Messaging\ListRooms` method. PageToken string `protobuf:"bytes,2,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` } func (x *ListRoomsRequest) Reset() { *x = ListRoomsRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ListRoomsRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*ListRoomsRequest) ProtoMessage() {} func (x *ListRoomsRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[5] 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 ListRoomsRequest.ProtoReflect.Descriptor instead. func (*ListRoomsRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_messaging_proto_rawDescGZIP(), []int{5} } func (x *ListRoomsRequest) GetPageSize() int32 { if x != nil { return x.PageSize } return 0 } func (x *ListRoomsRequest) GetPageToken() string { if x != nil { return x.PageToken } return "" } // The response message for the google.showcase.v1beta1.Messaging\ListRooms // method. type ListRoomsResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The list of rooms. Rooms []*Room `protobuf:"bytes,1,rep,name=rooms,proto3" json:"rooms,omitempty"` // A token to retrieve next page of results. // Pass this value in ListRoomsRequest.page_token field in the subsequent // call to `google.showcase.v1beta1.Messaging\ListRooms` method to retrieve // the next page of results. NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` } func (x *ListRoomsResponse) Reset() { *x = ListRoomsResponse{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ListRoomsResponse) String() string { return protoimpl.X.MessageStringOf(x) } func (*ListRoomsResponse) ProtoMessage() {} func (x *ListRoomsResponse) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[6] 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 ListRoomsResponse.ProtoReflect.Descriptor instead. func (*ListRoomsResponse) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_messaging_proto_rawDescGZIP(), []int{6} } func (x *ListRoomsResponse) GetRooms() []*Room { if x != nil { return x.Rooms } return nil } func (x *ListRoomsResponse) GetNextPageToken() string { if x != nil { return x.NextPageToken } return "" } // This protocol buffer message represents a blurb sent to a chat room or // posted on a user profile. type Blurb struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The resource name of the chat room. Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // The resource name of the blurb's author. User string `protobuf:"bytes,2,opt,name=user,proto3" json:"user,omitempty"` // Types that are assignable to Content: // // *Blurb_Text // *Blurb_Image Content isBlurb_Content `protobuf_oneof:"content"` // The timestamp at which the blurb was created. CreateTime *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=create_time,json=createTime,proto3" json:"create_time,omitempty"` // The latest timestamp at which the blurb was updated. UpdateTime *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=update_time,json=updateTime,proto3" json:"update_time,omitempty"` // (-- aip.dev/not-precedent: This is designed for testing non-slash // // resource patterns. Ordinarily, non-slash separators are discouraged. // --) // // Types that are assignable to LegacyId: // // *Blurb_LegacyRoomId // *Blurb_LegacyUserId LegacyId isBlurb_LegacyId `protobuf_oneof:"legacy_id"` } func (x *Blurb) Reset() { *x = Blurb{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Blurb) String() string { return protoimpl.X.MessageStringOf(x) } func (*Blurb) ProtoMessage() {} func (x *Blurb) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[7] 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 Blurb.ProtoReflect.Descriptor instead. func (*Blurb) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_messaging_proto_rawDescGZIP(), []int{7} } func (x *Blurb) GetName() string { if x != nil { return x.Name } return "" } func (x *Blurb) GetUser() string { if x != nil { return x.User } return "" } func (m *Blurb) GetContent() isBlurb_Content { if m != nil { return m.Content } return nil } func (x *Blurb) GetText() string { if x, ok := x.GetContent().(*Blurb_Text); ok { return x.Text } return "" } func (x *Blurb) GetImage() []byte { if x, ok := x.GetContent().(*Blurb_Image); ok { return x.Image } return nil } func (x *Blurb) GetCreateTime() *timestamppb.Timestamp { if x != nil { return x.CreateTime } return nil } func (x *Blurb) GetUpdateTime() *timestamppb.Timestamp { if x != nil { return x.UpdateTime } return nil } func (m *Blurb) GetLegacyId() isBlurb_LegacyId { if m != nil { return m.LegacyId } return nil } func (x *Blurb) GetLegacyRoomId() string { if x, ok := x.GetLegacyId().(*Blurb_LegacyRoomId); ok { return x.LegacyRoomId } return "" } func (x *Blurb) GetLegacyUserId() string { if x, ok := x.GetLegacyId().(*Blurb_LegacyUserId); ok { return x.LegacyUserId } return "" } type isBlurb_Content interface { isBlurb_Content() } type Blurb_Text struct { // The textual content of this blurb. Text string `protobuf:"bytes,3,opt,name=text,proto3,oneof"` } type Blurb_Image struct { // The image content of this blurb. Image []byte `protobuf:"bytes,4,opt,name=image,proto3,oneof"` } func (*Blurb_Text) isBlurb_Content() {} func (*Blurb_Image) isBlurb_Content() {} type isBlurb_LegacyId interface { isBlurb_LegacyId() } type Blurb_LegacyRoomId struct { // The legacy id of the room. This field is used to signal // the use of the compound resource pattern // `rooms/{room}/blurbs/legacy/{legacy_room}.{blurb}` LegacyRoomId string `protobuf:"bytes,7,opt,name=legacy_room_id,json=legacyRoomId,proto3,oneof"` } type Blurb_LegacyUserId struct { // The legacy id of the user. This field is used to signal // the use of the compound resource pattern // `users/{user}/profile/blurbs/legacy/{legacy_user}~{blurb}` LegacyUserId string `protobuf:"bytes,8,opt,name=legacy_user_id,json=legacyUserId,proto3,oneof"` } func (*Blurb_LegacyRoomId) isBlurb_LegacyId() {} func (*Blurb_LegacyUserId) isBlurb_LegacyId() {} // The request message for the google.showcase.v1beta1.Messaging\CreateBlurb // method. type CreateBlurbRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The resource name of the chat room or user profile that this blurb will // be tied to. Parent string `protobuf:"bytes,1,opt,name=parent,proto3" json:"parent,omitempty"` // The blurb to create. Blurb *Blurb `protobuf:"bytes,2,opt,name=blurb,proto3" json:"blurb,omitempty"` } func (x *CreateBlurbRequest) Reset() { *x = CreateBlurbRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *CreateBlurbRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*CreateBlurbRequest) ProtoMessage() {} func (x *CreateBlurbRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[8] 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 CreateBlurbRequest.ProtoReflect.Descriptor instead. func (*CreateBlurbRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_messaging_proto_rawDescGZIP(), []int{8} } func (x *CreateBlurbRequest) GetParent() string { if x != nil { return x.Parent } return "" } func (x *CreateBlurbRequest) GetBlurb() *Blurb { if x != nil { return x.Blurb } return nil } // The request message for the google.showcase.v1beta1.Messaging\GetBlurb // method. type GetBlurbRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The resource name of the requested blurb. Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` } func (x *GetBlurbRequest) Reset() { *x = GetBlurbRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *GetBlurbRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*GetBlurbRequest) ProtoMessage() {} func (x *GetBlurbRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[9] 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 GetBlurbRequest.ProtoReflect.Descriptor instead. func (*GetBlurbRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_messaging_proto_rawDescGZIP(), []int{9} } func (x *GetBlurbRequest) GetName() string { if x != nil { return x.Name } return "" } // The request message for the google.showcase.v1beta1.Messaging\UpdateBlurb // method. type UpdateBlurbRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The blurb to update. Blurb *Blurb `protobuf:"bytes,1,opt,name=blurb,proto3" json:"blurb,omitempty"` // The field mask to determine which fields are to be updated. If empty, the // server will assume all fields are to be updated. UpdateMask *fieldmaskpb.FieldMask `protobuf:"bytes,2,opt,name=update_mask,json=updateMask,proto3" json:"update_mask,omitempty"` } func (x *UpdateBlurbRequest) Reset() { *x = UpdateBlurbRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *UpdateBlurbRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*UpdateBlurbRequest) ProtoMessage() {} func (x *UpdateBlurbRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[10] 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 UpdateBlurbRequest.ProtoReflect.Descriptor instead. func (*UpdateBlurbRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_messaging_proto_rawDescGZIP(), []int{10} } func (x *UpdateBlurbRequest) GetBlurb() *Blurb { if x != nil { return x.Blurb } return nil } func (x *UpdateBlurbRequest) GetUpdateMask() *fieldmaskpb.FieldMask { if x != nil { return x.UpdateMask } return nil } // The request message for the google.showcase.v1beta1.Messaging\DeleteBlurb // method. type DeleteBlurbRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The resource name of the requested blurb. Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` } func (x *DeleteBlurbRequest) Reset() { *x = DeleteBlurbRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *DeleteBlurbRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*DeleteBlurbRequest) ProtoMessage() {} func (x *DeleteBlurbRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[11] 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 DeleteBlurbRequest.ProtoReflect.Descriptor instead. func (*DeleteBlurbRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_messaging_proto_rawDescGZIP(), []int{11} } func (x *DeleteBlurbRequest) GetName() string { if x != nil { return x.Name } return "" } // The request message for the google.showcase.v1beta1.Messaging\ListBlurbs // method. type ListBlurbsRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The resource name of the requested room or profile who blurbs to list. Parent string `protobuf:"bytes,1,opt,name=parent,proto3" json:"parent,omitempty"` // The maximum number of blurbs to return. Server may return fewer // blurbs than requested. If unspecified, server will pick an appropriate // default. PageSize int32 `protobuf:"varint,2,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` // The value of google.showcase.v1beta1.ListBlurbsResponse.next_page_token // returned from the previous call to // `google.showcase.v1beta1.Messaging\ListBlurbs` method. PageToken string `protobuf:"bytes,3,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` } func (x *ListBlurbsRequest) Reset() { *x = ListBlurbsRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ListBlurbsRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*ListBlurbsRequest) ProtoMessage() {} func (x *ListBlurbsRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[12] 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 ListBlurbsRequest.ProtoReflect.Descriptor instead. func (*ListBlurbsRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_messaging_proto_rawDescGZIP(), []int{12} } func (x *ListBlurbsRequest) GetParent() string { if x != nil { return x.Parent } return "" } func (x *ListBlurbsRequest) GetPageSize() int32 { if x != nil { return x.PageSize } return 0 } func (x *ListBlurbsRequest) GetPageToken() string { if x != nil { return x.PageToken } return "" } // The response message for the google.showcase.v1beta1.Messaging\ListBlurbs // method. type ListBlurbsResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The list of blurbs. Blurbs []*Blurb `protobuf:"bytes,1,rep,name=blurbs,proto3" json:"blurbs,omitempty"` // A token to retrieve next page of results. // Pass this value in ListBlurbsRequest.page_token field in the subsequent // call to `google.showcase.v1beta1.Blurb\ListBlurbs` method to retrieve // the next page of results. NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` } func (x *ListBlurbsResponse) Reset() { *x = ListBlurbsResponse{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ListBlurbsResponse) String() string { return protoimpl.X.MessageStringOf(x) } func (*ListBlurbsResponse) ProtoMessage() {} func (x *ListBlurbsResponse) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[13] 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 ListBlurbsResponse.ProtoReflect.Descriptor instead. func (*ListBlurbsResponse) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_messaging_proto_rawDescGZIP(), []int{13} } func (x *ListBlurbsResponse) GetBlurbs() []*Blurb { if x != nil { return x.Blurbs } return nil } func (x *ListBlurbsResponse) GetNextPageToken() string { if x != nil { return x.NextPageToken } return "" } // The request message for the google.showcase.v1beta1.Messaging\SearchBlurbs // method. type SearchBlurbsRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The query used to search for blurbs containing to words of this string. // Only posts that contain an exact match of a queried word will be returned. Query string `protobuf:"bytes,1,opt,name=query,proto3" json:"query,omitempty"` // The rooms or profiles to search. If unset, `SearchBlurbs` will search all // rooms and all profiles. Parent string `protobuf:"bytes,2,opt,name=parent,proto3" json:"parent,omitempty"` // The maximum number of blurbs return. Server may return fewer // blurbs than requested. If unspecified, server will pick an appropriate // default. PageSize int32 `protobuf:"varint,3,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` // The value of // google.showcase.v1beta1.SearchBlurbsResponse.next_page_token // returned from the previous call to // `google.showcase.v1beta1.Messaging\SearchBlurbs` method. PageToken string `protobuf:"bytes,4,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` } func (x *SearchBlurbsRequest) Reset() { *x = SearchBlurbsRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *SearchBlurbsRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*SearchBlurbsRequest) ProtoMessage() {} func (x *SearchBlurbsRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[14] 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 SearchBlurbsRequest.ProtoReflect.Descriptor instead. func (*SearchBlurbsRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_messaging_proto_rawDescGZIP(), []int{14} } func (x *SearchBlurbsRequest) GetQuery() string { if x != nil { return x.Query } return "" } func (x *SearchBlurbsRequest) GetParent() string { if x != nil { return x.Parent } return "" } func (x *SearchBlurbsRequest) GetPageSize() int32 { if x != nil { return x.PageSize } return 0 } func (x *SearchBlurbsRequest) GetPageToken() string { if x != nil { return x.PageToken } return "" } // The operation metadata message for the // google.showcase.v1beta1.Messaging\SearchBlurbs method. type SearchBlurbsMetadata struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // This signals to the client when to next poll for response. RetryInfo *errdetails.RetryInfo `protobuf:"bytes,1,opt,name=retry_info,json=retryInfo,proto3" json:"retry_info,omitempty"` } func (x *SearchBlurbsMetadata) Reset() { *x = SearchBlurbsMetadata{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *SearchBlurbsMetadata) String() string { return protoimpl.X.MessageStringOf(x) } func (*SearchBlurbsMetadata) ProtoMessage() {} func (x *SearchBlurbsMetadata) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[15] 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 SearchBlurbsMetadata.ProtoReflect.Descriptor instead. func (*SearchBlurbsMetadata) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_messaging_proto_rawDescGZIP(), []int{15} } func (x *SearchBlurbsMetadata) GetRetryInfo() *errdetails.RetryInfo { if x != nil { return x.RetryInfo } return nil } // The operation response message for the // google.showcase.v1beta1.Messaging\SearchBlurbs method. type SearchBlurbsResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Blurbs that matched the search query. Blurbs []*Blurb `protobuf:"bytes,1,rep,name=blurbs,proto3" json:"blurbs,omitempty"` // A token to retrieve next page of results. // Pass this value in SearchBlurbsRequest.page_token field in the subsequent // call to `google.showcase.v1beta1.Blurb\SearchBlurbs` method to // retrieve the next page of results. NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` } func (x *SearchBlurbsResponse) Reset() { *x = SearchBlurbsResponse{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *SearchBlurbsResponse) String() string { return protoimpl.X.MessageStringOf(x) } func (*SearchBlurbsResponse) ProtoMessage() {} func (x *SearchBlurbsResponse) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[16] 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 SearchBlurbsResponse.ProtoReflect.Descriptor instead. func (*SearchBlurbsResponse) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_messaging_proto_rawDescGZIP(), []int{16} } func (x *SearchBlurbsResponse) GetBlurbs() []*Blurb { if x != nil { return x.Blurbs } return nil } func (x *SearchBlurbsResponse) GetNextPageToken() string { if x != nil { return x.NextPageToken } return "" } // The request message for the google.showcase.v1beta1.Messaging\StreamBlurbs // method. type StreamBlurbsRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The resource name of a chat room or user profile whose blurbs to stream. Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // The time at which this stream will close. ExpireTime *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=expire_time,json=expireTime,proto3" json:"expire_time,omitempty"` } func (x *StreamBlurbsRequest) Reset() { *x = StreamBlurbsRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *StreamBlurbsRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*StreamBlurbsRequest) ProtoMessage() {} func (x *StreamBlurbsRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[17] 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 StreamBlurbsRequest.ProtoReflect.Descriptor instead. func (*StreamBlurbsRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_messaging_proto_rawDescGZIP(), []int{17} } func (x *StreamBlurbsRequest) GetName() string { if x != nil { return x.Name } return "" } func (x *StreamBlurbsRequest) GetExpireTime() *timestamppb.Timestamp { if x != nil { return x.ExpireTime } return nil } // The response message for the google.showcase.v1beta1.Messaging\StreamBlurbs // method. type StreamBlurbsResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The blurb that was either created, updated, or deleted. Blurb *Blurb `protobuf:"bytes,1,opt,name=blurb,proto3" json:"blurb,omitempty"` // The action that triggered the blurb to be returned. Action StreamBlurbsResponse_Action `protobuf:"varint,2,opt,name=action,proto3,enum=google.showcase.v1beta1.StreamBlurbsResponse_Action" json:"action,omitempty"` } func (x *StreamBlurbsResponse) Reset() { *x = StreamBlurbsResponse{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *StreamBlurbsResponse) String() string { return protoimpl.X.MessageStringOf(x) } func (*StreamBlurbsResponse) ProtoMessage() {} func (x *StreamBlurbsResponse) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[18] 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 StreamBlurbsResponse.ProtoReflect.Descriptor instead. func (*StreamBlurbsResponse) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_messaging_proto_rawDescGZIP(), []int{18} } func (x *StreamBlurbsResponse) GetBlurb() *Blurb { if x != nil { return x.Blurb } return nil } func (x *StreamBlurbsResponse) GetAction() StreamBlurbsResponse_Action { if x != nil { return x.Action } return StreamBlurbsResponse_ACTION_UNSPECIFIED } // The response message for the google.showcase.v1beta1.Messaging\SendBlurbs // method. type SendBlurbsResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The names of successful blurb creations. Names []string `protobuf:"bytes,1,rep,name=names,proto3" json:"names,omitempty"` } func (x *SendBlurbsResponse) Reset() { *x = SendBlurbsResponse{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *SendBlurbsResponse) String() string { return protoimpl.X.MessageStringOf(x) } func (*SendBlurbsResponse) ProtoMessage() {} func (x *SendBlurbsResponse) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[19] 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 SendBlurbsResponse.ProtoReflect.Descriptor instead. func (*SendBlurbsResponse) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_messaging_proto_rawDescGZIP(), []int{19} } func (x *SendBlurbsResponse) GetNames() []string { if x != nil { return x.Names } return nil } // The request message for the google.showcase.v1beta1.Messaging\Connect // method. type ConnectRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Types that are assignable to Request: // // *ConnectRequest_Config // *ConnectRequest_Blurb Request isConnectRequest_Request `protobuf_oneof:"request"` } func (x *ConnectRequest) Reset() { *x = ConnectRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ConnectRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*ConnectRequest) ProtoMessage() {} func (x *ConnectRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[20] 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 ConnectRequest.ProtoReflect.Descriptor instead. func (*ConnectRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_messaging_proto_rawDescGZIP(), []int{20} } func (m *ConnectRequest) GetRequest() isConnectRequest_Request { if m != nil { return m.Request } return nil } func (x *ConnectRequest) GetConfig() *ConnectRequest_ConnectConfig { if x, ok := x.GetRequest().(*ConnectRequest_Config); ok { return x.Config } return nil } func (x *ConnectRequest) GetBlurb() *Blurb { if x, ok := x.GetRequest().(*ConnectRequest_Blurb); ok { return x.Blurb } return nil } type isConnectRequest_Request interface { isConnectRequest_Request() } type ConnectRequest_Config struct { // Provides information that specifies how to process subsequent requests. // The first `ConnectRequest` message must contain a `config` message. Config *ConnectRequest_ConnectConfig `protobuf:"bytes,1,opt,name=config,proto3,oneof"` } type ConnectRequest_Blurb struct { // The blurb to be created. Blurb *Blurb `protobuf:"bytes,2,opt,name=blurb,proto3,oneof"` } func (*ConnectRequest_Config) isConnectRequest_Request() {} func (*ConnectRequest_Blurb) isConnectRequest_Request() {} type ConnectRequest_ConnectConfig struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The room or profile to follow and create messages for. Parent string `protobuf:"bytes,1,opt,name=parent,proto3" json:"parent,omitempty"` } func (x *ConnectRequest_ConnectConfig) Reset() { *x = ConnectRequest_ConnectConfig{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ConnectRequest_ConnectConfig) String() string { return protoimpl.X.MessageStringOf(x) } func (*ConnectRequest_ConnectConfig) ProtoMessage() {} func (x *ConnectRequest_ConnectConfig) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_messaging_proto_msgTypes[21] 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 ConnectRequest_ConnectConfig.ProtoReflect.Descriptor instead. func (*ConnectRequest_ConnectConfig) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_messaging_proto_rawDescGZIP(), []int{20, 0} } func (x *ConnectRequest_ConnectConfig) GetParent() string { if x != nil { return x.Parent } return "" } var File_google_showcase_v1beta1_messaging_proto protoreflect.FileDescriptor var file_google_showcase_v1beta1_messaging_proto_rawDesc = []byte{ 0x0a, 0x27, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x17, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x23, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x6c, 0x6f, 0x6e, 0x67, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x2f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 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, 0x72, 0x70, 0x63, 0x2f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x99, 0x02, 0x0a, 0x04, 0x52, 0x6f, 0x6f, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x40, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 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, 0x42, 0x03, 0xe0, 0x41, 0x03, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x40, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, 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, 0x42, 0x03, 0xe0, 0x41, 0x03, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x3a, 0x2f, 0xea, 0x41, 0x2c, 0x0a, 0x1c, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x52, 0x6f, 0x6f, 0x6d, 0x12, 0x0c, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6f, 0x6d, 0x7d, 0x22, 0x46, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x22, 0x4a, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x24, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x1e, 0x0a, 0x1c, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x83, 0x01, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x12, 0x3b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 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, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, 0x6b, 0x22, 0x4d, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x24, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x1e, 0x0a, 0x1c, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x4e, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x70, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x05, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x05, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xc3, 0x04, 0x0a, 0x05, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x24, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x1e, 0x0a, 0x1c, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x16, 0x0a, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x40, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, 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, 0x42, 0x03, 0xe0, 0x41, 0x03, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x40, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 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, 0x42, 0x03, 0xe0, 0x41, 0x03, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0c, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x52, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0e, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0c, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x3a, 0xd1, 0x01, 0xea, 0x41, 0xcd, 0x01, 0x0a, 0x1d, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x12, 0x38, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x75, 0x73, 0x65, 0x72, 0x7d, 0x2f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x2f, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x2f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x2f, 0x7b, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x7d, 0x7e, 0x7b, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x7d, 0x12, 0x23, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x75, 0x73, 0x65, 0x72, 0x7d, 0x2f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x2f, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x2f, 0x7b, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x7d, 0x12, 0x1b, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6f, 0x6d, 0x7d, 0x2f, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x2f, 0x7b, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x7d, 0x12, 0x30, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x6f, 0x6d, 0x7d, 0x2f, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x2f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x2f, 0x7b, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x72, 0x6f, 0x6f, 0x6d, 0x7d, 0x2e, 0x7b, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x7d, 0x42, 0x09, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x0b, 0x0a, 0x09, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x22, 0x89, 0x01, 0x0a, 0x12, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3d, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x25, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x1f, 0x12, 0x1d, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x34, 0x0a, 0x05, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x52, 0x05, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x22, 0x4c, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x25, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x1f, 0x0a, 0x1d, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x87, 0x01, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x05, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x52, 0x05, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x12, 0x3b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 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, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, 0x6b, 0x22, 0x4f, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x25, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x1f, 0x0a, 0x1d, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x8e, 0x01, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3d, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x25, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x1f, 0x12, 0x1d, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x74, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x06, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x52, 0x06, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xa8, 0x01, 0x0a, 0x13, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x3a, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x22, 0xfa, 0x41, 0x1f, 0x12, 0x1d, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x4c, 0x0a, 0x14, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x34, 0x0a, 0x0a, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x09, 0x72, 0x65, 0x74, 0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x76, 0x0a, 0x14, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x06, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x52, 0x06, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x92, 0x01, 0x0a, 0x13, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x25, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x1f, 0x12, 0x1d, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x40, 0x0a, 0x0b, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 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, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x22, 0xe0, 0x01, 0x0a, 0x14, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x05, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x52, 0x05, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x12, 0x4c, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x34, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x44, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x12, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x03, 0x22, 0x2a, 0x0a, 0x12, 0x53, 0x65, 0x6e, 0x64, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0xf1, 0x01, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4f, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x05, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x48, 0x00, 0x52, 0x05, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x1a, 0x4b, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3a, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x22, 0xfa, 0x41, 0x1f, 0x12, 0x1d, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x32, 0xb4, 0x13, 0x0a, 0x09, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x12, 0x97, 0x01, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x12, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x22, 0x3e, 0xda, 0x41, 0x22, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x22, 0x0e, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x12, 0x79, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x12, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x22, 0x26, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0x83, 0x01, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x12, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x3a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x32, 0x1c, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0x78, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x12, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x26, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x2a, 0x17, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0x7a, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x73, 0x12, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x12, 0x0e, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x12, 0xf6, 0x01, 0x0a, 0x0b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x12, 0x2b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x22, 0x99, 0x01, 0xda, 0x41, 0x1c, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x2c, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2c, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x2e, 0x74, 0x65, 0x78, 0x74, 0xda, 0x41, 0x1d, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x2c, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2c, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x2e, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x54, 0x3a, 0x01, 0x2a, 0x5a, 0x2d, 0x3a, 0x01, 0x2a, 0x22, 0x28, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x2a, 0x2f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x7d, 0x2f, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x22, 0x20, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x12, 0xb1, 0x01, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x12, 0x28, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x22, 0x5b, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4e, 0x5a, 0x2a, 0x12, 0x28, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x2a, 0x2f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x2f, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0x20, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x2f, 0x2a, 0x2f, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0xca, 0x01, 0x0a, 0x0b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x12, 0x2b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x22, 0x6e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x68, 0x3a, 0x05, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x5a, 0x37, 0x3a, 0x05, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x32, 0x2e, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x2a, 0x2f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x2f, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x2f, 0x2a, 0x7d, 0x32, 0x26, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x2f, 0x2a, 0x2f, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0xaf, 0x01, 0x0a, 0x0b, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x12, 0x2b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x5b, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4e, 0x5a, 0x2a, 0x2a, 0x28, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x2a, 0x2f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x2f, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x2f, 0x2a, 0x7d, 0x2a, 0x20, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x2f, 0x2a, 0x2f, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0xc4, 0x01, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x12, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5d, 0xda, 0x41, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4e, 0x5a, 0x2a, 0x12, 0x28, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x2a, 0x2f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x7d, 0x2f, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x12, 0x20, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x12, 0x81, 0x02, 0x0a, 0x0c, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x12, 0x2c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x6c, 0x6f, 0x6e, 0x67, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xa3, 0x01, 0xca, 0x41, 0x2c, 0x0a, 0x14, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xda, 0x41, 0x0c, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x2c, 0x71, 0x75, 0x65, 0x72, 0x79, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x5f, 0x3a, 0x01, 0x2a, 0x5a, 0x31, 0x22, 0x2f, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x2a, 0x2f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x7d, 0x2f, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x3a, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x22, 0x27, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x3a, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0xd3, 0x01, 0x0a, 0x0c, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x12, 0x2c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x64, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x5e, 0x3a, 0x01, 0x2a, 0x5a, 0x32, 0x3a, 0x01, 0x2a, 0x22, 0x2d, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x2a, 0x2f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x7d, 0x2f, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x3a, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x22, 0x25, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x3a, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x30, 0x01, 0x12, 0xce, 0x01, 0x0a, 0x0a, 0x53, 0x65, 0x6e, 0x64, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x12, 0x2b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x64, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x5e, 0x3a, 0x01, 0x2a, 0x5a, 0x32, 0x3a, 0x01, 0x2a, 0x22, 0x2d, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x2a, 0x2f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x7d, 0x2f, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x3a, 0x73, 0x65, 0x6e, 0x64, 0x22, 0x25, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x62, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x3a, 0x73, 0x65, 0x6e, 0x64, 0x28, 0x01, 0x12, 0x65, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x12, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x6c, 0x75, 0x72, 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x1a, 0x11, 0xca, 0x41, 0x0e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x3a, 0x37, 0x34, 0x36, 0x39, 0x42, 0x71, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x50, 0x01, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x67, 0x61, 0x70, 0x69, 0x63, 0x2d, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x65, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xea, 0x02, 0x19, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x3a, 0x3a, 0x53, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_google_showcase_v1beta1_messaging_proto_rawDescOnce sync.Once file_google_showcase_v1beta1_messaging_proto_rawDescData = file_google_showcase_v1beta1_messaging_proto_rawDesc ) func file_google_showcase_v1beta1_messaging_proto_rawDescGZIP() []byte { file_google_showcase_v1beta1_messaging_proto_rawDescOnce.Do(func() { file_google_showcase_v1beta1_messaging_proto_rawDescData = protoimpl.X.CompressGZIP(file_google_showcase_v1beta1_messaging_proto_rawDescData) }) return file_google_showcase_v1beta1_messaging_proto_rawDescData } var file_google_showcase_v1beta1_messaging_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_google_showcase_v1beta1_messaging_proto_msgTypes = make([]protoimpl.MessageInfo, 22) var file_google_showcase_v1beta1_messaging_proto_goTypes = []interface{}{ (StreamBlurbsResponse_Action)(0), // 0: google.showcase.v1beta1.StreamBlurbsResponse.Action (*Room)(nil), // 1: google.showcase.v1beta1.Room (*CreateRoomRequest)(nil), // 2: google.showcase.v1beta1.CreateRoomRequest (*GetRoomRequest)(nil), // 3: google.showcase.v1beta1.GetRoomRequest (*UpdateRoomRequest)(nil), // 4: google.showcase.v1beta1.UpdateRoomRequest (*DeleteRoomRequest)(nil), // 5: google.showcase.v1beta1.DeleteRoomRequest (*ListRoomsRequest)(nil), // 6: google.showcase.v1beta1.ListRoomsRequest (*ListRoomsResponse)(nil), // 7: google.showcase.v1beta1.ListRoomsResponse (*Blurb)(nil), // 8: google.showcase.v1beta1.Blurb (*CreateBlurbRequest)(nil), // 9: google.showcase.v1beta1.CreateBlurbRequest (*GetBlurbRequest)(nil), // 10: google.showcase.v1beta1.GetBlurbRequest (*UpdateBlurbRequest)(nil), // 11: google.showcase.v1beta1.UpdateBlurbRequest (*DeleteBlurbRequest)(nil), // 12: google.showcase.v1beta1.DeleteBlurbRequest (*ListBlurbsRequest)(nil), // 13: google.showcase.v1beta1.ListBlurbsRequest (*ListBlurbsResponse)(nil), // 14: google.showcase.v1beta1.ListBlurbsResponse (*SearchBlurbsRequest)(nil), // 15: google.showcase.v1beta1.SearchBlurbsRequest (*SearchBlurbsMetadata)(nil), // 16: google.showcase.v1beta1.SearchBlurbsMetadata (*SearchBlurbsResponse)(nil), // 17: google.showcase.v1beta1.SearchBlurbsResponse (*StreamBlurbsRequest)(nil), // 18: google.showcase.v1beta1.StreamBlurbsRequest (*StreamBlurbsResponse)(nil), // 19: google.showcase.v1beta1.StreamBlurbsResponse (*SendBlurbsResponse)(nil), // 20: google.showcase.v1beta1.SendBlurbsResponse (*ConnectRequest)(nil), // 21: google.showcase.v1beta1.ConnectRequest (*ConnectRequest_ConnectConfig)(nil), // 22: google.showcase.v1beta1.ConnectRequest.ConnectConfig (*timestamppb.Timestamp)(nil), // 23: google.protobuf.Timestamp (*fieldmaskpb.FieldMask)(nil), // 24: google.protobuf.FieldMask (*errdetails.RetryInfo)(nil), // 25: google.rpc.RetryInfo (*emptypb.Empty)(nil), // 26: google.protobuf.Empty (*longrunningpb.Operation)(nil), // 27: google.longrunning.Operation } var file_google_showcase_v1beta1_messaging_proto_depIdxs = []int32{ 23, // 0: google.showcase.v1beta1.Room.create_time:type_name -> google.protobuf.Timestamp 23, // 1: google.showcase.v1beta1.Room.update_time:type_name -> google.protobuf.Timestamp 1, // 2: google.showcase.v1beta1.CreateRoomRequest.room:type_name -> google.showcase.v1beta1.Room 1, // 3: google.showcase.v1beta1.UpdateRoomRequest.room:type_name -> google.showcase.v1beta1.Room 24, // 4: google.showcase.v1beta1.UpdateRoomRequest.update_mask:type_name -> google.protobuf.FieldMask 1, // 5: google.showcase.v1beta1.ListRoomsResponse.rooms:type_name -> google.showcase.v1beta1.Room 23, // 6: google.showcase.v1beta1.Blurb.create_time:type_name -> google.protobuf.Timestamp 23, // 7: google.showcase.v1beta1.Blurb.update_time:type_name -> google.protobuf.Timestamp 8, // 8: google.showcase.v1beta1.CreateBlurbRequest.blurb:type_name -> google.showcase.v1beta1.Blurb 8, // 9: google.showcase.v1beta1.UpdateBlurbRequest.blurb:type_name -> google.showcase.v1beta1.Blurb 24, // 10: google.showcase.v1beta1.UpdateBlurbRequest.update_mask:type_name -> google.protobuf.FieldMask 8, // 11: google.showcase.v1beta1.ListBlurbsResponse.blurbs:type_name -> google.showcase.v1beta1.Blurb 25, // 12: google.showcase.v1beta1.SearchBlurbsMetadata.retry_info:type_name -> google.rpc.RetryInfo 8, // 13: google.showcase.v1beta1.SearchBlurbsResponse.blurbs:type_name -> google.showcase.v1beta1.Blurb 23, // 14: google.showcase.v1beta1.StreamBlurbsRequest.expire_time:type_name -> google.protobuf.Timestamp 8, // 15: google.showcase.v1beta1.StreamBlurbsResponse.blurb:type_name -> google.showcase.v1beta1.Blurb 0, // 16: google.showcase.v1beta1.StreamBlurbsResponse.action:type_name -> google.showcase.v1beta1.StreamBlurbsResponse.Action 22, // 17: google.showcase.v1beta1.ConnectRequest.config:type_name -> google.showcase.v1beta1.ConnectRequest.ConnectConfig 8, // 18: google.showcase.v1beta1.ConnectRequest.blurb:type_name -> google.showcase.v1beta1.Blurb 2, // 19: google.showcase.v1beta1.Messaging.CreateRoom:input_type -> google.showcase.v1beta1.CreateRoomRequest 3, // 20: google.showcase.v1beta1.Messaging.GetRoom:input_type -> google.showcase.v1beta1.GetRoomRequest 4, // 21: google.showcase.v1beta1.Messaging.UpdateRoom:input_type -> google.showcase.v1beta1.UpdateRoomRequest 5, // 22: google.showcase.v1beta1.Messaging.DeleteRoom:input_type -> google.showcase.v1beta1.DeleteRoomRequest 6, // 23: google.showcase.v1beta1.Messaging.ListRooms:input_type -> google.showcase.v1beta1.ListRoomsRequest 9, // 24: google.showcase.v1beta1.Messaging.CreateBlurb:input_type -> google.showcase.v1beta1.CreateBlurbRequest 10, // 25: google.showcase.v1beta1.Messaging.GetBlurb:input_type -> google.showcase.v1beta1.GetBlurbRequest 11, // 26: google.showcase.v1beta1.Messaging.UpdateBlurb:input_type -> google.showcase.v1beta1.UpdateBlurbRequest 12, // 27: google.showcase.v1beta1.Messaging.DeleteBlurb:input_type -> google.showcase.v1beta1.DeleteBlurbRequest 13, // 28: google.showcase.v1beta1.Messaging.ListBlurbs:input_type -> google.showcase.v1beta1.ListBlurbsRequest 15, // 29: google.showcase.v1beta1.Messaging.SearchBlurbs:input_type -> google.showcase.v1beta1.SearchBlurbsRequest 18, // 30: google.showcase.v1beta1.Messaging.StreamBlurbs:input_type -> google.showcase.v1beta1.StreamBlurbsRequest 9, // 31: google.showcase.v1beta1.Messaging.SendBlurbs:input_type -> google.showcase.v1beta1.CreateBlurbRequest 21, // 32: google.showcase.v1beta1.Messaging.Connect:input_type -> google.showcase.v1beta1.ConnectRequest 1, // 33: google.showcase.v1beta1.Messaging.CreateRoom:output_type -> google.showcase.v1beta1.Room 1, // 34: google.showcase.v1beta1.Messaging.GetRoom:output_type -> google.showcase.v1beta1.Room 1, // 35: google.showcase.v1beta1.Messaging.UpdateRoom:output_type -> google.showcase.v1beta1.Room 26, // 36: google.showcase.v1beta1.Messaging.DeleteRoom:output_type -> google.protobuf.Empty 7, // 37: google.showcase.v1beta1.Messaging.ListRooms:output_type -> google.showcase.v1beta1.ListRoomsResponse 8, // 38: google.showcase.v1beta1.Messaging.CreateBlurb:output_type -> google.showcase.v1beta1.Blurb 8, // 39: google.showcase.v1beta1.Messaging.GetBlurb:output_type -> google.showcase.v1beta1.Blurb 8, // 40: google.showcase.v1beta1.Messaging.UpdateBlurb:output_type -> google.showcase.v1beta1.Blurb 26, // 41: google.showcase.v1beta1.Messaging.DeleteBlurb:output_type -> google.protobuf.Empty 14, // 42: google.showcase.v1beta1.Messaging.ListBlurbs:output_type -> google.showcase.v1beta1.ListBlurbsResponse 27, // 43: google.showcase.v1beta1.Messaging.SearchBlurbs:output_type -> google.longrunning.Operation 19, // 44: google.showcase.v1beta1.Messaging.StreamBlurbs:output_type -> google.showcase.v1beta1.StreamBlurbsResponse 20, // 45: google.showcase.v1beta1.Messaging.SendBlurbs:output_type -> google.showcase.v1beta1.SendBlurbsResponse 19, // 46: google.showcase.v1beta1.Messaging.Connect:output_type -> google.showcase.v1beta1.StreamBlurbsResponse 33, // [33:47] is the sub-list for method output_type 19, // [19:33] is the sub-list for method input_type 19, // [19:19] is the sub-list for extension type_name 19, // [19:19] is the sub-list for extension extendee 0, // [0:19] is the sub-list for field type_name } func init() { file_google_showcase_v1beta1_messaging_proto_init() } func file_google_showcase_v1beta1_messaging_proto_init() { if File_google_showcase_v1beta1_messaging_proto != nil { return } if !protoimpl.UnsafeEnabled { file_google_showcase_v1beta1_messaging_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Room); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_messaging_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateRoomRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_messaging_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetRoomRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_messaging_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UpdateRoomRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_messaging_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DeleteRoomRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_messaging_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListRoomsRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_messaging_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListRoomsResponse); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_messaging_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Blurb); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_messaging_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateBlurbRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_messaging_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetBlurbRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_messaging_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UpdateBlurbRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_messaging_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DeleteBlurbRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_messaging_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListBlurbsRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_messaging_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListBlurbsResponse); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_messaging_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SearchBlurbsRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_messaging_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SearchBlurbsMetadata); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_messaging_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SearchBlurbsResponse); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_messaging_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StreamBlurbsRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_messaging_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StreamBlurbsResponse); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_messaging_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SendBlurbsResponse); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_messaging_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ConnectRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_messaging_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ConnectRequest_ConnectConfig); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } file_google_showcase_v1beta1_messaging_proto_msgTypes[7].OneofWrappers = []interface{}{ (*Blurb_Text)(nil), (*Blurb_Image)(nil), (*Blurb_LegacyRoomId)(nil), (*Blurb_LegacyUserId)(nil), } file_google_showcase_v1beta1_messaging_proto_msgTypes[20].OneofWrappers = []interface{}{ (*ConnectRequest_Config)(nil), (*ConnectRequest_Blurb)(nil), } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_google_showcase_v1beta1_messaging_proto_rawDesc, NumEnums: 1, NumMessages: 22, NumExtensions: 0, NumServices: 1, }, GoTypes: file_google_showcase_v1beta1_messaging_proto_goTypes, DependencyIndexes: file_google_showcase_v1beta1_messaging_proto_depIdxs, EnumInfos: file_google_showcase_v1beta1_messaging_proto_enumTypes, MessageInfos: file_google_showcase_v1beta1_messaging_proto_msgTypes, }.Build() File_google_showcase_v1beta1_messaging_proto = out.File file_google_showcase_v1beta1_messaging_proto_rawDesc = nil file_google_showcase_v1beta1_messaging_proto_goTypes = nil file_google_showcase_v1beta1_messaging_proto_depIdxs = nil } // Reference imports to suppress errors if they are not otherwise used. var _ context.Context var _ grpc.ClientConnInterface // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. const _ = grpc.SupportPackageIsVersion6 // MessagingClient is the client API for Messaging service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type MessagingClient interface { // Creates a room. CreateRoom(ctx context.Context, in *CreateRoomRequest, opts ...grpc.CallOption) (*Room, error) // Retrieves the Room with the given resource name. GetRoom(ctx context.Context, in *GetRoomRequest, opts ...grpc.CallOption) (*Room, error) // Updates a room. UpdateRoom(ctx context.Context, in *UpdateRoomRequest, opts ...grpc.CallOption) (*Room, error) // Deletes a room and all of its blurbs. DeleteRoom(ctx context.Context, in *DeleteRoomRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) // Lists all chat rooms. ListRooms(ctx context.Context, in *ListRoomsRequest, opts ...grpc.CallOption) (*ListRoomsResponse, error) // Creates a blurb. If the parent is a room, the blurb is understood to be a // message in that room. If the parent is a profile, the blurb is understood // to be a post on the profile. CreateBlurb(ctx context.Context, in *CreateBlurbRequest, opts ...grpc.CallOption) (*Blurb, error) // Retrieves the Blurb with the given resource name. GetBlurb(ctx context.Context, in *GetBlurbRequest, opts ...grpc.CallOption) (*Blurb, error) // Updates a blurb. UpdateBlurb(ctx context.Context, in *UpdateBlurbRequest, opts ...grpc.CallOption) (*Blurb, error) // Deletes a blurb. DeleteBlurb(ctx context.Context, in *DeleteBlurbRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) // Lists blurbs for a specific chat room or user profile depending on the // parent resource name. ListBlurbs(ctx context.Context, in *ListBlurbsRequest, opts ...grpc.CallOption) (*ListBlurbsResponse, error) // This method searches through all blurbs across all rooms and profiles // for blurbs containing to words found in the query. Only posts that // contain an exact match of a queried word will be returned. SearchBlurbs(ctx context.Context, in *SearchBlurbsRequest, opts ...grpc.CallOption) (*longrunningpb.Operation, error) // This returns a stream that emits the blurbs that are created for a // particular chat room or user profile. StreamBlurbs(ctx context.Context, in *StreamBlurbsRequest, opts ...grpc.CallOption) (Messaging_StreamBlurbsClient, error) // This is a stream to create multiple blurbs. If an invalid blurb is // requested to be created, the stream will close with an error. SendBlurbs(ctx context.Context, opts ...grpc.CallOption) (Messaging_SendBlurbsClient, error) // This method starts a bidirectional stream that receives all blurbs that // are being created after the stream has started and sends requests to create // blurbs. If an invalid blurb is requested to be created, the stream will // close with an error. Connect(ctx context.Context, opts ...grpc.CallOption) (Messaging_ConnectClient, error) } type messagingClient struct { cc grpc.ClientConnInterface } func NewMessagingClient(cc grpc.ClientConnInterface) MessagingClient { return &messagingClient{cc} } func (c *messagingClient) CreateRoom(ctx context.Context, in *CreateRoomRequest, opts ...grpc.CallOption) (*Room, error) { out := new(Room) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Messaging/CreateRoom", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *messagingClient) GetRoom(ctx context.Context, in *GetRoomRequest, opts ...grpc.CallOption) (*Room, error) { out := new(Room) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Messaging/GetRoom", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *messagingClient) UpdateRoom(ctx context.Context, in *UpdateRoomRequest, opts ...grpc.CallOption) (*Room, error) { out := new(Room) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Messaging/UpdateRoom", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *messagingClient) DeleteRoom(ctx context.Context, in *DeleteRoomRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Messaging/DeleteRoom", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *messagingClient) ListRooms(ctx context.Context, in *ListRoomsRequest, opts ...grpc.CallOption) (*ListRoomsResponse, error) { out := new(ListRoomsResponse) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Messaging/ListRooms", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *messagingClient) CreateBlurb(ctx context.Context, in *CreateBlurbRequest, opts ...grpc.CallOption) (*Blurb, error) { out := new(Blurb) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Messaging/CreateBlurb", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *messagingClient) GetBlurb(ctx context.Context, in *GetBlurbRequest, opts ...grpc.CallOption) (*Blurb, error) { out := new(Blurb) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Messaging/GetBlurb", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *messagingClient) UpdateBlurb(ctx context.Context, in *UpdateBlurbRequest, opts ...grpc.CallOption) (*Blurb, error) { out := new(Blurb) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Messaging/UpdateBlurb", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *messagingClient) DeleteBlurb(ctx context.Context, in *DeleteBlurbRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Messaging/DeleteBlurb", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *messagingClient) ListBlurbs(ctx context.Context, in *ListBlurbsRequest, opts ...grpc.CallOption) (*ListBlurbsResponse, error) { out := new(ListBlurbsResponse) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Messaging/ListBlurbs", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *messagingClient) SearchBlurbs(ctx context.Context, in *SearchBlurbsRequest, opts ...grpc.CallOption) (*longrunningpb.Operation, error) { out := new(longrunningpb.Operation) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Messaging/SearchBlurbs", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *messagingClient) StreamBlurbs(ctx context.Context, in *StreamBlurbsRequest, opts ...grpc.CallOption) (Messaging_StreamBlurbsClient, error) { stream, err := c.cc.NewStream(ctx, &_Messaging_serviceDesc.Streams[0], "/google.showcase.v1beta1.Messaging/StreamBlurbs", opts...) if err != nil { return nil, err } x := &messagingStreamBlurbsClient{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 Messaging_StreamBlurbsClient interface { Recv() (*StreamBlurbsResponse, error) grpc.ClientStream } type messagingStreamBlurbsClient struct { grpc.ClientStream } func (x *messagingStreamBlurbsClient) Recv() (*StreamBlurbsResponse, error) { m := new(StreamBlurbsResponse) if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err } return m, nil } func (c *messagingClient) SendBlurbs(ctx context.Context, opts ...grpc.CallOption) (Messaging_SendBlurbsClient, error) { stream, err := c.cc.NewStream(ctx, &_Messaging_serviceDesc.Streams[1], "/google.showcase.v1beta1.Messaging/SendBlurbs", opts...) if err != nil { return nil, err } x := &messagingSendBlurbsClient{stream} return x, nil } type Messaging_SendBlurbsClient interface { Send(*CreateBlurbRequest) error CloseAndRecv() (*SendBlurbsResponse, error) grpc.ClientStream } type messagingSendBlurbsClient struct { grpc.ClientStream } func (x *messagingSendBlurbsClient) Send(m *CreateBlurbRequest) error { return x.ClientStream.SendMsg(m) } func (x *messagingSendBlurbsClient) CloseAndRecv() (*SendBlurbsResponse, error) { if err := x.ClientStream.CloseSend(); err != nil { return nil, err } m := new(SendBlurbsResponse) if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err } return m, nil } func (c *messagingClient) Connect(ctx context.Context, opts ...grpc.CallOption) (Messaging_ConnectClient, error) { stream, err := c.cc.NewStream(ctx, &_Messaging_serviceDesc.Streams[2], "/google.showcase.v1beta1.Messaging/Connect", opts...) if err != nil { return nil, err } x := &messagingConnectClient{stream} return x, nil } type Messaging_ConnectClient interface { Send(*ConnectRequest) error Recv() (*StreamBlurbsResponse, error) grpc.ClientStream } type messagingConnectClient struct { grpc.ClientStream } func (x *messagingConnectClient) Send(m *ConnectRequest) error { return x.ClientStream.SendMsg(m) } func (x *messagingConnectClient) Recv() (*StreamBlurbsResponse, error) { m := new(StreamBlurbsResponse) if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err } return m, nil } // MessagingServer is the server API for Messaging service. type MessagingServer interface { // Creates a room. CreateRoom(context.Context, *CreateRoomRequest) (*Room, error) // Retrieves the Room with the given resource name. GetRoom(context.Context, *GetRoomRequest) (*Room, error) // Updates a room. UpdateRoom(context.Context, *UpdateRoomRequest) (*Room, error) // Deletes a room and all of its blurbs. DeleteRoom(context.Context, *DeleteRoomRequest) (*emptypb.Empty, error) // Lists all chat rooms. ListRooms(context.Context, *ListRoomsRequest) (*ListRoomsResponse, error) // Creates a blurb. If the parent is a room, the blurb is understood to be a // message in that room. If the parent is a profile, the blurb is understood // to be a post on the profile. CreateBlurb(context.Context, *CreateBlurbRequest) (*Blurb, error) // Retrieves the Blurb with the given resource name. GetBlurb(context.Context, *GetBlurbRequest) (*Blurb, error) // Updates a blurb. UpdateBlurb(context.Context, *UpdateBlurbRequest) (*Blurb, error) // Deletes a blurb. DeleteBlurb(context.Context, *DeleteBlurbRequest) (*emptypb.Empty, error) // Lists blurbs for a specific chat room or user profile depending on the // parent resource name. ListBlurbs(context.Context, *ListBlurbsRequest) (*ListBlurbsResponse, error) // This method searches through all blurbs across all rooms and profiles // for blurbs containing to words found in the query. Only posts that // contain an exact match of a queried word will be returned. SearchBlurbs(context.Context, *SearchBlurbsRequest) (*longrunningpb.Operation, error) // This returns a stream that emits the blurbs that are created for a // particular chat room or user profile. StreamBlurbs(*StreamBlurbsRequest, Messaging_StreamBlurbsServer) error // This is a stream to create multiple blurbs. If an invalid blurb is // requested to be created, the stream will close with an error. SendBlurbs(Messaging_SendBlurbsServer) error // This method starts a bidirectional stream that receives all blurbs that // are being created after the stream has started and sends requests to create // blurbs. If an invalid blurb is requested to be created, the stream will // close with an error. Connect(Messaging_ConnectServer) error } // UnimplementedMessagingServer can be embedded to have forward compatible implementations. type UnimplementedMessagingServer struct { } func (*UnimplementedMessagingServer) CreateRoom(context.Context, *CreateRoomRequest) (*Room, error) { return nil, status.Errorf(codes.Unimplemented, "method CreateRoom not implemented") } func (*UnimplementedMessagingServer) GetRoom(context.Context, *GetRoomRequest) (*Room, error) { return nil, status.Errorf(codes.Unimplemented, "method GetRoom not implemented") } func (*UnimplementedMessagingServer) UpdateRoom(context.Context, *UpdateRoomRequest) (*Room, error) { return nil, status.Errorf(codes.Unimplemented, "method UpdateRoom not implemented") } func (*UnimplementedMessagingServer) DeleteRoom(context.Context, *DeleteRoomRequest) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method DeleteRoom not implemented") } func (*UnimplementedMessagingServer) ListRooms(context.Context, *ListRoomsRequest) (*ListRoomsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListRooms not implemented") } func (*UnimplementedMessagingServer) CreateBlurb(context.Context, *CreateBlurbRequest) (*Blurb, error) { return nil, status.Errorf(codes.Unimplemented, "method CreateBlurb not implemented") } func (*UnimplementedMessagingServer) GetBlurb(context.Context, *GetBlurbRequest) (*Blurb, error) { return nil, status.Errorf(codes.Unimplemented, "method GetBlurb not implemented") } func (*UnimplementedMessagingServer) UpdateBlurb(context.Context, *UpdateBlurbRequest) (*Blurb, error) { return nil, status.Errorf(codes.Unimplemented, "method UpdateBlurb not implemented") } func (*UnimplementedMessagingServer) DeleteBlurb(context.Context, *DeleteBlurbRequest) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method DeleteBlurb not implemented") } func (*UnimplementedMessagingServer) ListBlurbs(context.Context, *ListBlurbsRequest) (*ListBlurbsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListBlurbs not implemented") } func (*UnimplementedMessagingServer) SearchBlurbs(context.Context, *SearchBlurbsRequest) (*longrunningpb.Operation, error) { return nil, status.Errorf(codes.Unimplemented, "method SearchBlurbs not implemented") } func (*UnimplementedMessagingServer) StreamBlurbs(*StreamBlurbsRequest, Messaging_StreamBlurbsServer) error { return status.Errorf(codes.Unimplemented, "method StreamBlurbs not implemented") } func (*UnimplementedMessagingServer) SendBlurbs(Messaging_SendBlurbsServer) error { return status.Errorf(codes.Unimplemented, "method SendBlurbs not implemented") } func (*UnimplementedMessagingServer) Connect(Messaging_ConnectServer) error { return status.Errorf(codes.Unimplemented, "method Connect not implemented") } func RegisterMessagingServer(s *grpc.Server, srv MessagingServer) { s.RegisterService(&_Messaging_serviceDesc, srv) } func _Messaging_CreateRoom_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(CreateRoomRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(MessagingServer).CreateRoom(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Messaging/CreateRoom", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(MessagingServer).CreateRoom(ctx, req.(*CreateRoomRequest)) } return interceptor(ctx, in, info, handler) } func _Messaging_GetRoom_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetRoomRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(MessagingServer).GetRoom(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Messaging/GetRoom", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(MessagingServer).GetRoom(ctx, req.(*GetRoomRequest)) } return interceptor(ctx, in, info, handler) } func _Messaging_UpdateRoom_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(UpdateRoomRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(MessagingServer).UpdateRoom(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Messaging/UpdateRoom", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(MessagingServer).UpdateRoom(ctx, req.(*UpdateRoomRequest)) } return interceptor(ctx, in, info, handler) } func _Messaging_DeleteRoom_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(DeleteRoomRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(MessagingServer).DeleteRoom(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Messaging/DeleteRoom", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(MessagingServer).DeleteRoom(ctx, req.(*DeleteRoomRequest)) } return interceptor(ctx, in, info, handler) } func _Messaging_ListRooms_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ListRoomsRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(MessagingServer).ListRooms(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Messaging/ListRooms", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(MessagingServer).ListRooms(ctx, req.(*ListRoomsRequest)) } return interceptor(ctx, in, info, handler) } func _Messaging_CreateBlurb_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(CreateBlurbRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(MessagingServer).CreateBlurb(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Messaging/CreateBlurb", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(MessagingServer).CreateBlurb(ctx, req.(*CreateBlurbRequest)) } return interceptor(ctx, in, info, handler) } func _Messaging_GetBlurb_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetBlurbRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(MessagingServer).GetBlurb(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Messaging/GetBlurb", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(MessagingServer).GetBlurb(ctx, req.(*GetBlurbRequest)) } return interceptor(ctx, in, info, handler) } func _Messaging_UpdateBlurb_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(UpdateBlurbRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(MessagingServer).UpdateBlurb(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Messaging/UpdateBlurb", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(MessagingServer).UpdateBlurb(ctx, req.(*UpdateBlurbRequest)) } return interceptor(ctx, in, info, handler) } func _Messaging_DeleteBlurb_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(DeleteBlurbRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(MessagingServer).DeleteBlurb(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Messaging/DeleteBlurb", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(MessagingServer).DeleteBlurb(ctx, req.(*DeleteBlurbRequest)) } return interceptor(ctx, in, info, handler) } func _Messaging_ListBlurbs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ListBlurbsRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(MessagingServer).ListBlurbs(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Messaging/ListBlurbs", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(MessagingServer).ListBlurbs(ctx, req.(*ListBlurbsRequest)) } return interceptor(ctx, in, info, handler) } func _Messaging_SearchBlurbs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(SearchBlurbsRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(MessagingServer).SearchBlurbs(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Messaging/SearchBlurbs", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(MessagingServer).SearchBlurbs(ctx, req.(*SearchBlurbsRequest)) } return interceptor(ctx, in, info, handler) } func _Messaging_StreamBlurbs_Handler(srv interface{}, stream grpc.ServerStream) error { m := new(StreamBlurbsRequest) if err := stream.RecvMsg(m); err != nil { return err } return srv.(MessagingServer).StreamBlurbs(m, &messagingStreamBlurbsServer{stream}) } type Messaging_StreamBlurbsServer interface { Send(*StreamBlurbsResponse) error grpc.ServerStream } type messagingStreamBlurbsServer struct { grpc.ServerStream } func (x *messagingStreamBlurbsServer) Send(m *StreamBlurbsResponse) error { return x.ServerStream.SendMsg(m) } func _Messaging_SendBlurbs_Handler(srv interface{}, stream grpc.ServerStream) error { return srv.(MessagingServer).SendBlurbs(&messagingSendBlurbsServer{stream}) } type Messaging_SendBlurbsServer interface { SendAndClose(*SendBlurbsResponse) error Recv() (*CreateBlurbRequest, error) grpc.ServerStream } type messagingSendBlurbsServer struct { grpc.ServerStream } func (x *messagingSendBlurbsServer) SendAndClose(m *SendBlurbsResponse) error { return x.ServerStream.SendMsg(m) } func (x *messagingSendBlurbsServer) Recv() (*CreateBlurbRequest, error) { m := new(CreateBlurbRequest) if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err } return m, nil } func _Messaging_Connect_Handler(srv interface{}, stream grpc.ServerStream) error { return srv.(MessagingServer).Connect(&messagingConnectServer{stream}) } type Messaging_ConnectServer interface { Send(*StreamBlurbsResponse) error Recv() (*ConnectRequest, error) grpc.ServerStream } type messagingConnectServer struct { grpc.ServerStream } func (x *messagingConnectServer) Send(m *StreamBlurbsResponse) error { return x.ServerStream.SendMsg(m) } func (x *messagingConnectServer) Recv() (*ConnectRequest, error) { m := new(ConnectRequest) if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err } return m, nil } var _Messaging_serviceDesc = grpc.ServiceDesc{ ServiceName: "google.showcase.v1beta1.Messaging", HandlerType: (*MessagingServer)(nil), Methods: []grpc.MethodDesc{ { MethodName: "CreateRoom", Handler: _Messaging_CreateRoom_Handler, }, { MethodName: "GetRoom", Handler: _Messaging_GetRoom_Handler, }, { MethodName: "UpdateRoom", Handler: _Messaging_UpdateRoom_Handler, }, { MethodName: "DeleteRoom", Handler: _Messaging_DeleteRoom_Handler, }, { MethodName: "ListRooms", Handler: _Messaging_ListRooms_Handler, }, { MethodName: "CreateBlurb", Handler: _Messaging_CreateBlurb_Handler, }, { MethodName: "GetBlurb", Handler: _Messaging_GetBlurb_Handler, }, { MethodName: "UpdateBlurb", Handler: _Messaging_UpdateBlurb_Handler, }, { MethodName: "DeleteBlurb", Handler: _Messaging_DeleteBlurb_Handler, }, { MethodName: "ListBlurbs", Handler: _Messaging_ListBlurbs_Handler, }, { MethodName: "SearchBlurbs", Handler: _Messaging_SearchBlurbs_Handler, }, }, Streams: []grpc.StreamDesc{ { StreamName: "StreamBlurbs", Handler: _Messaging_StreamBlurbs_Handler, ServerStreams: true, }, { StreamName: "SendBlurbs", Handler: _Messaging_SendBlurbs_Handler, ClientStreams: true, }, { StreamName: "Connect", Handler: _Messaging_Connect_Handler, ServerStreams: true, ClientStreams: true, }, }, Metadata: "google/showcase/v1beta1/messaging.proto", } ================================================ FILE: server/genproto/rest_error.pb.go ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.33.0 // protoc v3.20.3 // source: google/showcase/v1beta1/rest_error.proto package genproto import ( code "google.golang.org/genproto/googleapis/rpc/code" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" anypb "google.golang.org/protobuf/types/known/anypb" 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) ) // HTTP/JSON error representation as defined in // https://google.aip.dev/193#http11json-representation, type RestError struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Error *RestError_Status `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` } func (x *RestError) Reset() { *x = RestError{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_rest_error_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *RestError) String() string { return protoimpl.X.MessageStringOf(x) } func (*RestError) ProtoMessage() {} func (x *RestError) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_rest_error_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 RestError.ProtoReflect.Descriptor instead. func (*RestError) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_rest_error_proto_rawDescGZIP(), []int{0} } func (x *RestError) GetError() *RestError_Status { if x != nil { return x.Error } return nil } type RestError_Status struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The HTTP status code that corresponds to `google.rpc.Status.code`. Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` // This corresponds to `google.rpc.Status.message`. Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` // This is the enum version for `google.rpc.Status.code`. Status code.Code `protobuf:"varint,4,opt,name=status,proto3,enum=google.rpc.Code" json:"status,omitempty"` // This corresponds to `google.rpc.Status.details`. Details []*anypb.Any `protobuf:"bytes,5,rep,name=details,proto3" json:"details,omitempty"` } func (x *RestError_Status) Reset() { *x = RestError_Status{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_rest_error_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *RestError_Status) String() string { return protoimpl.X.MessageStringOf(x) } func (*RestError_Status) ProtoMessage() {} func (x *RestError_Status) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_rest_error_proto_msgTypes[1] 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 RestError_Status.ProtoReflect.Descriptor instead. func (*RestError_Status) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_rest_error_proto_rawDescGZIP(), []int{0, 0} } func (x *RestError_Status) GetCode() int32 { if x != nil { return x.Code } return 0 } func (x *RestError_Status) GetMessage() string { if x != nil { return x.Message } return "" } func (x *RestError_Status) GetStatus() code.Code { if x != nil { return x.Status } return code.Code(0) } func (x *RestError_Status) GetDetails() []*anypb.Any { if x != nil { return x.Details } return nil } var File_google_showcase_v1beta1_rest_error_proto protoreflect.FileDescriptor var file_google_showcase_v1beta1_rest_error_proto_rawDesc = []byte{ 0x0a, 0x28, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x72, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x17, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 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, 0x15, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xdf, 0x01, 0x0a, 0x09, 0x52, 0x65, 0x73, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x3f, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x1a, 0x90, 0x01, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x28, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x10, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2e, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x03, 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, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x42, 0x71, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x50, 0x01, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x67, 0x61, 0x70, 0x69, 0x63, 0x2d, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x65, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xea, 0x02, 0x19, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x3a, 0x3a, 0x53, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_google_showcase_v1beta1_rest_error_proto_rawDescOnce sync.Once file_google_showcase_v1beta1_rest_error_proto_rawDescData = file_google_showcase_v1beta1_rest_error_proto_rawDesc ) func file_google_showcase_v1beta1_rest_error_proto_rawDescGZIP() []byte { file_google_showcase_v1beta1_rest_error_proto_rawDescOnce.Do(func() { file_google_showcase_v1beta1_rest_error_proto_rawDescData = protoimpl.X.CompressGZIP(file_google_showcase_v1beta1_rest_error_proto_rawDescData) }) return file_google_showcase_v1beta1_rest_error_proto_rawDescData } var file_google_showcase_v1beta1_rest_error_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_google_showcase_v1beta1_rest_error_proto_goTypes = []interface{}{ (*RestError)(nil), // 0: google.showcase.v1beta1.RestError (*RestError_Status)(nil), // 1: google.showcase.v1beta1.RestError.Status (code.Code)(0), // 2: google.rpc.Code (*anypb.Any)(nil), // 3: google.protobuf.Any } var file_google_showcase_v1beta1_rest_error_proto_depIdxs = []int32{ 1, // 0: google.showcase.v1beta1.RestError.error:type_name -> google.showcase.v1beta1.RestError.Status 2, // 1: google.showcase.v1beta1.RestError.Status.status:type_name -> google.rpc.Code 3, // 2: google.showcase.v1beta1.RestError.Status.details:type_name -> google.protobuf.Any 3, // [3:3] is the sub-list for method output_type 3, // [3:3] is the sub-list for method input_type 3, // [3:3] is the sub-list for extension type_name 3, // [3:3] is the sub-list for extension extendee 0, // [0:3] is the sub-list for field type_name } func init() { file_google_showcase_v1beta1_rest_error_proto_init() } func file_google_showcase_v1beta1_rest_error_proto_init() { if File_google_showcase_v1beta1_rest_error_proto != nil { return } if !protoimpl.UnsafeEnabled { file_google_showcase_v1beta1_rest_error_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RestError); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_rest_error_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RestError_Status); 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_google_showcase_v1beta1_rest_error_proto_rawDesc, NumEnums: 0, NumMessages: 2, NumExtensions: 0, NumServices: 0, }, GoTypes: file_google_showcase_v1beta1_rest_error_proto_goTypes, DependencyIndexes: file_google_showcase_v1beta1_rest_error_proto_depIdxs, MessageInfos: file_google_showcase_v1beta1_rest_error_proto_msgTypes, }.Build() File_google_showcase_v1beta1_rest_error_proto = out.File file_google_showcase_v1beta1_rest_error_proto_rawDesc = nil file_google_showcase_v1beta1_rest_error_proto_goTypes = nil file_google_showcase_v1beta1_rest_error_proto_depIdxs = nil } ================================================ FILE: server/genproto/sequence.pb.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.33.0 // protoc v3.20.3 // source: google/showcase/v1beta1/sequence.proto package genproto import ( context "context" _ "google.golang.org/genproto/googleapis/api/annotations" status "google.golang.org/genproto/googleapis/rpc/status" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status1 "google.golang.org/grpc/status" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" durationpb "google.golang.org/protobuf/types/known/durationpb" emptypb "google.golang.org/protobuf/types/known/emptypb" timestamppb "google.golang.org/protobuf/types/known/timestamppb" 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) ) // A sequence of responses to be returned in order for each unary call attempt type Sequence struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // Sequence of responses to return in order for each attempt. If empty, the // default response is an immediate OK. Responses []*Sequence_Response `protobuf:"bytes,2,rep,name=responses,proto3" json:"responses,omitempty"` } func (x *Sequence) Reset() { *x = Sequence{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Sequence) String() string { return protoimpl.X.MessageStringOf(x) } func (*Sequence) ProtoMessage() {} func (x *Sequence) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_sequence_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 Sequence.ProtoReflect.Descriptor instead. func (*Sequence) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_sequence_proto_rawDescGZIP(), []int{0} } func (x *Sequence) GetName() string { if x != nil { return x.Name } return "" } func (x *Sequence) GetResponses() []*Sequence_Response { if x != nil { return x.Responses } return nil } // A sequence of responses to be returned in order at the delay specified // as part of the server streaming call type StreamingSequence struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The name of the streaming sequence. Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // The content that the stream will send // this was specified when the sequence was created Content string `protobuf:"bytes,2,opt,name=content,proto3" json:"content,omitempty"` // Sequence of responses to return in order for each attempt. If empty, the // default response is an immediate OK. Responses []*StreamingSequence_Response `protobuf:"bytes,3,rep,name=responses,proto3" json:"responses,omitempty"` } func (x *StreamingSequence) Reset() { *x = StreamingSequence{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *StreamingSequence) String() string { return protoimpl.X.MessageStringOf(x) } func (*StreamingSequence) ProtoMessage() {} func (x *StreamingSequence) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[1] 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 StreamingSequence.ProtoReflect.Descriptor instead. func (*StreamingSequence) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_sequence_proto_rawDescGZIP(), []int{1} } func (x *StreamingSequence) GetName() string { if x != nil { return x.Name } return "" } func (x *StreamingSequence) GetContent() string { if x != nil { return x.Content } return "" } func (x *StreamingSequence) GetResponses() []*StreamingSequence_Response { if x != nil { return x.Responses } return nil } // A report of the results of a streaming sequence. type StreamingSequenceReport struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // The set of RPC attempts received by the server for a Sequence. Attempts []*StreamingSequenceReport_Attempt `protobuf:"bytes,2,rep,name=attempts,proto3" json:"attempts,omitempty"` } func (x *StreamingSequenceReport) Reset() { *x = StreamingSequenceReport{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *StreamingSequenceReport) String() string { return protoimpl.X.MessageStringOf(x) } func (*StreamingSequenceReport) ProtoMessage() {} func (x *StreamingSequenceReport) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[2] 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 StreamingSequenceReport.ProtoReflect.Descriptor instead. func (*StreamingSequenceReport) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_sequence_proto_rawDescGZIP(), []int{2} } func (x *StreamingSequenceReport) GetName() string { if x != nil { return x.Name } return "" } func (x *StreamingSequenceReport) GetAttempts() []*StreamingSequenceReport_Attempt { if x != nil { return x.Attempts } return nil } // A report of the results of a sequence of unary responses type SequenceReport struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // The set of RPC attempts received by the server for a Sequence. Attempts []*SequenceReport_Attempt `protobuf:"bytes,2,rep,name=attempts,proto3" json:"attempts,omitempty"` } func (x *SequenceReport) Reset() { *x = SequenceReport{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *SequenceReport) String() string { return protoimpl.X.MessageStringOf(x) } func (*SequenceReport) ProtoMessage() {} func (x *SequenceReport) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[3] 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 SequenceReport.ProtoReflect.Descriptor instead. func (*SequenceReport) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_sequence_proto_rawDescGZIP(), []int{3} } func (x *SequenceReport) GetName() string { if x != nil { return x.Name } return "" } func (x *SequenceReport) GetAttempts() []*SequenceReport_Attempt { if x != nil { return x.Attempts } return nil } // Request message for creating a sequence of unary calls type CreateSequenceRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Sequence *Sequence `protobuf:"bytes,1,opt,name=sequence,proto3" json:"sequence,omitempty"` } func (x *CreateSequenceRequest) Reset() { *x = CreateSequenceRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *CreateSequenceRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*CreateSequenceRequest) ProtoMessage() {} func (x *CreateSequenceRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[4] 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 CreateSequenceRequest.ProtoReflect.Descriptor instead. func (*CreateSequenceRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_sequence_proto_rawDescGZIP(), []int{4} } func (x *CreateSequenceRequest) GetSequence() *Sequence { if x != nil { return x.Sequence } return nil } // Request message for the sequences of responses to be sent in a server streaming call type CreateStreamingSequenceRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields StreamingSequence *StreamingSequence `protobuf:"bytes,1,opt,name=streaming_sequence,json=streamingSequence,proto3" json:"streaming_sequence,omitempty"` } func (x *CreateStreamingSequenceRequest) Reset() { *x = CreateStreamingSequenceRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *CreateStreamingSequenceRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*CreateStreamingSequenceRequest) ProtoMessage() {} func (x *CreateStreamingSequenceRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[5] 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 CreateStreamingSequenceRequest.ProtoReflect.Descriptor instead. func (*CreateStreamingSequenceRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_sequence_proto_rawDescGZIP(), []int{5} } func (x *CreateStreamingSequenceRequest) GetStreamingSequence() *StreamingSequence { if x != nil { return x.StreamingSequence } return nil } // Request message for the unary AttemptSequence method type AttemptSequenceRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` } func (x *AttemptSequenceRequest) Reset() { *x = AttemptSequenceRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AttemptSequenceRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*AttemptSequenceRequest) ProtoMessage() {} func (x *AttemptSequenceRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[6] 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 AttemptSequenceRequest.ProtoReflect.Descriptor instead. func (*AttemptSequenceRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_sequence_proto_rawDescGZIP(), []int{6} } func (x *AttemptSequenceRequest) GetName() string { if x != nil { return x.Name } return "" } // Request message for the AttemptStreamingSequence method. type AttemptStreamingSequenceRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // used to send the index of the last failed message // in the string "content" of an AttemptStreamingSequenceResponse // needed for stream resumption logic testing LastFailIndex int32 `protobuf:"varint,2,opt,name=last_fail_index,json=lastFailIndex,proto3" json:"last_fail_index,omitempty"` } func (x *AttemptStreamingSequenceRequest) Reset() { *x = AttemptStreamingSequenceRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AttemptStreamingSequenceRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*AttemptStreamingSequenceRequest) ProtoMessage() {} func (x *AttemptStreamingSequenceRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[7] 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 AttemptStreamingSequenceRequest.ProtoReflect.Descriptor instead. func (*AttemptStreamingSequenceRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_sequence_proto_rawDescGZIP(), []int{7} } func (x *AttemptStreamingSequenceRequest) GetName() string { if x != nil { return x.Name } return "" } func (x *AttemptStreamingSequenceRequest) GetLastFailIndex() int32 { if x != nil { return x.LastFailIndex } return 0 } // The response message for the AttemptStreamingSequence method. type AttemptStreamingSequenceResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The content specified in the request. Content string `protobuf:"bytes,1,opt,name=content,proto3" json:"content,omitempty"` } func (x *AttemptStreamingSequenceResponse) Reset() { *x = AttemptStreamingSequenceResponse{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AttemptStreamingSequenceResponse) String() string { return protoimpl.X.MessageStringOf(x) } func (*AttemptStreamingSequenceResponse) ProtoMessage() {} func (x *AttemptStreamingSequenceResponse) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[8] 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 AttemptStreamingSequenceResponse.ProtoReflect.Descriptor instead. func (*AttemptStreamingSequenceResponse) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_sequence_proto_rawDescGZIP(), []int{8} } func (x *AttemptStreamingSequenceResponse) GetContent() string { if x != nil { return x.Content } return "" } type GetSequenceReportRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` } func (x *GetSequenceReportRequest) Reset() { *x = GetSequenceReportRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *GetSequenceReportRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*GetSequenceReportRequest) ProtoMessage() {} func (x *GetSequenceReportRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[9] 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 GetSequenceReportRequest.ProtoReflect.Descriptor instead. func (*GetSequenceReportRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_sequence_proto_rawDescGZIP(), []int{9} } func (x *GetSequenceReportRequest) GetName() string { if x != nil { return x.Name } return "" } type GetStreamingSequenceReportRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` } func (x *GetStreamingSequenceReportRequest) Reset() { *x = GetStreamingSequenceReportRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *GetStreamingSequenceReportRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*GetStreamingSequenceReportRequest) ProtoMessage() {} func (x *GetStreamingSequenceReportRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[10] 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 GetStreamingSequenceReportRequest.ProtoReflect.Descriptor instead. func (*GetStreamingSequenceReportRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_sequence_proto_rawDescGZIP(), []int{10} } func (x *GetStreamingSequenceReportRequest) GetName() string { if x != nil { return x.Name } return "" } // A server response to an RPC Attempt in a sequence. type Sequence_Response struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The status to return for an individual attempt. Status *status.Status `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"` // The amount of time to delay sending the response. Delay *durationpb.Duration `protobuf:"bytes,2,opt,name=delay,proto3" json:"delay,omitempty"` } func (x *Sequence_Response) Reset() { *x = Sequence_Response{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Sequence_Response) String() string { return protoimpl.X.MessageStringOf(x) } func (*Sequence_Response) ProtoMessage() {} func (x *Sequence_Response) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[11] 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 Sequence_Response.ProtoReflect.Descriptor instead. func (*Sequence_Response) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_sequence_proto_rawDescGZIP(), []int{0, 0} } func (x *Sequence_Response) GetStatus() *status.Status { if x != nil { return x.Status } return nil } func (x *Sequence_Response) GetDelay() *durationpb.Duration { if x != nil { return x.Delay } return nil } // A server response to an RPC Attempt in a sequence. type StreamingSequence_Response struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The status to return for an individual attempt. Status *status.Status `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"` // The amount of time to delay sending the response. Delay *durationpb.Duration `protobuf:"bytes,2,opt,name=delay,proto3" json:"delay,omitempty"` // The index that the status should be sent at ResponseIndex int32 `protobuf:"varint,3,opt,name=response_index,json=responseIndex,proto3" json:"response_index,omitempty"` } func (x *StreamingSequence_Response) Reset() { *x = StreamingSequence_Response{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *StreamingSequence_Response) String() string { return protoimpl.X.MessageStringOf(x) } func (*StreamingSequence_Response) ProtoMessage() {} func (x *StreamingSequence_Response) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[12] 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 StreamingSequence_Response.ProtoReflect.Descriptor instead. func (*StreamingSequence_Response) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_sequence_proto_rawDescGZIP(), []int{1, 0} } func (x *StreamingSequence_Response) GetStatus() *status.Status { if x != nil { return x.Status } return nil } func (x *StreamingSequence_Response) GetDelay() *durationpb.Duration { if x != nil { return x.Delay } return nil } func (x *StreamingSequence_Response) GetResponseIndex() int32 { if x != nil { return x.ResponseIndex } return 0 } // Contains metrics on individual RPC Attempts in a sequence. type StreamingSequenceReport_Attempt struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The attempt number - starting at 0. AttemptNumber int32 `protobuf:"varint,1,opt,name=attempt_number,json=attemptNumber,proto3" json:"attempt_number,omitempty"` // The deadline dictated by the attempt to the server. AttemptDeadline *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=attempt_deadline,json=attemptDeadline,proto3" json:"attempt_deadline,omitempty"` // The time that the server responded to the RPC attempt. Used for // calculating attempt_delay. ResponseTime *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=response_time,json=responseTime,proto3" json:"response_time,omitempty"` // The server perceived delay between sending the last response and // receiving this attempt. Used for validating attempt delay backoff. AttemptDelay *durationpb.Duration `protobuf:"bytes,4,opt,name=attempt_delay,json=attemptDelay,proto3" json:"attempt_delay,omitempty"` // The status returned to the attempt. Status *status.Status `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` } func (x *StreamingSequenceReport_Attempt) Reset() { *x = StreamingSequenceReport_Attempt{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *StreamingSequenceReport_Attempt) String() string { return protoimpl.X.MessageStringOf(x) } func (*StreamingSequenceReport_Attempt) ProtoMessage() {} func (x *StreamingSequenceReport_Attempt) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[13] 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 StreamingSequenceReport_Attempt.ProtoReflect.Descriptor instead. func (*StreamingSequenceReport_Attempt) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_sequence_proto_rawDescGZIP(), []int{2, 0} } func (x *StreamingSequenceReport_Attempt) GetAttemptNumber() int32 { if x != nil { return x.AttemptNumber } return 0 } func (x *StreamingSequenceReport_Attempt) GetAttemptDeadline() *timestamppb.Timestamp { if x != nil { return x.AttemptDeadline } return nil } func (x *StreamingSequenceReport_Attempt) GetResponseTime() *timestamppb.Timestamp { if x != nil { return x.ResponseTime } return nil } func (x *StreamingSequenceReport_Attempt) GetAttemptDelay() *durationpb.Duration { if x != nil { return x.AttemptDelay } return nil } func (x *StreamingSequenceReport_Attempt) GetStatus() *status.Status { if x != nil { return x.Status } return nil } // Contains metrics on individual RPC Attempts in a sequence. type SequenceReport_Attempt struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The attempt number - starting at 0. AttemptNumber int32 `protobuf:"varint,1,opt,name=attempt_number,json=attemptNumber,proto3" json:"attempt_number,omitempty"` // The deadline dictated by the attempt to the server. AttemptDeadline *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=attempt_deadline,json=attemptDeadline,proto3" json:"attempt_deadline,omitempty"` // The time that the server responded to the RPC attempt. Used for // calculating attempt_delay. ResponseTime *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=response_time,json=responseTime,proto3" json:"response_time,omitempty"` // The server perceived delay between sending the last response and // receiving this attempt. Used for validating attempt delay backoff. AttemptDelay *durationpb.Duration `protobuf:"bytes,4,opt,name=attempt_delay,json=attemptDelay,proto3" json:"attempt_delay,omitempty"` // The status returned to the attempt. Status *status.Status `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` } func (x *SequenceReport_Attempt) Reset() { *x = SequenceReport_Attempt{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *SequenceReport_Attempt) String() string { return protoimpl.X.MessageStringOf(x) } func (*SequenceReport_Attempt) ProtoMessage() {} func (x *SequenceReport_Attempt) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_sequence_proto_msgTypes[14] 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 SequenceReport_Attempt.ProtoReflect.Descriptor instead. func (*SequenceReport_Attempt) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_sequence_proto_rawDescGZIP(), []int{3, 0} } func (x *SequenceReport_Attempt) GetAttemptNumber() int32 { if x != nil { return x.AttemptNumber } return 0 } func (x *SequenceReport_Attempt) GetAttemptDeadline() *timestamppb.Timestamp { if x != nil { return x.AttemptDeadline } return nil } func (x *SequenceReport_Attempt) GetResponseTime() *timestamppb.Timestamp { if x != nil { return x.ResponseTime } return nil } func (x *SequenceReport_Attempt) GetAttemptDelay() *durationpb.Duration { if x != nil { return x.AttemptDelay } return nil } func (x *SequenceReport_Attempt) GetStatus() *status.Status { if x != nil { return x.Status } return nil } var File_google_showcase_v1beta1_sequence_proto protoreflect.FileDescriptor var file_google_showcase_v1beta1_sequence_proto_rawDesc = []byte{ 0x0a, 0x26, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x17, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 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, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 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, 0x17, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x93, 0x02, 0x0a, 0x08, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x17, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x03, 0xe0, 0x41, 0x03, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x48, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x1a, 0x67, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2f, 0x0a, 0x05, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x02, 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, 0x05, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x3a, 0x3b, 0xea, 0x41, 0x38, 0x0a, 0x20, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x14, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x7d, 0x22, 0x83, 0x03, 0x0a, 0x11, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x17, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x03, 0xe0, 0x41, 0x03, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x51, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x1a, 0x8e, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2f, 0x0a, 0x05, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x02, 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, 0x05, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x3a, 0x57, 0xea, 0x41, 0x54, 0x0a, 0x29, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x27, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x7d, 0x22, 0xa6, 0x04, 0x0a, 0x17, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x17, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x03, 0xe0, 0x41, 0x03, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x54, 0x0a, 0x08, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x52, 0x08, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x1a, 0xa4, 0x02, 0x0a, 0x07, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x45, 0x0a, 0x10, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 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, 0x0f, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x3f, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 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, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0d, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x04, 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, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x2a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3a, 0x75, 0xea, 0x41, 0x72, 0x0a, 0x2f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x3f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x7d, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x22, 0xef, 0x03, 0x0a, 0x0e, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x17, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x03, 0xe0, 0x41, 0x03, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x52, 0x08, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x1a, 0xa4, 0x02, 0x0a, 0x07, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x45, 0x0a, 0x10, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 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, 0x0f, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x3f, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 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, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0d, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x04, 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, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x2a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3a, 0x50, 0xea, 0x41, 0x4d, 0x0a, 0x26, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x23, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x7d, 0x2f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x56, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3d, 0x0a, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x7b, 0x0a, 0x1e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x59, 0x0a, 0x12, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x11, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x56, 0x0a, 0x16, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x28, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x22, 0x0a, 0x20, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x95, 0x01, 0x0a, 0x1f, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x45, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x31, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x2b, 0x0a, 0x29, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x42, 0x03, 0xe0, 0x41, 0x01, 0x52, 0x0d, 0x6c, 0x61, 0x73, 0x74, 0x46, 0x61, 0x69, 0x6c, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x3c, 0x0a, 0x20, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x5e, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x42, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2e, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x28, 0x0a, 0x26, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x70, 0x0a, 0x21, 0x47, 0x65, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x37, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x31, 0x0a, 0x2f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x32, 0xf0, 0x08, 0x0a, 0x0f, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x94, 0x01, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x2e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x2f, 0xda, 0x41, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x3a, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x12, 0xcc, 0x01, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x37, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x4c, 0xda, 0x41, 0x12, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x31, 0x3a, 0x12, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x1b, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x12, 0xaa, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x31, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x39, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2c, 0x12, 0x2a, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x7d, 0x12, 0xd7, 0x01, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x3a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x4b, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3e, 0x12, 0x3c, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x7d, 0x12, 0x89, 0x01, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x2f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x2d, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x01, 0x2a, 0x22, 0x1b, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0xd0, 0x01, 0x0a, 0x18, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x38, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3d, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x3a, 0x01, 0x2a, 0x22, 0x2b, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x30, 0x01, 0x1a, 0x11, 0xca, 0x41, 0x0e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x3a, 0x37, 0x34, 0x36, 0x39, 0x42, 0x71, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x50, 0x01, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x67, 0x61, 0x70, 0x69, 0x63, 0x2d, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x65, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xea, 0x02, 0x19, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x3a, 0x3a, 0x53, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_google_showcase_v1beta1_sequence_proto_rawDescOnce sync.Once file_google_showcase_v1beta1_sequence_proto_rawDescData = file_google_showcase_v1beta1_sequence_proto_rawDesc ) func file_google_showcase_v1beta1_sequence_proto_rawDescGZIP() []byte { file_google_showcase_v1beta1_sequence_proto_rawDescOnce.Do(func() { file_google_showcase_v1beta1_sequence_proto_rawDescData = protoimpl.X.CompressGZIP(file_google_showcase_v1beta1_sequence_proto_rawDescData) }) return file_google_showcase_v1beta1_sequence_proto_rawDescData } var file_google_showcase_v1beta1_sequence_proto_msgTypes = make([]protoimpl.MessageInfo, 15) var file_google_showcase_v1beta1_sequence_proto_goTypes = []interface{}{ (*Sequence)(nil), // 0: google.showcase.v1beta1.Sequence (*StreamingSequence)(nil), // 1: google.showcase.v1beta1.StreamingSequence (*StreamingSequenceReport)(nil), // 2: google.showcase.v1beta1.StreamingSequenceReport (*SequenceReport)(nil), // 3: google.showcase.v1beta1.SequenceReport (*CreateSequenceRequest)(nil), // 4: google.showcase.v1beta1.CreateSequenceRequest (*CreateStreamingSequenceRequest)(nil), // 5: google.showcase.v1beta1.CreateStreamingSequenceRequest (*AttemptSequenceRequest)(nil), // 6: google.showcase.v1beta1.AttemptSequenceRequest (*AttemptStreamingSequenceRequest)(nil), // 7: google.showcase.v1beta1.AttemptStreamingSequenceRequest (*AttemptStreamingSequenceResponse)(nil), // 8: google.showcase.v1beta1.AttemptStreamingSequenceResponse (*GetSequenceReportRequest)(nil), // 9: google.showcase.v1beta1.GetSequenceReportRequest (*GetStreamingSequenceReportRequest)(nil), // 10: google.showcase.v1beta1.GetStreamingSequenceReportRequest (*Sequence_Response)(nil), // 11: google.showcase.v1beta1.Sequence.Response (*StreamingSequence_Response)(nil), // 12: google.showcase.v1beta1.StreamingSequence.Response (*StreamingSequenceReport_Attempt)(nil), // 13: google.showcase.v1beta1.StreamingSequenceReport.Attempt (*SequenceReport_Attempt)(nil), // 14: google.showcase.v1beta1.SequenceReport.Attempt (*status.Status)(nil), // 15: google.rpc.Status (*durationpb.Duration)(nil), // 16: google.protobuf.Duration (*timestamppb.Timestamp)(nil), // 17: google.protobuf.Timestamp (*emptypb.Empty)(nil), // 18: google.protobuf.Empty } var file_google_showcase_v1beta1_sequence_proto_depIdxs = []int32{ 11, // 0: google.showcase.v1beta1.Sequence.responses:type_name -> google.showcase.v1beta1.Sequence.Response 12, // 1: google.showcase.v1beta1.StreamingSequence.responses:type_name -> google.showcase.v1beta1.StreamingSequence.Response 13, // 2: google.showcase.v1beta1.StreamingSequenceReport.attempts:type_name -> google.showcase.v1beta1.StreamingSequenceReport.Attempt 14, // 3: google.showcase.v1beta1.SequenceReport.attempts:type_name -> google.showcase.v1beta1.SequenceReport.Attempt 0, // 4: google.showcase.v1beta1.CreateSequenceRequest.sequence:type_name -> google.showcase.v1beta1.Sequence 1, // 5: google.showcase.v1beta1.CreateStreamingSequenceRequest.streaming_sequence:type_name -> google.showcase.v1beta1.StreamingSequence 15, // 6: google.showcase.v1beta1.Sequence.Response.status:type_name -> google.rpc.Status 16, // 7: google.showcase.v1beta1.Sequence.Response.delay:type_name -> google.protobuf.Duration 15, // 8: google.showcase.v1beta1.StreamingSequence.Response.status:type_name -> google.rpc.Status 16, // 9: google.showcase.v1beta1.StreamingSequence.Response.delay:type_name -> google.protobuf.Duration 17, // 10: google.showcase.v1beta1.StreamingSequenceReport.Attempt.attempt_deadline:type_name -> google.protobuf.Timestamp 17, // 11: google.showcase.v1beta1.StreamingSequenceReport.Attempt.response_time:type_name -> google.protobuf.Timestamp 16, // 12: google.showcase.v1beta1.StreamingSequenceReport.Attempt.attempt_delay:type_name -> google.protobuf.Duration 15, // 13: google.showcase.v1beta1.StreamingSequenceReport.Attempt.status:type_name -> google.rpc.Status 17, // 14: google.showcase.v1beta1.SequenceReport.Attempt.attempt_deadline:type_name -> google.protobuf.Timestamp 17, // 15: google.showcase.v1beta1.SequenceReport.Attempt.response_time:type_name -> google.protobuf.Timestamp 16, // 16: google.showcase.v1beta1.SequenceReport.Attempt.attempt_delay:type_name -> google.protobuf.Duration 15, // 17: google.showcase.v1beta1.SequenceReport.Attempt.status:type_name -> google.rpc.Status 4, // 18: google.showcase.v1beta1.SequenceService.CreateSequence:input_type -> google.showcase.v1beta1.CreateSequenceRequest 5, // 19: google.showcase.v1beta1.SequenceService.CreateStreamingSequence:input_type -> google.showcase.v1beta1.CreateStreamingSequenceRequest 9, // 20: google.showcase.v1beta1.SequenceService.GetSequenceReport:input_type -> google.showcase.v1beta1.GetSequenceReportRequest 10, // 21: google.showcase.v1beta1.SequenceService.GetStreamingSequenceReport:input_type -> google.showcase.v1beta1.GetStreamingSequenceReportRequest 6, // 22: google.showcase.v1beta1.SequenceService.AttemptSequence:input_type -> google.showcase.v1beta1.AttemptSequenceRequest 7, // 23: google.showcase.v1beta1.SequenceService.AttemptStreamingSequence:input_type -> google.showcase.v1beta1.AttemptStreamingSequenceRequest 0, // 24: google.showcase.v1beta1.SequenceService.CreateSequence:output_type -> google.showcase.v1beta1.Sequence 1, // 25: google.showcase.v1beta1.SequenceService.CreateStreamingSequence:output_type -> google.showcase.v1beta1.StreamingSequence 3, // 26: google.showcase.v1beta1.SequenceService.GetSequenceReport:output_type -> google.showcase.v1beta1.SequenceReport 2, // 27: google.showcase.v1beta1.SequenceService.GetStreamingSequenceReport:output_type -> google.showcase.v1beta1.StreamingSequenceReport 18, // 28: google.showcase.v1beta1.SequenceService.AttemptSequence:output_type -> google.protobuf.Empty 8, // 29: google.showcase.v1beta1.SequenceService.AttemptStreamingSequence:output_type -> google.showcase.v1beta1.AttemptStreamingSequenceResponse 24, // [24:30] is the sub-list for method output_type 18, // [18:24] is the sub-list for method input_type 18, // [18:18] is the sub-list for extension type_name 18, // [18:18] is the sub-list for extension extendee 0, // [0:18] is the sub-list for field type_name } func init() { file_google_showcase_v1beta1_sequence_proto_init() } func file_google_showcase_v1beta1_sequence_proto_init() { if File_google_showcase_v1beta1_sequence_proto != nil { return } if !protoimpl.UnsafeEnabled { file_google_showcase_v1beta1_sequence_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Sequence); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_sequence_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StreamingSequence); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_sequence_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StreamingSequenceReport); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_sequence_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SequenceReport); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_sequence_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateSequenceRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_sequence_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateStreamingSequenceRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_sequence_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AttemptSequenceRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_sequence_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AttemptStreamingSequenceRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_sequence_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AttemptStreamingSequenceResponse); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_sequence_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetSequenceReportRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_sequence_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetStreamingSequenceReportRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_sequence_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Sequence_Response); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_sequence_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StreamingSequence_Response); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_sequence_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StreamingSequenceReport_Attempt); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_sequence_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SequenceReport_Attempt); 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_google_showcase_v1beta1_sequence_proto_rawDesc, NumEnums: 0, NumMessages: 15, NumExtensions: 0, NumServices: 1, }, GoTypes: file_google_showcase_v1beta1_sequence_proto_goTypes, DependencyIndexes: file_google_showcase_v1beta1_sequence_proto_depIdxs, MessageInfos: file_google_showcase_v1beta1_sequence_proto_msgTypes, }.Build() File_google_showcase_v1beta1_sequence_proto = out.File file_google_showcase_v1beta1_sequence_proto_rawDesc = nil file_google_showcase_v1beta1_sequence_proto_goTypes = nil file_google_showcase_v1beta1_sequence_proto_depIdxs = nil } // Reference imports to suppress errors if they are not otherwise used. var _ context.Context var _ grpc.ClientConnInterface // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. const _ = grpc.SupportPackageIsVersion6 // SequenceServiceClient is the client API for SequenceService service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type SequenceServiceClient interface { // Create a sequence of responses to be returned as unary calls CreateSequence(ctx context.Context, in *CreateSequenceRequest, opts ...grpc.CallOption) (*Sequence, error) // Creates a sequence of responses to be returned in a server streaming call CreateStreamingSequence(ctx context.Context, in *CreateStreamingSequenceRequest, opts ...grpc.CallOption) (*StreamingSequence, error) // Retrieves a sequence report which can be used to retrieve information about a // sequence of unary calls. GetSequenceReport(ctx context.Context, in *GetSequenceReportRequest, opts ...grpc.CallOption) (*SequenceReport, error) // Retrieves a sequence report which can be used to retrieve information // about a sequences of responses in a server streaming call. GetStreamingSequenceReport(ctx context.Context, in *GetStreamingSequenceReportRequest, opts ...grpc.CallOption) (*StreamingSequenceReport, error) // Attempts a sequence of unary responses. AttemptSequence(ctx context.Context, in *AttemptSequenceRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) // Attempts a server streaming call with a sequence of responses // Can be used to test retries and stream resumption logic // May not function as expected in HTTP mode due to when http statuses are sent // See https://github.com/googleapis/gapic-showcase/issues/1377 for more details AttemptStreamingSequence(ctx context.Context, in *AttemptStreamingSequenceRequest, opts ...grpc.CallOption) (SequenceService_AttemptStreamingSequenceClient, error) } type sequenceServiceClient struct { cc grpc.ClientConnInterface } func NewSequenceServiceClient(cc grpc.ClientConnInterface) SequenceServiceClient { return &sequenceServiceClient{cc} } func (c *sequenceServiceClient) CreateSequence(ctx context.Context, in *CreateSequenceRequest, opts ...grpc.CallOption) (*Sequence, error) { out := new(Sequence) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.SequenceService/CreateSequence", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *sequenceServiceClient) CreateStreamingSequence(ctx context.Context, in *CreateStreamingSequenceRequest, opts ...grpc.CallOption) (*StreamingSequence, error) { out := new(StreamingSequence) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.SequenceService/CreateStreamingSequence", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *sequenceServiceClient) GetSequenceReport(ctx context.Context, in *GetSequenceReportRequest, opts ...grpc.CallOption) (*SequenceReport, error) { out := new(SequenceReport) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.SequenceService/GetSequenceReport", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *sequenceServiceClient) GetStreamingSequenceReport(ctx context.Context, in *GetStreamingSequenceReportRequest, opts ...grpc.CallOption) (*StreamingSequenceReport, error) { out := new(StreamingSequenceReport) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.SequenceService/GetStreamingSequenceReport", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *sequenceServiceClient) AttemptSequence(ctx context.Context, in *AttemptSequenceRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.SequenceService/AttemptSequence", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *sequenceServiceClient) AttemptStreamingSequence(ctx context.Context, in *AttemptStreamingSequenceRequest, opts ...grpc.CallOption) (SequenceService_AttemptStreamingSequenceClient, error) { stream, err := c.cc.NewStream(ctx, &_SequenceService_serviceDesc.Streams[0], "/google.showcase.v1beta1.SequenceService/AttemptStreamingSequence", opts...) if err != nil { return nil, err } x := &sequenceServiceAttemptStreamingSequenceClient{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 SequenceService_AttemptStreamingSequenceClient interface { Recv() (*AttemptStreamingSequenceResponse, error) grpc.ClientStream } type sequenceServiceAttemptStreamingSequenceClient struct { grpc.ClientStream } func (x *sequenceServiceAttemptStreamingSequenceClient) Recv() (*AttemptStreamingSequenceResponse, error) { m := new(AttemptStreamingSequenceResponse) if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err } return m, nil } // SequenceServiceServer is the server API for SequenceService service. type SequenceServiceServer interface { // Create a sequence of responses to be returned as unary calls CreateSequence(context.Context, *CreateSequenceRequest) (*Sequence, error) // Creates a sequence of responses to be returned in a server streaming call CreateStreamingSequence(context.Context, *CreateStreamingSequenceRequest) (*StreamingSequence, error) // Retrieves a sequence report which can be used to retrieve information about a // sequence of unary calls. GetSequenceReport(context.Context, *GetSequenceReportRequest) (*SequenceReport, error) // Retrieves a sequence report which can be used to retrieve information // about a sequences of responses in a server streaming call. GetStreamingSequenceReport(context.Context, *GetStreamingSequenceReportRequest) (*StreamingSequenceReport, error) // Attempts a sequence of unary responses. AttemptSequence(context.Context, *AttemptSequenceRequest) (*emptypb.Empty, error) // Attempts a server streaming call with a sequence of responses // Can be used to test retries and stream resumption logic // May not function as expected in HTTP mode due to when http statuses are sent // See https://github.com/googleapis/gapic-showcase/issues/1377 for more details AttemptStreamingSequence(*AttemptStreamingSequenceRequest, SequenceService_AttemptStreamingSequenceServer) error } // UnimplementedSequenceServiceServer can be embedded to have forward compatible implementations. type UnimplementedSequenceServiceServer struct { } func (*UnimplementedSequenceServiceServer) CreateSequence(context.Context, *CreateSequenceRequest) (*Sequence, error) { return nil, status1.Errorf(codes.Unimplemented, "method CreateSequence not implemented") } func (*UnimplementedSequenceServiceServer) CreateStreamingSequence(context.Context, *CreateStreamingSequenceRequest) (*StreamingSequence, error) { return nil, status1.Errorf(codes.Unimplemented, "method CreateStreamingSequence not implemented") } func (*UnimplementedSequenceServiceServer) GetSequenceReport(context.Context, *GetSequenceReportRequest) (*SequenceReport, error) { return nil, status1.Errorf(codes.Unimplemented, "method GetSequenceReport not implemented") } func (*UnimplementedSequenceServiceServer) GetStreamingSequenceReport(context.Context, *GetStreamingSequenceReportRequest) (*StreamingSequenceReport, error) { return nil, status1.Errorf(codes.Unimplemented, "method GetStreamingSequenceReport not implemented") } func (*UnimplementedSequenceServiceServer) AttemptSequence(context.Context, *AttemptSequenceRequest) (*emptypb.Empty, error) { return nil, status1.Errorf(codes.Unimplemented, "method AttemptSequence not implemented") } func (*UnimplementedSequenceServiceServer) AttemptStreamingSequence(*AttemptStreamingSequenceRequest, SequenceService_AttemptStreamingSequenceServer) error { return status1.Errorf(codes.Unimplemented, "method AttemptStreamingSequence not implemented") } func RegisterSequenceServiceServer(s *grpc.Server, srv SequenceServiceServer) { s.RegisterService(&_SequenceService_serviceDesc, srv) } func _SequenceService_CreateSequence_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(CreateSequenceRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(SequenceServiceServer).CreateSequence(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.SequenceService/CreateSequence", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(SequenceServiceServer).CreateSequence(ctx, req.(*CreateSequenceRequest)) } return interceptor(ctx, in, info, handler) } func _SequenceService_CreateStreamingSequence_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(CreateStreamingSequenceRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(SequenceServiceServer).CreateStreamingSequence(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.SequenceService/CreateStreamingSequence", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(SequenceServiceServer).CreateStreamingSequence(ctx, req.(*CreateStreamingSequenceRequest)) } return interceptor(ctx, in, info, handler) } func _SequenceService_GetSequenceReport_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetSequenceReportRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(SequenceServiceServer).GetSequenceReport(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.SequenceService/GetSequenceReport", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(SequenceServiceServer).GetSequenceReport(ctx, req.(*GetSequenceReportRequest)) } return interceptor(ctx, in, info, handler) } func _SequenceService_GetStreamingSequenceReport_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetStreamingSequenceReportRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(SequenceServiceServer).GetStreamingSequenceReport(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.SequenceService/GetStreamingSequenceReport", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(SequenceServiceServer).GetStreamingSequenceReport(ctx, req.(*GetStreamingSequenceReportRequest)) } return interceptor(ctx, in, info, handler) } func _SequenceService_AttemptSequence_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(AttemptSequenceRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(SequenceServiceServer).AttemptSequence(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.SequenceService/AttemptSequence", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(SequenceServiceServer).AttemptSequence(ctx, req.(*AttemptSequenceRequest)) } return interceptor(ctx, in, info, handler) } func _SequenceService_AttemptStreamingSequence_Handler(srv interface{}, stream grpc.ServerStream) error { m := new(AttemptStreamingSequenceRequest) if err := stream.RecvMsg(m); err != nil { return err } return srv.(SequenceServiceServer).AttemptStreamingSequence(m, &sequenceServiceAttemptStreamingSequenceServer{stream}) } type SequenceService_AttemptStreamingSequenceServer interface { Send(*AttemptStreamingSequenceResponse) error grpc.ServerStream } type sequenceServiceAttemptStreamingSequenceServer struct { grpc.ServerStream } func (x *sequenceServiceAttemptStreamingSequenceServer) Send(m *AttemptStreamingSequenceResponse) error { return x.ServerStream.SendMsg(m) } var _SequenceService_serviceDesc = grpc.ServiceDesc{ ServiceName: "google.showcase.v1beta1.SequenceService", HandlerType: (*SequenceServiceServer)(nil), Methods: []grpc.MethodDesc{ { MethodName: "CreateSequence", Handler: _SequenceService_CreateSequence_Handler, }, { MethodName: "CreateStreamingSequence", Handler: _SequenceService_CreateStreamingSequence_Handler, }, { MethodName: "GetSequenceReport", Handler: _SequenceService_GetSequenceReport_Handler, }, { MethodName: "GetStreamingSequenceReport", Handler: _SequenceService_GetStreamingSequenceReport_Handler, }, { MethodName: "AttemptSequence", Handler: _SequenceService_AttemptSequence_Handler, }, }, Streams: []grpc.StreamDesc{ { StreamName: "AttemptStreamingSequence", Handler: _SequenceService_AttemptStreamingSequence_Handler, ServerStreams: true, }, }, Metadata: "google/showcase/v1beta1/sequence.proto", } ================================================ FILE: server/genproto/testing.pb.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.33.0 // protoc v3.20.3 // source: google/showcase/v1beta1/testing.proto package genproto import ( context "context" _ "google.golang.org/genproto/googleapis/api/annotations" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" emptypb "google.golang.org/protobuf/types/known/emptypb" 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) ) // The specification versions understood by Showcase. type Session_Version int32 const ( // Unspecified version. If passed on creation, the session will default // to using the latest stable release. Session_VERSION_UNSPECIFIED Session_Version = 0 // The latest v1. Currently, this is v1.0. Session_V1_LATEST Session_Version = 1 // v1.0. (Until the spec is "GA", this will be a moving target.) Session_V1_0 Session_Version = 2 ) // Enum value maps for Session_Version. var ( Session_Version_name = map[int32]string{ 0: "VERSION_UNSPECIFIED", 1: "V1_LATEST", 2: "V1_0", } Session_Version_value = map[string]int32{ "VERSION_UNSPECIFIED": 0, "V1_LATEST": 1, "V1_0": 2, } ) func (x Session_Version) Enum() *Session_Version { p := new(Session_Version) *p = x return p } func (x Session_Version) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (Session_Version) Descriptor() protoreflect.EnumDescriptor { return file_google_showcase_v1beta1_testing_proto_enumTypes[0].Descriptor() } func (Session_Version) Type() protoreflect.EnumType { return &file_google_showcase_v1beta1_testing_proto_enumTypes[0] } func (x Session_Version) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use Session_Version.Descriptor instead. func (Session_Version) EnumDescriptor() ([]byte, []int) { return file_google_showcase_v1beta1_testing_proto_rawDescGZIP(), []int{0, 0} } // The topline state of the report. type ReportSessionResponse_Result int32 const ( ReportSessionResponse_RESULT_UNSPECIFIED ReportSessionResponse_Result = 0 // The session is complete, and everything passed. ReportSessionResponse_PASSED ReportSessionResponse_Result = 1 // The session had an explicit failure. ReportSessionResponse_FAILED ReportSessionResponse_Result = 2 // The session is incomplete. This is a failure response. ReportSessionResponse_INCOMPLETE ReportSessionResponse_Result = 3 ) // Enum value maps for ReportSessionResponse_Result. var ( ReportSessionResponse_Result_name = map[int32]string{ 0: "RESULT_UNSPECIFIED", 1: "PASSED", 2: "FAILED", 3: "INCOMPLETE", } ReportSessionResponse_Result_value = map[string]int32{ "RESULT_UNSPECIFIED": 0, "PASSED": 1, "FAILED": 2, "INCOMPLETE": 3, } ) func (x ReportSessionResponse_Result) Enum() *ReportSessionResponse_Result { p := new(ReportSessionResponse_Result) *p = x return p } func (x ReportSessionResponse_Result) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (ReportSessionResponse_Result) Descriptor() protoreflect.EnumDescriptor { return file_google_showcase_v1beta1_testing_proto_enumTypes[1].Descriptor() } func (ReportSessionResponse_Result) Type() protoreflect.EnumType { return &file_google_showcase_v1beta1_testing_proto_enumTypes[1] } func (x ReportSessionResponse_Result) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use ReportSessionResponse_Result.Descriptor instead. func (ReportSessionResponse_Result) EnumDescriptor() ([]byte, []int) { return file_google_showcase_v1beta1_testing_proto_rawDescGZIP(), []int{7, 0} } // Whether or not a test is required, recommended, or optional. type Test_ExpectationLevel int32 const ( Test_EXPECTATION_LEVEL_UNSPECIFIED Test_ExpectationLevel = 0 // This test is strictly required. Test_REQUIRED Test_ExpectationLevel = 1 // This test is recommended. // // If a generator explicitly ignores a recommended test (see `DeleteTest`), // then the report may still pass, but with a warning. // // If a generator skips a recommended test and does not explicitly // express that intention, the report will fail. Test_RECOMMENDED Test_ExpectationLevel = 2 // This test is optional. // // If a generator explicitly ignores an optional test (see `DeleteTest`), // then the report may still pass, and no warning will be issued. // // If a generator skips an optional test and does not explicitly // express that intention, the report may still pass, but with a // warning. Test_OPTIONAL Test_ExpectationLevel = 3 ) // Enum value maps for Test_ExpectationLevel. var ( Test_ExpectationLevel_name = map[int32]string{ 0: "EXPECTATION_LEVEL_UNSPECIFIED", 1: "REQUIRED", 2: "RECOMMENDED", 3: "OPTIONAL", } Test_ExpectationLevel_value = map[string]int32{ "EXPECTATION_LEVEL_UNSPECIFIED": 0, "REQUIRED": 1, "RECOMMENDED": 2, "OPTIONAL": 3, } ) func (x Test_ExpectationLevel) Enum() *Test_ExpectationLevel { p := new(Test_ExpectationLevel) *p = x return p } func (x Test_ExpectationLevel) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (Test_ExpectationLevel) Descriptor() protoreflect.EnumDescriptor { return file_google_showcase_v1beta1_testing_proto_enumTypes[2].Descriptor() } func (Test_ExpectationLevel) Type() protoreflect.EnumType { return &file_google_showcase_v1beta1_testing_proto_enumTypes[2] } func (x Test_ExpectationLevel) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use Test_ExpectationLevel.Descriptor instead. func (Test_ExpectationLevel) EnumDescriptor() ([]byte, []int) { return file_google_showcase_v1beta1_testing_proto_rawDescGZIP(), []int{8, 0} } // The different potential types of issues. type Issue_Type int32 const ( Issue_TYPE_UNSPECIFIED Issue_Type = 0 // The test was never instrumented. Issue_SKIPPED Issue_Type = 1 // The test was started but never confirmed. Issue_PENDING Issue_Type = 2 // The test was instrumented, but Showcase got an unexpected // value when the generator tried to confirm success. Issue_INCORRECT_CONFIRMATION Issue_Type = 3 ) // Enum value maps for Issue_Type. var ( Issue_Type_name = map[int32]string{ 0: "TYPE_UNSPECIFIED", 1: "SKIPPED", 2: "PENDING", 3: "INCORRECT_CONFIRMATION", } Issue_Type_value = map[string]int32{ "TYPE_UNSPECIFIED": 0, "SKIPPED": 1, "PENDING": 2, "INCORRECT_CONFIRMATION": 3, } ) func (x Issue_Type) Enum() *Issue_Type { p := new(Issue_Type) *p = x return p } func (x Issue_Type) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (Issue_Type) Descriptor() protoreflect.EnumDescriptor { return file_google_showcase_v1beta1_testing_proto_enumTypes[3].Descriptor() } func (Issue_Type) Type() protoreflect.EnumType { return &file_google_showcase_v1beta1_testing_proto_enumTypes[3] } func (x Issue_Type) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use Issue_Type.Descriptor instead. func (Issue_Type) EnumDescriptor() ([]byte, []int) { return file_google_showcase_v1beta1_testing_proto_rawDescGZIP(), []int{9, 0} } // Severity levels. type Issue_Severity int32 const ( Issue_SEVERITY_UNSPECIFIED Issue_Severity = 0 // Errors. Issue_ERROR Issue_Severity = 1 // Warnings. Issue_WARNING Issue_Severity = 2 ) // Enum value maps for Issue_Severity. var ( Issue_Severity_name = map[int32]string{ 0: "SEVERITY_UNSPECIFIED", 1: "ERROR", 2: "WARNING", } Issue_Severity_value = map[string]int32{ "SEVERITY_UNSPECIFIED": 0, "ERROR": 1, "WARNING": 2, } ) func (x Issue_Severity) Enum() *Issue_Severity { p := new(Issue_Severity) *p = x return p } func (x Issue_Severity) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (Issue_Severity) Descriptor() protoreflect.EnumDescriptor { return file_google_showcase_v1beta1_testing_proto_enumTypes[4].Descriptor() } func (Issue_Severity) Type() protoreflect.EnumType { return &file_google_showcase_v1beta1_testing_proto_enumTypes[4] } func (x Issue_Severity) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use Issue_Severity.Descriptor instead. func (Issue_Severity) EnumDescriptor() ([]byte, []int) { return file_google_showcase_v1beta1_testing_proto_rawDescGZIP(), []int{9, 1} } // A session is a suite of tests, generally being made in the context // of testing code generation. // // A session defines tests it may expect, based on which version of the // code generation spec is in use. type Session struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The name of the session. The ID must conform to ^[a-z]+$ // If this is not provided, Showcase chooses one at random. Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // Required. The version this session is using. Version Session_Version `protobuf:"varint,2,opt,name=version,proto3,enum=google.showcase.v1beta1.Session_Version" json:"version,omitempty"` } func (x *Session) Reset() { *x = Session{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Session) String() string { return protoimpl.X.MessageStringOf(x) } func (*Session) ProtoMessage() {} func (x *Session) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_testing_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 Session.ProtoReflect.Descriptor instead. func (*Session) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_testing_proto_rawDescGZIP(), []int{0} } func (x *Session) GetName() string { if x != nil { return x.Name } return "" } func (x *Session) GetVersion() Session_Version { if x != nil { return x.Version } return Session_VERSION_UNSPECIFIED } // The request for the CreateSession method. type CreateSessionRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The session to be created. // Sessions are immutable once they are created (although they can // be deleted). Session *Session `protobuf:"bytes,1,opt,name=session,proto3" json:"session,omitempty"` } func (x *CreateSessionRequest) Reset() { *x = CreateSessionRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *CreateSessionRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*CreateSessionRequest) ProtoMessage() {} func (x *CreateSessionRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[1] 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 CreateSessionRequest.ProtoReflect.Descriptor instead. func (*CreateSessionRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_testing_proto_rawDescGZIP(), []int{1} } func (x *CreateSessionRequest) GetSession() *Session { if x != nil { return x.Session } return nil } // The request for the GetSession method. type GetSessionRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The session to be retrieved. Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` } func (x *GetSessionRequest) Reset() { *x = GetSessionRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *GetSessionRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*GetSessionRequest) ProtoMessage() {} func (x *GetSessionRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[2] 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 GetSessionRequest.ProtoReflect.Descriptor instead. func (*GetSessionRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_testing_proto_rawDescGZIP(), []int{2} } func (x *GetSessionRequest) GetName() string { if x != nil { return x.Name } return "" } // The request for the ListSessions method. type ListSessionsRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The maximum number of sessions to return per page. PageSize int32 `protobuf:"varint,1,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` // The page token, for retrieving subsequent pages. PageToken string `protobuf:"bytes,2,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` } func (x *ListSessionsRequest) Reset() { *x = ListSessionsRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ListSessionsRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*ListSessionsRequest) ProtoMessage() {} func (x *ListSessionsRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[3] 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 ListSessionsRequest.ProtoReflect.Descriptor instead. func (*ListSessionsRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_testing_proto_rawDescGZIP(), []int{3} } func (x *ListSessionsRequest) GetPageSize() int32 { if x != nil { return x.PageSize } return 0 } func (x *ListSessionsRequest) GetPageToken() string { if x != nil { return x.PageToken } return "" } // Response for the ListSessions method. type ListSessionsResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The sessions being returned. Sessions []*Session `protobuf:"bytes,1,rep,name=sessions,proto3" json:"sessions,omitempty"` // The next page token, if any. // An empty value here means the last page has been reached. NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` } func (x *ListSessionsResponse) Reset() { *x = ListSessionsResponse{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ListSessionsResponse) String() string { return protoimpl.X.MessageStringOf(x) } func (*ListSessionsResponse) ProtoMessage() {} func (x *ListSessionsResponse) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[4] 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 ListSessionsResponse.ProtoReflect.Descriptor instead. func (*ListSessionsResponse) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_testing_proto_rawDescGZIP(), []int{4} } func (x *ListSessionsResponse) GetSessions() []*Session { if x != nil { return x.Sessions } return nil } func (x *ListSessionsResponse) GetNextPageToken() string { if x != nil { return x.NextPageToken } return "" } // Request for the DeleteSession method. type DeleteSessionRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The session to be deleted. Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` } func (x *DeleteSessionRequest) Reset() { *x = DeleteSessionRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *DeleteSessionRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*DeleteSessionRequest) ProtoMessage() {} func (x *DeleteSessionRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[5] 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 DeleteSessionRequest.ProtoReflect.Descriptor instead. func (*DeleteSessionRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_testing_proto_rawDescGZIP(), []int{5} } func (x *DeleteSessionRequest) GetName() string { if x != nil { return x.Name } return "" } // Request message for reporting on a session. type ReportSessionRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The session to be reported on. Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` } func (x *ReportSessionRequest) Reset() { *x = ReportSessionRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ReportSessionRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*ReportSessionRequest) ProtoMessage() {} func (x *ReportSessionRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[6] 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 ReportSessionRequest.ProtoReflect.Descriptor instead. func (*ReportSessionRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_testing_proto_rawDescGZIP(), []int{6} } func (x *ReportSessionRequest) GetName() string { if x != nil { return x.Name } return "" } // Response message for reporting on a session. type ReportSessionResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The state of the report. Result ReportSessionResponse_Result `protobuf:"varint,1,opt,name=result,proto3,enum=google.showcase.v1beta1.ReportSessionResponse_Result" json:"result,omitempty"` // The test runs of this session. TestRuns []*TestRun `protobuf:"bytes,2,rep,name=test_runs,json=testRuns,proto3" json:"test_runs,omitempty"` } func (x *ReportSessionResponse) Reset() { *x = ReportSessionResponse{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ReportSessionResponse) String() string { return protoimpl.X.MessageStringOf(x) } func (*ReportSessionResponse) ProtoMessage() {} func (x *ReportSessionResponse) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[7] 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 ReportSessionResponse.ProtoReflect.Descriptor instead. func (*ReportSessionResponse) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_testing_proto_rawDescGZIP(), []int{7} } func (x *ReportSessionResponse) GetResult() ReportSessionResponse_Result { if x != nil { return x.Result } return ReportSessionResponse_RESULT_UNSPECIFIED } func (x *ReportSessionResponse) GetTestRuns() []*TestRun { if x != nil { return x.TestRuns } return nil } type Test struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The name of the test. // The tests/* portion of the names are hard-coded, and do not change // from session to session. Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // The expectation level for this test. ExpectationLevel Test_ExpectationLevel `protobuf:"varint,2,opt,name=expectation_level,json=expectationLevel,proto3,enum=google.showcase.v1beta1.Test_ExpectationLevel" json:"expectation_level,omitempty"` // A description of the test. Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` // The blueprints that will satisfy this test. There may be multiple blueprints // that can signal to the server that this test case is being exercised. Although // multiple blueprints are specified, only a single blueprint needs to be run to // signal that the test case was exercised. Blueprints []*Test_Blueprint `protobuf:"bytes,4,rep,name=blueprints,proto3" json:"blueprints,omitempty"` } func (x *Test) Reset() { *x = Test{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Test) String() string { return protoimpl.X.MessageStringOf(x) } func (*Test) ProtoMessage() {} func (x *Test) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[8] 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 Test.ProtoReflect.Descriptor instead. func (*Test) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_testing_proto_rawDescGZIP(), []int{8} } func (x *Test) GetName() string { if x != nil { return x.Name } return "" } func (x *Test) GetExpectationLevel() Test_ExpectationLevel { if x != nil { return x.ExpectationLevel } return Test_EXPECTATION_LEVEL_UNSPECIFIED } func (x *Test) GetDescription() string { if x != nil { return x.Description } return "" } func (x *Test) GetBlueprints() []*Test_Blueprint { if x != nil { return x.Blueprints } return nil } // An issue found in the test. type Issue struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The type of the issue. Type Issue_Type `protobuf:"varint,1,opt,name=type,proto3,enum=google.showcase.v1beta1.Issue_Type" json:"type,omitempty"` // The severity of the issue. Severity Issue_Severity `protobuf:"varint,2,opt,name=severity,proto3,enum=google.showcase.v1beta1.Issue_Severity" json:"severity,omitempty"` // A description of the issue. Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` } func (x *Issue) Reset() { *x = Issue{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Issue) String() string { return protoimpl.X.MessageStringOf(x) } func (*Issue) ProtoMessage() {} func (x *Issue) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[9] 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 Issue.ProtoReflect.Descriptor instead. func (*Issue) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_testing_proto_rawDescGZIP(), []int{9} } func (x *Issue) GetType() Issue_Type { if x != nil { return x.Type } return Issue_TYPE_UNSPECIFIED } func (x *Issue) GetSeverity() Issue_Severity { if x != nil { return x.Severity } return Issue_SEVERITY_UNSPECIFIED } func (x *Issue) GetDescription() string { if x != nil { return x.Description } return "" } // The request for the ListTests method. type ListTestsRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The session. Parent string `protobuf:"bytes,1,opt,name=parent,proto3" json:"parent,omitempty"` // The maximum number of tests to return per page. PageSize int32 `protobuf:"varint,2,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` // The page token, for retrieving subsequent pages. PageToken string `protobuf:"bytes,3,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` } func (x *ListTestsRequest) Reset() { *x = ListTestsRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ListTestsRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*ListTestsRequest) ProtoMessage() {} func (x *ListTestsRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[10] 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 ListTestsRequest.ProtoReflect.Descriptor instead. func (*ListTestsRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_testing_proto_rawDescGZIP(), []int{10} } func (x *ListTestsRequest) GetParent() string { if x != nil { return x.Parent } return "" } func (x *ListTestsRequest) GetPageSize() int32 { if x != nil { return x.PageSize } return 0 } func (x *ListTestsRequest) GetPageToken() string { if x != nil { return x.PageToken } return "" } // The response for the ListTests method. type ListTestsResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The tests being returned. Tests []*Test `protobuf:"bytes,1,rep,name=tests,proto3" json:"tests,omitempty"` // The next page token, if any. // An empty value here means the last page has been reached. NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` } func (x *ListTestsResponse) Reset() { *x = ListTestsResponse{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ListTestsResponse) String() string { return protoimpl.X.MessageStringOf(x) } func (*ListTestsResponse) ProtoMessage() {} func (x *ListTestsResponse) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[11] 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 ListTestsResponse.ProtoReflect.Descriptor instead. func (*ListTestsResponse) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_testing_proto_rawDescGZIP(), []int{11} } func (x *ListTestsResponse) GetTests() []*Test { if x != nil { return x.Tests } return nil } func (x *ListTestsResponse) GetNextPageToken() string { if x != nil { return x.NextPageToken } return "" } // A TestRun is the result of running a Test. type TestRun struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The name of the test. // The tests/* portion of the names are hard-coded, and do not change // from session to session. Test string `protobuf:"bytes,1,opt,name=test,proto3" json:"test,omitempty"` // An issue found with the test run. If empty, this test run was successful. Issue *Issue `protobuf:"bytes,2,opt,name=issue,proto3" json:"issue,omitempty"` } func (x *TestRun) Reset() { *x = TestRun{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *TestRun) String() string { return protoimpl.X.MessageStringOf(x) } func (*TestRun) ProtoMessage() {} func (x *TestRun) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[12] 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 TestRun.ProtoReflect.Descriptor instead. func (*TestRun) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_testing_proto_rawDescGZIP(), []int{12} } func (x *TestRun) GetTest() string { if x != nil { return x.Test } return "" } func (x *TestRun) GetIssue() *Issue { if x != nil { return x.Issue } return nil } // Request message for deleting a test. type DeleteTestRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The test to be deleted. Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` } func (x *DeleteTestRequest) Reset() { *x = DeleteTestRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *DeleteTestRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*DeleteTestRequest) ProtoMessage() {} func (x *DeleteTestRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[13] 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 DeleteTestRequest.ProtoReflect.Descriptor instead. func (*DeleteTestRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_testing_proto_rawDescGZIP(), []int{13} } func (x *DeleteTestRequest) GetName() string { if x != nil { return x.Name } return "" } type VerifyTestRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The test to have an answer registered to it. Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // The answer from the test. Answer []byte `protobuf:"bytes,2,opt,name=answer,proto3" json:"answer,omitempty"` // The answers from the test if multiple are to be checked Answers [][]byte `protobuf:"bytes,3,rep,name=answers,proto3" json:"answers,omitempty"` } func (x *VerifyTestRequest) Reset() { *x = VerifyTestRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *VerifyTestRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*VerifyTestRequest) ProtoMessage() {} func (x *VerifyTestRequest) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[14] 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 VerifyTestRequest.ProtoReflect.Descriptor instead. func (*VerifyTestRequest) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_testing_proto_rawDescGZIP(), []int{14} } func (x *VerifyTestRequest) GetName() string { if x != nil { return x.Name } return "" } func (x *VerifyTestRequest) GetAnswer() []byte { if x != nil { return x.Answer } return nil } func (x *VerifyTestRequest) GetAnswers() [][]byte { if x != nil { return x.Answers } return nil } type VerifyTestResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // An issue if check answer was unsuccessful. This will be empty if the check answer succeeded. Issue *Issue `protobuf:"bytes,1,opt,name=issue,proto3" json:"issue,omitempty"` } func (x *VerifyTestResponse) Reset() { *x = VerifyTestResponse{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *VerifyTestResponse) String() string { return protoimpl.X.MessageStringOf(x) } func (*VerifyTestResponse) ProtoMessage() {} func (x *VerifyTestResponse) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[15] 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 VerifyTestResponse.ProtoReflect.Descriptor instead. func (*VerifyTestResponse) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_testing_proto_rawDescGZIP(), []int{15} } func (x *VerifyTestResponse) GetIssue() *Issue { if x != nil { return x.Issue } return nil } // A blueprint is an explicit definition of methods and requests that are needed // to be made to test this specific test case. Ideally this would be represented // by something more robust like CEL, but as of writing this, I am unsure if CEL // is ready. type Test_Blueprint struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The name of this blueprint. Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // A description of this blueprint. Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` // The initial request to trigger this test. Request *Test_Blueprint_Invocation `protobuf:"bytes,3,opt,name=request,proto3" json:"request,omitempty"` // An ordered list of method calls that can be called to trigger this test. AdditionalRequests []*Test_Blueprint_Invocation `protobuf:"bytes,4,rep,name=additional_requests,json=additionalRequests,proto3" json:"additional_requests,omitempty"` } func (x *Test_Blueprint) Reset() { *x = Test_Blueprint{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Test_Blueprint) String() string { return protoimpl.X.MessageStringOf(x) } func (*Test_Blueprint) ProtoMessage() {} func (x *Test_Blueprint) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[16] 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 Test_Blueprint.ProtoReflect.Descriptor instead. func (*Test_Blueprint) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_testing_proto_rawDescGZIP(), []int{8, 0} } func (x *Test_Blueprint) GetName() string { if x != nil { return x.Name } return "" } func (x *Test_Blueprint) GetDescription() string { if x != nil { return x.Description } return "" } func (x *Test_Blueprint) GetRequest() *Test_Blueprint_Invocation { if x != nil { return x.Request } return nil } func (x *Test_Blueprint) GetAdditionalRequests() []*Test_Blueprint_Invocation { if x != nil { return x.AdditionalRequests } return nil } // A message representing a method invocation. type Test_Blueprint_Invocation struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The fully qualified name of the showcase method to be invoked. Method string `protobuf:"bytes,1,opt,name=method,proto3" json:"method,omitempty"` // The request to be made if a specific request is necessary. SerializedRequest []byte `protobuf:"bytes,2,opt,name=serialized_request,json=serializedRequest,proto3" json:"serialized_request,omitempty"` } func (x *Test_Blueprint_Invocation) Reset() { *x = Test_Blueprint_Invocation{} if protoimpl.UnsafeEnabled { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Test_Blueprint_Invocation) String() string { return protoimpl.X.MessageStringOf(x) } func (*Test_Blueprint_Invocation) ProtoMessage() {} func (x *Test_Blueprint_Invocation) ProtoReflect() protoreflect.Message { mi := &file_google_showcase_v1beta1_testing_proto_msgTypes[17] 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 Test_Blueprint_Invocation.ProtoReflect.Descriptor instead. func (*Test_Blueprint_Invocation) Descriptor() ([]byte, []int) { return file_google_showcase_v1beta1_testing_proto_rawDescGZIP(), []int{8, 0, 0} } func (x *Test_Blueprint_Invocation) GetMethod() string { if x != nil { return x.Method } return "" } func (x *Test_Blueprint_Invocation) GetSerializedRequest() []byte { if x != nil { return x.SerializedRequest } return nil } var File_google_showcase_v1beta1_testing_proto protoreflect.FileDescriptor var file_google_showcase_v1beta1_testing_proto_rawDesc = []byte{ 0x0a, 0x25, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x17, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd8, 0x01, 0x0a, 0x07, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x42, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3b, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x56, 0x31, 0x5f, 0x4c, 0x41, 0x54, 0x45, 0x53, 0x54, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x56, 0x31, 0x5f, 0x30, 0x10, 0x02, 0x3a, 0x38, 0xea, 0x41, 0x35, 0x0a, 0x1f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x7b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x7d, 0x22, 0x52, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x4d, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x24, 0xfa, 0x41, 0x21, 0x0a, 0x1f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x51, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x7c, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x08, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x50, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x24, 0xfa, 0x41, 0x21, 0x0a, 0x1f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x50, 0x0a, 0x14, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x24, 0xfa, 0x41, 0x21, 0x0a, 0x1f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xef, 0x01, 0x0a, 0x15, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x35, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x3d, 0x0a, 0x09, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x72, 0x75, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x52, 0x75, 0x6e, 0x52, 0x08, 0x74, 0x65, 0x73, 0x74, 0x52, 0x75, 0x6e, 0x73, 0x22, 0x48, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x41, 0x53, 0x53, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x4e, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x03, 0x22, 0xb6, 0x06, 0x0a, 0x04, 0x54, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x5b, 0x0a, 0x11, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x2e, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x10, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x0a, 0x62, 0x6c, 0x75, 0x65, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6c, 0x75, 0x65, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x62, 0x6c, 0x75, 0x65, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, 0x1a, 0xa9, 0x03, 0x0a, 0x09, 0x42, 0x6c, 0x75, 0x65, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4c, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6c, 0x75, 0x65, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x63, 0x0a, 0x13, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6c, 0x75, 0x65, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x12, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x1a, 0x53, 0x0a, 0x0a, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x2d, 0x0a, 0x12, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x11, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x3a, 0x5e, 0xea, 0x41, 0x5b, 0x0a, 0x21, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x42, 0x6c, 0x75, 0x65, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x12, 0x36, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x7b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x7d, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2f, 0x7b, 0x74, 0x65, 0x73, 0x74, 0x7d, 0x2f, 0x62, 0x6c, 0x75, 0x65, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, 0x2f, 0x7b, 0x62, 0x6c, 0x75, 0x65, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x7d, 0x22, 0x62, 0x0a, 0x10, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x21, 0x0a, 0x1d, 0x45, 0x58, 0x50, 0x45, 0x43, 0x54, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4c, 0x45, 0x56, 0x45, 0x4c, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x51, 0x55, 0x49, 0x52, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x52, 0x45, 0x43, 0x4f, 0x4d, 0x4d, 0x45, 0x4e, 0x44, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x10, 0x03, 0x3a, 0x42, 0xea, 0x41, 0x3f, 0x0a, 0x1c, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x54, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x7b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x7d, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2f, 0x7b, 0x74, 0x65, 0x73, 0x74, 0x7d, 0x22, 0xb9, 0x02, 0x0a, 0x05, 0x49, 0x73, 0x73, 0x75, 0x65, 0x12, 0x37, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x49, 0x73, 0x73, 0x75, 0x65, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x43, 0x0a, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x49, 0x73, 0x73, 0x75, 0x65, 0x2e, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x52, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x4b, 0x49, 0x50, 0x50, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x49, 0x4e, 0x43, 0x4f, 0x52, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x52, 0x4d, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x03, 0x22, 0x3c, 0x0a, 0x08, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x45, 0x56, 0x45, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x22, 0x8c, 0x01, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x65, 0x73, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x24, 0xfa, 0x41, 0x21, 0x0a, 0x1f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x70, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x65, 0x73, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x05, 0x74, 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x52, 0x05, 0x74, 0x65, 0x73, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x76, 0x0a, 0x07, 0x54, 0x65, 0x73, 0x74, 0x52, 0x75, 0x6e, 0x12, 0x35, 0x0a, 0x04, 0x74, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x21, 0xfa, 0x41, 0x1e, 0x0a, 0x1c, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x54, 0x65, 0x73, 0x74, 0x52, 0x04, 0x74, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x05, 0x69, 0x73, 0x73, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x49, 0x73, 0x73, 0x75, 0x65, 0x52, 0x05, 0x69, 0x73, 0x73, 0x75, 0x65, 0x22, 0x4a, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x21, 0xfa, 0x41, 0x1e, 0x0a, 0x1c, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x54, 0x65, 0x73, 0x74, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x7c, 0x0a, 0x11, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x21, 0xfa, 0x41, 0x1e, 0x0a, 0x1c, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x54, 0x65, 0x73, 0x74, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x73, 0x22, 0x4a, 0x0a, 0x12, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x05, 0x69, 0x73, 0x73, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x49, 0x73, 0x73, 0x75, 0x65, 0x52, 0x05, 0x69, 0x73, 0x73, 0x75, 0x65, 0x32, 0xed, 0x08, 0x0a, 0x07, 0x54, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x84, 0x01, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x3a, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x11, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x7e, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x12, 0x1a, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0x86, 0x01, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x7a, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x2a, 0x1a, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0x99, 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x29, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x22, 0x21, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x8e, 0x01, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x65, 0x73, 0x74, 0x73, 0x12, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x65, 0x73, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x65, 0x73, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x12, 0x22, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x73, 0x12, 0x7c, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x12, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x2a, 0x22, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0x97, 0x01, 0x0a, 0x0a, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x54, 0x65, 0x73, 0x74, 0x12, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a, 0x22, 0x28, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x1a, 0x11, 0xca, 0x41, 0x0e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x3a, 0x37, 0x34, 0x36, 0x39, 0x42, 0x71, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x50, 0x01, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x67, 0x61, 0x70, 0x69, 0x63, 0x2d, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x65, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xea, 0x02, 0x19, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x3a, 0x3a, 0x53, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_google_showcase_v1beta1_testing_proto_rawDescOnce sync.Once file_google_showcase_v1beta1_testing_proto_rawDescData = file_google_showcase_v1beta1_testing_proto_rawDesc ) func file_google_showcase_v1beta1_testing_proto_rawDescGZIP() []byte { file_google_showcase_v1beta1_testing_proto_rawDescOnce.Do(func() { file_google_showcase_v1beta1_testing_proto_rawDescData = protoimpl.X.CompressGZIP(file_google_showcase_v1beta1_testing_proto_rawDescData) }) return file_google_showcase_v1beta1_testing_proto_rawDescData } var file_google_showcase_v1beta1_testing_proto_enumTypes = make([]protoimpl.EnumInfo, 5) var file_google_showcase_v1beta1_testing_proto_msgTypes = make([]protoimpl.MessageInfo, 18) var file_google_showcase_v1beta1_testing_proto_goTypes = []interface{}{ (Session_Version)(0), // 0: google.showcase.v1beta1.Session.Version (ReportSessionResponse_Result)(0), // 1: google.showcase.v1beta1.ReportSessionResponse.Result (Test_ExpectationLevel)(0), // 2: google.showcase.v1beta1.Test.ExpectationLevel (Issue_Type)(0), // 3: google.showcase.v1beta1.Issue.Type (Issue_Severity)(0), // 4: google.showcase.v1beta1.Issue.Severity (*Session)(nil), // 5: google.showcase.v1beta1.Session (*CreateSessionRequest)(nil), // 6: google.showcase.v1beta1.CreateSessionRequest (*GetSessionRequest)(nil), // 7: google.showcase.v1beta1.GetSessionRequest (*ListSessionsRequest)(nil), // 8: google.showcase.v1beta1.ListSessionsRequest (*ListSessionsResponse)(nil), // 9: google.showcase.v1beta1.ListSessionsResponse (*DeleteSessionRequest)(nil), // 10: google.showcase.v1beta1.DeleteSessionRequest (*ReportSessionRequest)(nil), // 11: google.showcase.v1beta1.ReportSessionRequest (*ReportSessionResponse)(nil), // 12: google.showcase.v1beta1.ReportSessionResponse (*Test)(nil), // 13: google.showcase.v1beta1.Test (*Issue)(nil), // 14: google.showcase.v1beta1.Issue (*ListTestsRequest)(nil), // 15: google.showcase.v1beta1.ListTestsRequest (*ListTestsResponse)(nil), // 16: google.showcase.v1beta1.ListTestsResponse (*TestRun)(nil), // 17: google.showcase.v1beta1.TestRun (*DeleteTestRequest)(nil), // 18: google.showcase.v1beta1.DeleteTestRequest (*VerifyTestRequest)(nil), // 19: google.showcase.v1beta1.VerifyTestRequest (*VerifyTestResponse)(nil), // 20: google.showcase.v1beta1.VerifyTestResponse (*Test_Blueprint)(nil), // 21: google.showcase.v1beta1.Test.Blueprint (*Test_Blueprint_Invocation)(nil), // 22: google.showcase.v1beta1.Test.Blueprint.Invocation (*emptypb.Empty)(nil), // 23: google.protobuf.Empty } var file_google_showcase_v1beta1_testing_proto_depIdxs = []int32{ 0, // 0: google.showcase.v1beta1.Session.version:type_name -> google.showcase.v1beta1.Session.Version 5, // 1: google.showcase.v1beta1.CreateSessionRequest.session:type_name -> google.showcase.v1beta1.Session 5, // 2: google.showcase.v1beta1.ListSessionsResponse.sessions:type_name -> google.showcase.v1beta1.Session 1, // 3: google.showcase.v1beta1.ReportSessionResponse.result:type_name -> google.showcase.v1beta1.ReportSessionResponse.Result 17, // 4: google.showcase.v1beta1.ReportSessionResponse.test_runs:type_name -> google.showcase.v1beta1.TestRun 2, // 5: google.showcase.v1beta1.Test.expectation_level:type_name -> google.showcase.v1beta1.Test.ExpectationLevel 21, // 6: google.showcase.v1beta1.Test.blueprints:type_name -> google.showcase.v1beta1.Test.Blueprint 3, // 7: google.showcase.v1beta1.Issue.type:type_name -> google.showcase.v1beta1.Issue.Type 4, // 8: google.showcase.v1beta1.Issue.severity:type_name -> google.showcase.v1beta1.Issue.Severity 13, // 9: google.showcase.v1beta1.ListTestsResponse.tests:type_name -> google.showcase.v1beta1.Test 14, // 10: google.showcase.v1beta1.TestRun.issue:type_name -> google.showcase.v1beta1.Issue 14, // 11: google.showcase.v1beta1.VerifyTestResponse.issue:type_name -> google.showcase.v1beta1.Issue 22, // 12: google.showcase.v1beta1.Test.Blueprint.request:type_name -> google.showcase.v1beta1.Test.Blueprint.Invocation 22, // 13: google.showcase.v1beta1.Test.Blueprint.additional_requests:type_name -> google.showcase.v1beta1.Test.Blueprint.Invocation 6, // 14: google.showcase.v1beta1.Testing.CreateSession:input_type -> google.showcase.v1beta1.CreateSessionRequest 7, // 15: google.showcase.v1beta1.Testing.GetSession:input_type -> google.showcase.v1beta1.GetSessionRequest 8, // 16: google.showcase.v1beta1.Testing.ListSessions:input_type -> google.showcase.v1beta1.ListSessionsRequest 10, // 17: google.showcase.v1beta1.Testing.DeleteSession:input_type -> google.showcase.v1beta1.DeleteSessionRequest 11, // 18: google.showcase.v1beta1.Testing.ReportSession:input_type -> google.showcase.v1beta1.ReportSessionRequest 15, // 19: google.showcase.v1beta1.Testing.ListTests:input_type -> google.showcase.v1beta1.ListTestsRequest 18, // 20: google.showcase.v1beta1.Testing.DeleteTest:input_type -> google.showcase.v1beta1.DeleteTestRequest 19, // 21: google.showcase.v1beta1.Testing.VerifyTest:input_type -> google.showcase.v1beta1.VerifyTestRequest 5, // 22: google.showcase.v1beta1.Testing.CreateSession:output_type -> google.showcase.v1beta1.Session 5, // 23: google.showcase.v1beta1.Testing.GetSession:output_type -> google.showcase.v1beta1.Session 9, // 24: google.showcase.v1beta1.Testing.ListSessions:output_type -> google.showcase.v1beta1.ListSessionsResponse 23, // 25: google.showcase.v1beta1.Testing.DeleteSession:output_type -> google.protobuf.Empty 12, // 26: google.showcase.v1beta1.Testing.ReportSession:output_type -> google.showcase.v1beta1.ReportSessionResponse 16, // 27: google.showcase.v1beta1.Testing.ListTests:output_type -> google.showcase.v1beta1.ListTestsResponse 23, // 28: google.showcase.v1beta1.Testing.DeleteTest:output_type -> google.protobuf.Empty 20, // 29: google.showcase.v1beta1.Testing.VerifyTest:output_type -> google.showcase.v1beta1.VerifyTestResponse 22, // [22:30] is the sub-list for method output_type 14, // [14:22] is the sub-list for method input_type 14, // [14:14] is the sub-list for extension type_name 14, // [14:14] is the sub-list for extension extendee 0, // [0:14] is the sub-list for field type_name } func init() { file_google_showcase_v1beta1_testing_proto_init() } func file_google_showcase_v1beta1_testing_proto_init() { if File_google_showcase_v1beta1_testing_proto != nil { return } if !protoimpl.UnsafeEnabled { file_google_showcase_v1beta1_testing_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Session); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_testing_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateSessionRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_testing_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetSessionRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_testing_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListSessionsRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_testing_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListSessionsResponse); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_testing_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DeleteSessionRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_testing_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ReportSessionRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_testing_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ReportSessionResponse); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_testing_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Test); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_testing_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Issue); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_testing_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListTestsRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_testing_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListTestsResponse); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_testing_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*TestRun); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_testing_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DeleteTestRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_testing_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*VerifyTestRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_testing_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*VerifyTestResponse); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_testing_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Test_Blueprint); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_showcase_v1beta1_testing_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Test_Blueprint_Invocation); 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_google_showcase_v1beta1_testing_proto_rawDesc, NumEnums: 5, NumMessages: 18, NumExtensions: 0, NumServices: 1, }, GoTypes: file_google_showcase_v1beta1_testing_proto_goTypes, DependencyIndexes: file_google_showcase_v1beta1_testing_proto_depIdxs, EnumInfos: file_google_showcase_v1beta1_testing_proto_enumTypes, MessageInfos: file_google_showcase_v1beta1_testing_proto_msgTypes, }.Build() File_google_showcase_v1beta1_testing_proto = out.File file_google_showcase_v1beta1_testing_proto_rawDesc = nil file_google_showcase_v1beta1_testing_proto_goTypes = nil file_google_showcase_v1beta1_testing_proto_depIdxs = nil } // Reference imports to suppress errors if they are not otherwise used. var _ context.Context var _ grpc.ClientConnInterface // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. const _ = grpc.SupportPackageIsVersion6 // TestingClient is the client API for Testing service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type TestingClient interface { // Creates a new testing session. // Adding this comment with special characters for comment formatting tests: // 1. (abra->kadabra->alakazam) // 2) [Nonsense][]: `pokemon/*/psychic/*` CreateSession(ctx context.Context, in *CreateSessionRequest, opts ...grpc.CallOption) (*Session, error) // Gets a testing session. GetSession(ctx context.Context, in *GetSessionRequest, opts ...grpc.CallOption) (*Session, error) // Lists the current test sessions. ListSessions(ctx context.Context, in *ListSessionsRequest, opts ...grpc.CallOption) (*ListSessionsResponse, error) // Delete a test session. DeleteSession(ctx context.Context, in *DeleteSessionRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) // Report on the status of a session. // This generates a report detailing which tests have been completed, // and an overall rollup. ReportSession(ctx context.Context, in *ReportSessionRequest, opts ...grpc.CallOption) (*ReportSessionResponse, error) // List the tests of a sessesion. ListTests(ctx context.Context, in *ListTestsRequest, opts ...grpc.CallOption) (*ListTestsResponse, error) // Explicitly decline to implement a test. // // This removes the test from subsequent `ListTests` calls, and // attempting to do the test will error. // // This method will error if attempting to delete a required test. DeleteTest(ctx context.Context, in *DeleteTestRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) // Register a response to a test. // // In cases where a test involves registering a final answer at the // end of the test, this method provides the means to do so. VerifyTest(ctx context.Context, in *VerifyTestRequest, opts ...grpc.CallOption) (*VerifyTestResponse, error) } type testingClient struct { cc grpc.ClientConnInterface } func NewTestingClient(cc grpc.ClientConnInterface) TestingClient { return &testingClient{cc} } func (c *testingClient) CreateSession(ctx context.Context, in *CreateSessionRequest, opts ...grpc.CallOption) (*Session, error) { out := new(Session) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Testing/CreateSession", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *testingClient) GetSession(ctx context.Context, in *GetSessionRequest, opts ...grpc.CallOption) (*Session, error) { out := new(Session) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Testing/GetSession", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *testingClient) ListSessions(ctx context.Context, in *ListSessionsRequest, opts ...grpc.CallOption) (*ListSessionsResponse, error) { out := new(ListSessionsResponse) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Testing/ListSessions", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *testingClient) DeleteSession(ctx context.Context, in *DeleteSessionRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Testing/DeleteSession", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *testingClient) ReportSession(ctx context.Context, in *ReportSessionRequest, opts ...grpc.CallOption) (*ReportSessionResponse, error) { out := new(ReportSessionResponse) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Testing/ReportSession", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *testingClient) ListTests(ctx context.Context, in *ListTestsRequest, opts ...grpc.CallOption) (*ListTestsResponse, error) { out := new(ListTestsResponse) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Testing/ListTests", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *testingClient) DeleteTest(ctx context.Context, in *DeleteTestRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Testing/DeleteTest", in, out, opts...) if err != nil { return nil, err } return out, nil } func (c *testingClient) VerifyTest(ctx context.Context, in *VerifyTestRequest, opts ...grpc.CallOption) (*VerifyTestResponse, error) { out := new(VerifyTestResponse) err := c.cc.Invoke(ctx, "/google.showcase.v1beta1.Testing/VerifyTest", in, out, opts...) if err != nil { return nil, err } return out, nil } // TestingServer is the server API for Testing service. type TestingServer interface { // Creates a new testing session. // Adding this comment with special characters for comment formatting tests: // 1. (abra->kadabra->alakazam) // 2) [Nonsense][]: `pokemon/*/psychic/*` CreateSession(context.Context, *CreateSessionRequest) (*Session, error) // Gets a testing session. GetSession(context.Context, *GetSessionRequest) (*Session, error) // Lists the current test sessions. ListSessions(context.Context, *ListSessionsRequest) (*ListSessionsResponse, error) // Delete a test session. DeleteSession(context.Context, *DeleteSessionRequest) (*emptypb.Empty, error) // Report on the status of a session. // This generates a report detailing which tests have been completed, // and an overall rollup. ReportSession(context.Context, *ReportSessionRequest) (*ReportSessionResponse, error) // List the tests of a sessesion. ListTests(context.Context, *ListTestsRequest) (*ListTestsResponse, error) // Explicitly decline to implement a test. // // This removes the test from subsequent `ListTests` calls, and // attempting to do the test will error. // // This method will error if attempting to delete a required test. DeleteTest(context.Context, *DeleteTestRequest) (*emptypb.Empty, error) // Register a response to a test. // // In cases where a test involves registering a final answer at the // end of the test, this method provides the means to do so. VerifyTest(context.Context, *VerifyTestRequest) (*VerifyTestResponse, error) } // UnimplementedTestingServer can be embedded to have forward compatible implementations. type UnimplementedTestingServer struct { } func (*UnimplementedTestingServer) CreateSession(context.Context, *CreateSessionRequest) (*Session, error) { return nil, status.Errorf(codes.Unimplemented, "method CreateSession not implemented") } func (*UnimplementedTestingServer) GetSession(context.Context, *GetSessionRequest) (*Session, error) { return nil, status.Errorf(codes.Unimplemented, "method GetSession not implemented") } func (*UnimplementedTestingServer) ListSessions(context.Context, *ListSessionsRequest) (*ListSessionsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListSessions not implemented") } func (*UnimplementedTestingServer) DeleteSession(context.Context, *DeleteSessionRequest) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method DeleteSession not implemented") } func (*UnimplementedTestingServer) ReportSession(context.Context, *ReportSessionRequest) (*ReportSessionResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ReportSession not implemented") } func (*UnimplementedTestingServer) ListTests(context.Context, *ListTestsRequest) (*ListTestsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListTests not implemented") } func (*UnimplementedTestingServer) DeleteTest(context.Context, *DeleteTestRequest) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method DeleteTest not implemented") } func (*UnimplementedTestingServer) VerifyTest(context.Context, *VerifyTestRequest) (*VerifyTestResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method VerifyTest not implemented") } func RegisterTestingServer(s *grpc.Server, srv TestingServer) { s.RegisterService(&_Testing_serviceDesc, srv) } func _Testing_CreateSession_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(CreateSessionRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(TestingServer).CreateSession(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Testing/CreateSession", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(TestingServer).CreateSession(ctx, req.(*CreateSessionRequest)) } return interceptor(ctx, in, info, handler) } func _Testing_GetSession_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetSessionRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(TestingServer).GetSession(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Testing/GetSession", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(TestingServer).GetSession(ctx, req.(*GetSessionRequest)) } return interceptor(ctx, in, info, handler) } func _Testing_ListSessions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ListSessionsRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(TestingServer).ListSessions(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Testing/ListSessions", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(TestingServer).ListSessions(ctx, req.(*ListSessionsRequest)) } return interceptor(ctx, in, info, handler) } func _Testing_DeleteSession_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(DeleteSessionRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(TestingServer).DeleteSession(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Testing/DeleteSession", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(TestingServer).DeleteSession(ctx, req.(*DeleteSessionRequest)) } return interceptor(ctx, in, info, handler) } func _Testing_ReportSession_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ReportSessionRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(TestingServer).ReportSession(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Testing/ReportSession", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(TestingServer).ReportSession(ctx, req.(*ReportSessionRequest)) } return interceptor(ctx, in, info, handler) } func _Testing_ListTests_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ListTestsRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(TestingServer).ListTests(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Testing/ListTests", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(TestingServer).ListTests(ctx, req.(*ListTestsRequest)) } return interceptor(ctx, in, info, handler) } func _Testing_DeleteTest_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(DeleteTestRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(TestingServer).DeleteTest(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Testing/DeleteTest", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(TestingServer).DeleteTest(ctx, req.(*DeleteTestRequest)) } return interceptor(ctx, in, info, handler) } func _Testing_VerifyTest_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(VerifyTestRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(TestingServer).VerifyTest(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/google.showcase.v1beta1.Testing/VerifyTest", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(TestingServer).VerifyTest(ctx, req.(*VerifyTestRequest)) } return interceptor(ctx, in, info, handler) } var _Testing_serviceDesc = grpc.ServiceDesc{ ServiceName: "google.showcase.v1beta1.Testing", HandlerType: (*TestingServer)(nil), Methods: []grpc.MethodDesc{ { MethodName: "CreateSession", Handler: _Testing_CreateSession_Handler, }, { MethodName: "GetSession", Handler: _Testing_GetSession_Handler, }, { MethodName: "ListSessions", Handler: _Testing_ListSessions_Handler, }, { MethodName: "DeleteSession", Handler: _Testing_DeleteSession_Handler, }, { MethodName: "ReportSession", Handler: _Testing_ReportSession_Handler, }, { MethodName: "ListTests", Handler: _Testing_ListTests_Handler, }, { MethodName: "DeleteTest", Handler: _Testing_DeleteTest_Handler, }, { MethodName: "VerifyTest", Handler: _Testing_VerifyTest_Handler, }, }, Streams: []grpc.StreamDesc{}, Metadata: "google/showcase/v1beta1/testing.proto", } ================================================ FILE: server/genrest/README.md ================================================ # server/genrest This directory contains auto-generated files used to implement a REST endpoint for Showcase services. ================================================ FILE: server/genrest/compliance.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // DO NOT EDIT. This is an auto-generated file containing the REST handlers // for service #0: "Compliance" (.google.showcase.v1beta1.Compliance). package genrest import ( "bytes" "context" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/googleapis/gapic-showcase/util/genrest/resttools" gmux "github.com/gorilla/mux" "io" "net/http" ) // HandleRepeatDataBody translates REST requests/responses on the wire to internal proto messages for RepeatDataBody // // Generated for HTTP binding pattern: POST "/v1beta1/repeat:body" func (backend *RESTBackend) HandleRepeatDataBody(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/repeat:body': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 0, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 0 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 0, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.RepeatRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/repeat:body") response, err := backend.ComplianceServer.RepeatDataBody(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleRepeatDataBodyInfo translates REST requests/responses on the wire to internal proto messages for RepeatDataBodyInfo // // Generated for HTTP binding pattern: POST "/v1beta1/repeat:bodyinfo" func (backend *RESTBackend) HandleRepeatDataBodyInfo(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/repeat:bodyinfo': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 0, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 0 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 0, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.RepeatRequest{} // Intentional: Field values in the URL path override those set in the body. var bodyField genprotopb.ComplianceData var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, &bodyField); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body into request field 'info': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } request.Info = &bodyField if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"info"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/repeat:bodyinfo") response, err := backend.ComplianceServer.RepeatDataBodyInfo(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleRepeatDataQuery translates REST requests/responses on the wire to internal proto messages for RepeatDataQuery // // Generated for HTTP binding pattern: GET "/v1beta1/repeat:query" func (backend *RESTBackend) HandleRepeatDataQuery(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/repeat:query': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 0, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 0 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 0, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.RepeatRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/repeat:query") response, err := backend.ComplianceServer.RepeatDataQuery(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleRepeatDataSimplePath translates REST requests/responses on the wire to internal proto messages for RepeatDataSimplePath // // Generated for HTTP binding pattern: GET "/v1beta1/repeat/{info.f_string}/{info.f_int32}/{info.f_double}/{info.f_bool}/{info.f_kingdom}:simplepath" func (backend *RESTBackend) HandleRepeatDataSimplePath(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/repeat/{info.f_string}/{info.f_int32}/{info.f_double}/{info.f_bool}/{info.f_kingdom}:simplepath': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 5, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 5 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 5, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.RepeatRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"info.f_string", "info.f_int32", "info.f_double", "info.f_bool", "info.f_kingdom"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/repeat/{info.f_string}/{info.f_int32}/{info.f_double}/{info.f_bool}/{info.f_kingdom}:simplepath") response, err := backend.ComplianceServer.RepeatDataSimplePath(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleRepeatDataPathResource translates REST requests/responses on the wire to internal proto messages for RepeatDataPathResource // // Generated for HTTP binding pattern: GET "/v1beta1/repeat/{info.f_string=first/*}/{info.f_child.f_string=second/*}/bool/{info.f_bool}:pathresource" func (backend *RESTBackend) HandleRepeatDataPathResource(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/repeat/{info.f_string=first/*}/{info.f_child.f_string=second/*}/bool/{info.f_bool}:pathresource': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 3, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 3 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 3, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.RepeatRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"info.f_string", "info.f_child.f_string", "info.f_bool"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/repeat/{info.f_string=first/*}/{info.f_child.f_string=second/*}/bool/{info.f_bool}:pathresource") response, err := backend.ComplianceServer.RepeatDataPathResource(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleRepeatDataPathResource_1 translates REST requests/responses on the wire to internal proto messages for RepeatDataPathResource // // Generated for HTTP binding pattern: GET "/v1beta1/repeat/{info.f_child.f_string=first/*}/{info.f_string=second/*}/bool/{info.f_bool}:childfirstpathresource" func (backend *RESTBackend) HandleRepeatDataPathResource_1(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/repeat/{info.f_child.f_string=first/*}/{info.f_string=second/*}/bool/{info.f_bool}:childfirstpathresource': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 3, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 3 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 3, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.RepeatRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"info.f_child.f_string", "info.f_string", "info.f_bool"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/repeat/{info.f_child.f_string=first/*}/{info.f_string=second/*}/bool/{info.f_bool}:childfirstpathresource") response, err := backend.ComplianceServer.RepeatDataPathResource(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleRepeatDataPathTrailingResource translates REST requests/responses on the wire to internal proto messages for RepeatDataPathTrailingResource // // Generated for HTTP binding pattern: GET "/v1beta1/repeat/{info.f_string=first/*}/{info.f_child.f_string=second/**}:pathtrailingresource" func (backend *RESTBackend) HandleRepeatDataPathTrailingResource(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/repeat/{info.f_string=first/*}/{info.f_child.f_string=second/**}:pathtrailingresource': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 2, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 2 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 2, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.RepeatRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"info.f_string", "info.f_child.f_string"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/repeat/{info.f_string=first/*}/{info.f_child.f_string=second/**}:pathtrailingresource") response, err := backend.ComplianceServer.RepeatDataPathTrailingResource(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleRepeatDataBodyPut translates REST requests/responses on the wire to internal proto messages for RepeatDataBodyPut // // Generated for HTTP binding pattern: PUT "/v1beta1/repeat:bodyput" func (backend *RESTBackend) HandleRepeatDataBodyPut(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/repeat:bodyput': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 0, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 0 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 0, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.RepeatRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/repeat:bodyput") response, err := backend.ComplianceServer.RepeatDataBodyPut(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleRepeatDataBodyPatch translates REST requests/responses on the wire to internal proto messages for RepeatDataBodyPatch // // Generated for HTTP binding pattern: PATCH "/v1beta1/repeat:bodypatch" func (backend *RESTBackend) HandleRepeatDataBodyPatch(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/repeat:bodypatch': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 0, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 0 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 0, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.RepeatRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/repeat:bodypatch") response, err := backend.ComplianceServer.RepeatDataBodyPatch(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleGetEnum translates REST requests/responses on the wire to internal proto messages for GetEnum // // Generated for HTTP binding pattern: GET "/v1beta1/compliance/enum" func (backend *RESTBackend) HandleGetEnum(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/compliance/enum': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 0, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 0 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 0, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.EnumRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/compliance/enum") response, err := backend.ComplianceServer.GetEnum(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleVerifyEnum translates REST requests/responses on the wire to internal proto messages for VerifyEnum // // Generated for HTTP binding pattern: POST "/v1beta1/compliance/enum" func (backend *RESTBackend) HandleVerifyEnum(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/compliance/enum': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 0, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 0 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 0, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.EnumResponse{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/compliance/enum") response, err := backend.ComplianceServer.VerifyEnum(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } ================================================ FILE: server/genrest/echo.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // DO NOT EDIT. This is an auto-generated file containing the REST handlers // for service #1: "Echo" (.google.showcase.v1beta1.Echo). package genrest import ( "bytes" "context" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/googleapis/gapic-showcase/util/genrest/resttools" gmux "github.com/gorilla/mux" "io" "net/http" ) // HandleEcho translates REST requests/responses on the wire to internal proto messages for Echo // // Generated for HTTP binding pattern: POST "/v1beta1/echo:echo" func (backend *RESTBackend) HandleEcho(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/echo:echo': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 0, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 0 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 0, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.EchoRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/echo:echo") response, err := backend.EchoServer.Echo(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleEchoErrorDetails translates REST requests/responses on the wire to internal proto messages for EchoErrorDetails // // Generated for HTTP binding pattern: POST "/v1beta1/echo:error-details" func (backend *RESTBackend) HandleEchoErrorDetails(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/echo:error-details': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 0, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 0 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 0, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.EchoErrorDetailsRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/echo:error-details") response, err := backend.EchoServer.EchoErrorDetails(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleFailEchoWithDetails translates REST requests/responses on the wire to internal proto messages for FailEchoWithDetails // // Generated for HTTP binding pattern: POST "/v1beta1/echo:failWithDetails" func (backend *RESTBackend) HandleFailEchoWithDetails(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/echo:failWithDetails': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 0, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 0 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 0, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.FailEchoWithDetailsRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/echo:failWithDetails") response, err := backend.EchoServer.FailEchoWithDetails(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleExpand translates REST requests/responses on the wire to internal proto messages for Expand // // Generated for HTTP binding pattern: POST "/v1beta1/echo:expand" func (backend *RESTBackend) HandleExpand(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/echo:expand': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 0, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 0 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 0, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.ExpandRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) serverStreamer, err := resttools.NewServerStreamer(w, resttools.ServerStreamingChunkSize) if err != nil { backend.Error(w, http.StatusInternalServerError, "server error: could not construct server streamer: %s", err.Error()) return } defer serverStreamer.End() streamer := &Echo_ExpandServer{serverStreamer} if err := backend.EchoServer.Expand(request, streamer); err != nil { backend.ReportGRPCError(w, err) } } // HandleCollect translates REST requests/responses on the wire to internal proto messages for Collect // // Generated for HTTP binding pattern: POST "/v1beta1/echo:collect" func (backend *RESTBackend) HandleCollect(w http.ResponseWriter, r *http.Request) { backend.Error(w, http.StatusNotImplemented, "client-streaming methods not implemented yet (request matched '/v1beta1/echo:collect': %q)", r.URL) } // HandlePagedExpand translates REST requests/responses on the wire to internal proto messages for PagedExpand // // Generated for HTTP binding pattern: POST "/v1beta1/echo:pagedExpand" func (backend *RESTBackend) HandlePagedExpand(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/echo:pagedExpand': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 0, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 0 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 0, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.PagedExpandRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/echo:pagedExpand") response, err := backend.EchoServer.PagedExpand(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandlePagedExpandLegacy translates REST requests/responses on the wire to internal proto messages for PagedExpandLegacy // // Generated for HTTP binding pattern: POST "/v1beta1/echo:pagedExpandLegacy" func (backend *RESTBackend) HandlePagedExpandLegacy(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/echo:pagedExpandLegacy': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 0, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 0 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 0, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.PagedExpandLegacyRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/echo:pagedExpandLegacy") response, err := backend.EchoServer.PagedExpandLegacy(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandlePagedExpandLegacyMapped translates REST requests/responses on the wire to internal proto messages for PagedExpandLegacyMapped // // Generated for HTTP binding pattern: POST "/v1beta1/echo:pagedExpandLegacyMapped" func (backend *RESTBackend) HandlePagedExpandLegacyMapped(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/echo:pagedExpandLegacyMapped': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 0, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 0 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 0, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.PagedExpandRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/echo:pagedExpandLegacyMapped") response, err := backend.EchoServer.PagedExpandLegacyMapped(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleWait translates REST requests/responses on the wire to internal proto messages for Wait // // Generated for HTTP binding pattern: POST "/v1beta1/echo:wait" func (backend *RESTBackend) HandleWait(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/echo:wait': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 0, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 0 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 0, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.WaitRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/echo:wait") response, err := backend.EchoServer.Wait(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleBlock translates REST requests/responses on the wire to internal proto messages for Block // // Generated for HTTP binding pattern: POST "/v1beta1/echo:block" func (backend *RESTBackend) HandleBlock(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/echo:block': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 0, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 0 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 0, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.BlockRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/echo:block") response, err := backend.EchoServer.Block(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // Echo_ExpandServer implements genprotopb.Echo_ExpandServer to provide server-side streaming over REST, returning all the // individual responses as part of a long JSON list. type Echo_ExpandServer struct { *resttools.ServerStreamer } // Send accumulates a response to be fetched later as part of response list returned over REST. func (streamer *Echo_ExpandServer) Send(response *genprotopb.EchoResponse) error { return streamer.ServerStreamer.Send(response) } ================================================ FILE: server/genrest/genrest.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // DO NOT EDIT. This is an auto-generated file registering the REST handlers. // for the various Showcase services. package genrest import ( "fmt" "net/http" "github.com/googleapis/gapic-showcase/server/services" "github.com/googleapis/gapic-showcase/util/genrest/resttools" gmux "github.com/gorilla/mux" "google.golang.org/grpc/status" ) type RESTBackend services.Backend func RegisterHandlers(router *gmux.Router, backend *services.Backend) { rest := (*RESTBackend)(backend) router.HandleFunc("/v1beta1/repeat:body", rest.HandleRepeatDataBody).Methods("POST") router.HandleFunc("/v1beta1/repeat:bodyinfo", rest.HandleRepeatDataBodyInfo).Methods("POST") router.HandleFunc("/v1beta1/repeat:query", rest.HandleRepeatDataQuery).Methods("GET") router.HandleFunc("/v1beta1/repeat/{info.fString:[^:]+}/{info.fInt32:[^:]+}/{info.fDouble:[^:]+}/{info.fBool:[^:]+}/{info.fKingdom:[^:]+}:simplepath", rest.HandleRepeatDataSimplePath).Methods("GET") router.HandleFunc("/v1beta1/repeat/{info.fString:first/[^:]+}/{info.fChild.fString:second/[^:]+}/bool/{info.fBool:[^:]+}:pathresource", rest.HandleRepeatDataPathResource).Methods("GET") router.HandleFunc("/v1beta1/repeat/{info.fChild.fString:first/[^:]+}/{info.fString:second/[^:]+}/bool/{info.fBool:[^:]+}:childfirstpathresource", rest.HandleRepeatDataPathResource_1).Methods("GET") router.HandleFunc("/v1beta1/repeat/{info.fString:first/[^:]+}/{info.fChild.fString:second/[^:]+}:pathtrailingresource", rest.HandleRepeatDataPathTrailingResource).Methods("GET") router.HandleFunc("/v1beta1/repeat:bodyput", rest.HandleRepeatDataBodyPut).Methods("PUT") router.HandleFunc("/v1beta1/repeat:bodypatch", rest.HandleRepeatDataBodyPatch).Methods("PATCH") router.HandleFunc("/v1beta1/repeat:bodypatch", rest.HandleRepeatDataBodyPatch).HeadersRegexp("X-HTTP-Method-Override", "^PATCH$").Methods("POST") router.HandleFunc("/v1beta1/compliance/enum", rest.HandleGetEnum).Methods("GET") router.HandleFunc("/v1beta1/compliance/enum", rest.HandleVerifyEnum).Methods("POST") router.HandleFunc("/v1beta1/echo:echo", rest.HandleEcho).Methods("POST") router.HandleFunc("/v1beta1/echo:error-details", rest.HandleEchoErrorDetails).Methods("POST") router.HandleFunc("/v1beta1/echo:failWithDetails", rest.HandleFailEchoWithDetails).Methods("POST") router.HandleFunc("/v1beta1/echo:expand", rest.HandleExpand).Methods("POST") router.HandleFunc("/v1beta1/echo:collect", rest.HandleCollect).Methods("POST") router.HandleFunc("/v1beta1/echo:pagedExpand", rest.HandlePagedExpand).Methods("POST") router.HandleFunc("/v1beta1/echo:pagedExpandLegacy", rest.HandlePagedExpandLegacy).Methods("POST") router.HandleFunc("/v1beta1/echo:pagedExpandLegacyMapped", rest.HandlePagedExpandLegacyMapped).Methods("POST") router.HandleFunc("/v1beta1/echo:wait", rest.HandleWait).Methods("POST") router.HandleFunc("/v1beta1/echo:block", rest.HandleBlock).Methods("POST") router.HandleFunc("/v1beta1/users", rest.HandleCreateUser).Methods("POST") router.HandleFunc("/v1beta1/{name:users/[^:]+}", rest.HandleGetUser).Methods("GET") router.HandleFunc("/v1beta1/{user.name:users/[^:]+}", rest.HandleUpdateUser).Methods("PATCH") router.HandleFunc("/v1beta1/{user.name:users/[^:]+}", rest.HandleUpdateUser).HeadersRegexp("X-HTTP-Method-Override", "^PATCH$").Methods("POST") router.HandleFunc("/v1beta1/{name:users/[^:]+}", rest.HandleDeleteUser).Methods("DELETE") router.HandleFunc("/v1beta1/users", rest.HandleListUsers).Methods("GET") router.HandleFunc("/v1beta1/rooms", rest.HandleCreateRoom).Methods("POST") router.HandleFunc("/v1beta1/{name:rooms/[^:]+}", rest.HandleGetRoom).Methods("GET") router.HandleFunc("/v1beta1/{room.name:rooms/[^:]+}", rest.HandleUpdateRoom).Methods("PATCH") router.HandleFunc("/v1beta1/{room.name:rooms/[^:]+}", rest.HandleUpdateRoom).HeadersRegexp("X-HTTP-Method-Override", "^PATCH$").Methods("POST") router.HandleFunc("/v1beta1/{name:rooms/[^:]+}", rest.HandleDeleteRoom).Methods("DELETE") router.HandleFunc("/v1beta1/rooms", rest.HandleListRooms).Methods("GET") router.HandleFunc("/v1beta1/{parent:rooms/[^:]+}/blurbs", rest.HandleCreateBlurb).Methods("POST") router.HandleFunc("/v1beta1/{parent:users/[^:]+/profile}/blurbs", rest.HandleCreateBlurb_1).Methods("POST") router.HandleFunc("/v1beta1/{name:rooms/[^:]+/blurbs/[^:]+}", rest.HandleGetBlurb).Methods("GET") router.HandleFunc("/v1beta1/{name:users/[^:]+/profile/blurbs/[^:]+}", rest.HandleGetBlurb_1).Methods("GET") router.HandleFunc("/v1beta1/{blurb.name:rooms/[^:]+/blurbs/[^:]+}", rest.HandleUpdateBlurb).Methods("PATCH") router.HandleFunc("/v1beta1/{blurb.name:rooms/[^:]+/blurbs/[^:]+}", rest.HandleUpdateBlurb).HeadersRegexp("X-HTTP-Method-Override", "^PATCH$").Methods("POST") router.HandleFunc("/v1beta1/{blurb.name:users/[^:]+/profile/blurbs/[^:]+}", rest.HandleUpdateBlurb_1).Methods("PATCH") router.HandleFunc("/v1beta1/{blurb.name:users/[^:]+/profile/blurbs/[^:]+}", rest.HandleUpdateBlurb_1).HeadersRegexp("X-HTTP-Method-Override", "^PATCH$").Methods("POST") router.HandleFunc("/v1beta1/{name:rooms/[^:]+/blurbs/[^:]+}", rest.HandleDeleteBlurb).Methods("DELETE") router.HandleFunc("/v1beta1/{name:users/[^:]+/profile/blurbs/[^:]+}", rest.HandleDeleteBlurb_1).Methods("DELETE") router.HandleFunc("/v1beta1/{parent:rooms/[^:]+}/blurbs", rest.HandleListBlurbs).Methods("GET") router.HandleFunc("/v1beta1/{parent:users/[^:]+/profile}/blurbs", rest.HandleListBlurbs_1).Methods("GET") router.HandleFunc("/v1beta1/{parent:rooms/[^:]+}/blurbs:search", rest.HandleSearchBlurbs).Methods("POST") router.HandleFunc("/v1beta1/{parent:users/[^:]+/profile}/blurbs:search", rest.HandleSearchBlurbs_1).Methods("POST") router.HandleFunc("/v1beta1/{name:rooms/[^:]+}/blurbs:stream", rest.HandleStreamBlurbs).Methods("POST") router.HandleFunc("/v1beta1/{name:users/[^:]+/profile}/blurbs:stream", rest.HandleStreamBlurbs_1).Methods("POST") router.HandleFunc("/v1beta1/{parent:rooms/[^:]+}/blurbs:send", rest.HandleSendBlurbs).Methods("POST") router.HandleFunc("/v1beta1/{parent:users/[^:]+/profile}/blurbs:send", rest.HandleSendBlurbs_1).Methods("POST") router.HandleFunc("/v1beta1/sequences", rest.HandleCreateSequence).Methods("POST") router.HandleFunc("/v1beta1/streamingSequences", rest.HandleCreateStreamingSequence).Methods("POST") router.HandleFunc("/v1beta1/{name:sequences/[^:]+/sequenceReport}", rest.HandleGetSequenceReport).Methods("GET") router.HandleFunc("/v1beta1/{name:streamingSequences/[^:]+/streamingSequenceReport}", rest.HandleGetStreamingSequenceReport).Methods("GET") router.HandleFunc("/v1beta1/{name:sequences/[^:]+}", rest.HandleAttemptSequence).Methods("POST") router.HandleFunc("/v1beta1/{name:streamingSequences/[^:]+}:stream", rest.HandleAttemptStreamingSequence).Methods("POST") router.HandleFunc("/v1beta1/sessions", rest.HandleCreateSession).Methods("POST") router.HandleFunc("/v1beta1/{name:sessions/[^:]+}", rest.HandleGetSession).Methods("GET") router.HandleFunc("/v1beta1/sessions", rest.HandleListSessions).Methods("GET") router.HandleFunc("/v1beta1/{name:sessions/[^:]+}", rest.HandleDeleteSession).Methods("DELETE") router.HandleFunc("/v1beta1/{name:sessions/[^:]+}:report", rest.HandleReportSession).Methods("POST") router.HandleFunc("/v1beta1/{parent:sessions/[^:]+}/tests", rest.HandleListTests).Methods("GET") router.HandleFunc("/v1beta1/{name:sessions/[^:]+/tests/[^:]+}", rest.HandleDeleteTest).Methods("DELETE") router.HandleFunc("/v1beta1/{name:sessions/[^:]+/tests/[^:]+}:check", rest.HandleVerifyTest).Methods("POST") router.HandleFunc("/v1beta1/{name:projects/[^:]+}/locations", rest.HandleListLocations).Methods("GET") router.HandleFunc("/v1beta1/{name:projects/[^:]+/locations/[^:]+}", rest.HandleGetLocation).Methods("GET") router.HandleFunc("/v1beta1/{resource:users/[^:]+}:setIamPolicy", rest.HandleSetIamPolicy).Methods("POST") router.HandleFunc("/v1beta1/{resource:rooms/[^:]+}:setIamPolicy", rest.HandleSetIamPolicy_1).Methods("POST") router.HandleFunc("/v1beta1/{resource:rooms/[^:]+/blurbs/[^:]+}:setIamPolicy", rest.HandleSetIamPolicy_2).Methods("POST") router.HandleFunc("/v1beta1/{resource:sequences/[^:]+}:setIamPolicy", rest.HandleSetIamPolicy_3).Methods("POST") router.HandleFunc("/v1beta1/{resource:users/[^:]+}:getIamPolicy", rest.HandleGetIamPolicy).Methods("GET") router.HandleFunc("/v1beta1/{resource:rooms/[^:]+}:getIamPolicy", rest.HandleGetIamPolicy_1).Methods("GET") router.HandleFunc("/v1beta1/{resource:rooms/[^:]+/blurbs/[^:]+}:getIamPolicy", rest.HandleGetIamPolicy_2).Methods("GET") router.HandleFunc("/v1beta1/{resource:sequences/[^:]+}:getIamPolicy", rest.HandleGetIamPolicy_3).Methods("GET") router.HandleFunc("/v1beta1/{resource:users/[^:]+}:testIamPermissions", rest.HandleTestIamPermissions).Methods("POST") router.HandleFunc("/v1beta1/{resource:rooms/[^:]+}:testIamPermissions", rest.HandleTestIamPermissions_1).Methods("POST") router.HandleFunc("/v1beta1/{resource:rooms/[^:]+/blurbs/[^:]+}:testIamPermissions", rest.HandleTestIamPermissions_2).Methods("POST") router.HandleFunc("/v1beta1/{resource:sequences/[^:]+}:testIamPermissions", rest.HandleTestIamPermissions_3).Methods("POST") router.HandleFunc("/v1beta1/operations", rest.HandleListOperations).Methods("GET") router.HandleFunc("/v1beta1/{name:operations/[^:]+}", rest.HandleGetOperation).Methods("GET") router.HandleFunc("/v1beta1/{name:operations/[^:]+}", rest.HandleDeleteOperation).Methods("DELETE") router.HandleFunc("/v1beta1/{name:operations/[^:]+}:cancel", rest.HandleCancelOperation).Methods("POST") router.PathPrefix("/").HandlerFunc(rest.catchAllHandler) } func (backend *RESTBackend) catchAllHandler(w http.ResponseWriter, r *http.Request) { backend.Error(w, http.StatusBadRequest, "unrecognized request: %s %q", r.Method, r.URL) } func (backend *RESTBackend) Error(w http.ResponseWriter, httpStatus int, format string, args ...interface{}) { message := fmt.Sprintf(format, args...) backend.ErrLog.Print(message) resttools.ErrorResponse(w, httpStatus, resttools.NoCodeGRPC, message) } func (backend *RESTBackend) ReportGRPCError(w http.ResponseWriter, err error) { st, ok := status.FromError(err) if !ok { backend.Error(w, http.StatusInternalServerError, "server error: %s", err.Error()) return } backend.ErrLog.Print(st.Message()) resttools.ErrorResponse(w, resttools.NoCodeHTTP, st.Code(), st.Message(), st.Details()...) } ================================================ FILE: server/genrest/iampolicy.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // DO NOT EDIT. This is an auto-generated file containing the REST handlers // for service #7: "IAMPolicy" (.google.iam.v1.IAMPolicy). package genrest import ( "bytes" iampbpb "cloud.google.com/go/iam/apiv1/iampb" "context" "github.com/googleapis/gapic-showcase/util/genrest/resttools" gmux "github.com/gorilla/mux" "io" "net/http" ) // HandleSetIamPolicy translates REST requests/responses on the wire to internal proto messages for SetIamPolicy // // Generated for HTTP binding pattern: POST "/v1beta1/{resource=users/*}:setIamPolicy" func (backend *RESTBackend) HandleSetIamPolicy(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{resource=users/*}:setIamPolicy': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &iampbpb.SetIamPolicyRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{resource=users/*}:setIamPolicy") response, err := backend.IAMPolicyServer.SetIamPolicy(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleSetIamPolicy_1 translates REST requests/responses on the wire to internal proto messages for SetIamPolicy // // Generated for HTTP binding pattern: POST "/v1beta1/{resource=rooms/*}:setIamPolicy" func (backend *RESTBackend) HandleSetIamPolicy_1(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{resource=rooms/*}:setIamPolicy': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &iampbpb.SetIamPolicyRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{resource=rooms/*}:setIamPolicy") response, err := backend.IAMPolicyServer.SetIamPolicy(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleSetIamPolicy_2 translates REST requests/responses on the wire to internal proto messages for SetIamPolicy // // Generated for HTTP binding pattern: POST "/v1beta1/{resource=rooms/*/blurbs/*}:setIamPolicy" func (backend *RESTBackend) HandleSetIamPolicy_2(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{resource=rooms/*/blurbs/*}:setIamPolicy': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &iampbpb.SetIamPolicyRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{resource=rooms/*/blurbs/*}:setIamPolicy") response, err := backend.IAMPolicyServer.SetIamPolicy(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleSetIamPolicy_3 translates REST requests/responses on the wire to internal proto messages for SetIamPolicy // // Generated for HTTP binding pattern: POST "/v1beta1/{resource=sequences/*}:setIamPolicy" func (backend *RESTBackend) HandleSetIamPolicy_3(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{resource=sequences/*}:setIamPolicy': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &iampbpb.SetIamPolicyRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{resource=sequences/*}:setIamPolicy") response, err := backend.IAMPolicyServer.SetIamPolicy(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleGetIamPolicy translates REST requests/responses on the wire to internal proto messages for GetIamPolicy // // Generated for HTTP binding pattern: GET "/v1beta1/{resource=users/*}:getIamPolicy" func (backend *RESTBackend) HandleGetIamPolicy(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{resource=users/*}:getIamPolicy': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &iampbpb.GetIamPolicyRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"resource"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{resource=users/*}:getIamPolicy") response, err := backend.IAMPolicyServer.GetIamPolicy(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleGetIamPolicy_1 translates REST requests/responses on the wire to internal proto messages for GetIamPolicy // // Generated for HTTP binding pattern: GET "/v1beta1/{resource=rooms/*}:getIamPolicy" func (backend *RESTBackend) HandleGetIamPolicy_1(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{resource=rooms/*}:getIamPolicy': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &iampbpb.GetIamPolicyRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"resource"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{resource=rooms/*}:getIamPolicy") response, err := backend.IAMPolicyServer.GetIamPolicy(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleGetIamPolicy_2 translates REST requests/responses on the wire to internal proto messages for GetIamPolicy // // Generated for HTTP binding pattern: GET "/v1beta1/{resource=rooms/*/blurbs/*}:getIamPolicy" func (backend *RESTBackend) HandleGetIamPolicy_2(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{resource=rooms/*/blurbs/*}:getIamPolicy': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &iampbpb.GetIamPolicyRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"resource"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{resource=rooms/*/blurbs/*}:getIamPolicy") response, err := backend.IAMPolicyServer.GetIamPolicy(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleGetIamPolicy_3 translates REST requests/responses on the wire to internal proto messages for GetIamPolicy // // Generated for HTTP binding pattern: GET "/v1beta1/{resource=sequences/*}:getIamPolicy" func (backend *RESTBackend) HandleGetIamPolicy_3(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{resource=sequences/*}:getIamPolicy': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &iampbpb.GetIamPolicyRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"resource"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{resource=sequences/*}:getIamPolicy") response, err := backend.IAMPolicyServer.GetIamPolicy(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleTestIamPermissions translates REST requests/responses on the wire to internal proto messages for TestIamPermissions // // Generated for HTTP binding pattern: POST "/v1beta1/{resource=users/*}:testIamPermissions" func (backend *RESTBackend) HandleTestIamPermissions(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{resource=users/*}:testIamPermissions': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &iampbpb.TestIamPermissionsRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{resource=users/*}:testIamPermissions") response, err := backend.IAMPolicyServer.TestIamPermissions(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleTestIamPermissions_1 translates REST requests/responses on the wire to internal proto messages for TestIamPermissions // // Generated for HTTP binding pattern: POST "/v1beta1/{resource=rooms/*}:testIamPermissions" func (backend *RESTBackend) HandleTestIamPermissions_1(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{resource=rooms/*}:testIamPermissions': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &iampbpb.TestIamPermissionsRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{resource=rooms/*}:testIamPermissions") response, err := backend.IAMPolicyServer.TestIamPermissions(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleTestIamPermissions_2 translates REST requests/responses on the wire to internal proto messages for TestIamPermissions // // Generated for HTTP binding pattern: POST "/v1beta1/{resource=rooms/*/blurbs/*}:testIamPermissions" func (backend *RESTBackend) HandleTestIamPermissions_2(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{resource=rooms/*/blurbs/*}:testIamPermissions': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &iampbpb.TestIamPermissionsRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{resource=rooms/*/blurbs/*}:testIamPermissions") response, err := backend.IAMPolicyServer.TestIamPermissions(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleTestIamPermissions_3 translates REST requests/responses on the wire to internal proto messages for TestIamPermissions // // Generated for HTTP binding pattern: POST "/v1beta1/{resource=sequences/*}:testIamPermissions" func (backend *RESTBackend) HandleTestIamPermissions_3(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{resource=sequences/*}:testIamPermissions': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &iampbpb.TestIamPermissionsRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{resource=sequences/*}:testIamPermissions") response, err := backend.IAMPolicyServer.TestIamPermissions(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } ================================================ FILE: server/genrest/identity.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // DO NOT EDIT. This is an auto-generated file containing the REST handlers // for service #2: "Identity" (.google.showcase.v1beta1.Identity). package genrest import ( "bytes" "context" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/googleapis/gapic-showcase/util/genrest/resttools" gmux "github.com/gorilla/mux" "io" "net/http" ) // HandleCreateUser translates REST requests/responses on the wire to internal proto messages for CreateUser // // Generated for HTTP binding pattern: POST "/v1beta1/users" func (backend *RESTBackend) HandleCreateUser(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/users': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 0, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 0 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 0, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.CreateUserRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/users") response, err := backend.IdentityServer.CreateUser(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleGetUser translates REST requests/responses on the wire to internal proto messages for GetUser // // Generated for HTTP binding pattern: GET "/v1beta1/{name=users/*}" func (backend *RESTBackend) HandleGetUser(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{name=users/*}': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.GetUserRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"name"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{name=users/*}") response, err := backend.IdentityServer.GetUser(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleUpdateUser translates REST requests/responses on the wire to internal proto messages for UpdateUser // // Generated for HTTP binding pattern: PATCH "/v1beta1/{user.name=users/*}" func (backend *RESTBackend) HandleUpdateUser(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{user.name=users/*}': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.UpdateUserRequest{} // Intentional: Field values in the URL path override those set in the body. var bodyField genprotopb.User var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, &bodyField); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body into request field 'user': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } request.User = &bodyField if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"user", "user.name"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{user.name=users/*}") response, err := backend.IdentityServer.UpdateUser(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleDeleteUser translates REST requests/responses on the wire to internal proto messages for DeleteUser // // Generated for HTTP binding pattern: DELETE "/v1beta1/{name=users/*}" func (backend *RESTBackend) HandleDeleteUser(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{name=users/*}': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.DeleteUserRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"name"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{name=users/*}") response, err := backend.IdentityServer.DeleteUser(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleListUsers translates REST requests/responses on the wire to internal proto messages for ListUsers // // Generated for HTTP binding pattern: GET "/v1beta1/users" func (backend *RESTBackend) HandleListUsers(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/users': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 0, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 0 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 0, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.ListUsersRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/users") response, err := backend.IdentityServer.ListUsers(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } ================================================ FILE: server/genrest/locations.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // DO NOT EDIT. This is an auto-generated file containing the REST handlers // for service #6: "Locations" (.google.cloud.location.Locations). package genrest import ( "context" "github.com/googleapis/gapic-showcase/util/genrest/resttools" gmux "github.com/gorilla/mux" locationpb "google.golang.org/genproto/googleapis/cloud/location" "net/http" ) // HandleListLocations translates REST requests/responses on the wire to internal proto messages for ListLocations // // Generated for HTTP binding pattern: GET "/v1beta1/{name=projects/*}/locations" func (backend *RESTBackend) HandleListLocations(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{name=projects/*}/locations': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &locationpb.ListLocationsRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"name"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{name=projects/*}/locations") response, err := backend.LocationsServer.ListLocations(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleGetLocation translates REST requests/responses on the wire to internal proto messages for GetLocation // // Generated for HTTP binding pattern: GET "/v1beta1/{name=projects/*/locations/*}" func (backend *RESTBackend) HandleGetLocation(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{name=projects/*/locations/*}': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &locationpb.GetLocationRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"name"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{name=projects/*/locations/*}") response, err := backend.LocationsServer.GetLocation(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } ================================================ FILE: server/genrest/messaging.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // DO NOT EDIT. This is an auto-generated file containing the REST handlers // for service #3: "Messaging" (.google.showcase.v1beta1.Messaging). package genrest import ( "bytes" "context" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/googleapis/gapic-showcase/util/genrest/resttools" gmux "github.com/gorilla/mux" "io" "net/http" ) // HandleCreateRoom translates REST requests/responses on the wire to internal proto messages for CreateRoom // // Generated for HTTP binding pattern: POST "/v1beta1/rooms" func (backend *RESTBackend) HandleCreateRoom(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/rooms': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 0, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 0 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 0, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.CreateRoomRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/rooms") response, err := backend.MessagingServer.CreateRoom(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleGetRoom translates REST requests/responses on the wire to internal proto messages for GetRoom // // Generated for HTTP binding pattern: GET "/v1beta1/{name=rooms/*}" func (backend *RESTBackend) HandleGetRoom(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{name=rooms/*}': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.GetRoomRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"name"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{name=rooms/*}") response, err := backend.MessagingServer.GetRoom(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleUpdateRoom translates REST requests/responses on the wire to internal proto messages for UpdateRoom // // Generated for HTTP binding pattern: PATCH "/v1beta1/{room.name=rooms/*}" func (backend *RESTBackend) HandleUpdateRoom(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{room.name=rooms/*}': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.UpdateRoomRequest{} // Intentional: Field values in the URL path override those set in the body. var bodyField genprotopb.Room var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, &bodyField); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body into request field 'room': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } request.Room = &bodyField if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"room", "room.name"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{room.name=rooms/*}") response, err := backend.MessagingServer.UpdateRoom(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleDeleteRoom translates REST requests/responses on the wire to internal proto messages for DeleteRoom // // Generated for HTTP binding pattern: DELETE "/v1beta1/{name=rooms/*}" func (backend *RESTBackend) HandleDeleteRoom(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{name=rooms/*}': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.DeleteRoomRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"name"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{name=rooms/*}") response, err := backend.MessagingServer.DeleteRoom(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleListRooms translates REST requests/responses on the wire to internal proto messages for ListRooms // // Generated for HTTP binding pattern: GET "/v1beta1/rooms" func (backend *RESTBackend) HandleListRooms(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/rooms': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 0, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 0 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 0, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.ListRoomsRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/rooms") response, err := backend.MessagingServer.ListRooms(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleCreateBlurb translates REST requests/responses on the wire to internal proto messages for CreateBlurb // // Generated for HTTP binding pattern: POST "/v1beta1/{parent=rooms/*}/blurbs" func (backend *RESTBackend) HandleCreateBlurb(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{parent=rooms/*}/blurbs': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.CreateBlurbRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{parent=rooms/*}/blurbs") response, err := backend.MessagingServer.CreateBlurb(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleCreateBlurb_1 translates REST requests/responses on the wire to internal proto messages for CreateBlurb // // Generated for HTTP binding pattern: POST "/v1beta1/{parent=users/*/profile}/blurbs" func (backend *RESTBackend) HandleCreateBlurb_1(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{parent=users/*/profile}/blurbs': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.CreateBlurbRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{parent=users/*/profile}/blurbs") response, err := backend.MessagingServer.CreateBlurb(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleGetBlurb translates REST requests/responses on the wire to internal proto messages for GetBlurb // // Generated for HTTP binding pattern: GET "/v1beta1/{name=rooms/*/blurbs/*}" func (backend *RESTBackend) HandleGetBlurb(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{name=rooms/*/blurbs/*}': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.GetBlurbRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"name"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{name=rooms/*/blurbs/*}") response, err := backend.MessagingServer.GetBlurb(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleGetBlurb_1 translates REST requests/responses on the wire to internal proto messages for GetBlurb // // Generated for HTTP binding pattern: GET "/v1beta1/{name=users/*/profile/blurbs/*}" func (backend *RESTBackend) HandleGetBlurb_1(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{name=users/*/profile/blurbs/*}': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.GetBlurbRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"name"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{name=users/*/profile/blurbs/*}") response, err := backend.MessagingServer.GetBlurb(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleUpdateBlurb translates REST requests/responses on the wire to internal proto messages for UpdateBlurb // // Generated for HTTP binding pattern: PATCH "/v1beta1/{blurb.name=rooms/*/blurbs/*}" func (backend *RESTBackend) HandleUpdateBlurb(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{blurb.name=rooms/*/blurbs/*}': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.UpdateBlurbRequest{} // Intentional: Field values in the URL path override those set in the body. var bodyField genprotopb.Blurb var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, &bodyField); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body into request field 'blurb': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } request.Blurb = &bodyField if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"blurb", "blurb.name"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{blurb.name=rooms/*/blurbs/*}") response, err := backend.MessagingServer.UpdateBlurb(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleUpdateBlurb_1 translates REST requests/responses on the wire to internal proto messages for UpdateBlurb // // Generated for HTTP binding pattern: PATCH "/v1beta1/{blurb.name=users/*/profile/blurbs/*}" func (backend *RESTBackend) HandleUpdateBlurb_1(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{blurb.name=users/*/profile/blurbs/*}': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.UpdateBlurbRequest{} // Intentional: Field values in the URL path override those set in the body. var bodyField genprotopb.Blurb var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, &bodyField); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body into request field 'blurb': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } request.Blurb = &bodyField if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"blurb", "blurb.name"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{blurb.name=users/*/profile/blurbs/*}") response, err := backend.MessagingServer.UpdateBlurb(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleDeleteBlurb translates REST requests/responses on the wire to internal proto messages for DeleteBlurb // // Generated for HTTP binding pattern: DELETE "/v1beta1/{name=rooms/*/blurbs/*}" func (backend *RESTBackend) HandleDeleteBlurb(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{name=rooms/*/blurbs/*}': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.DeleteBlurbRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"name"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{name=rooms/*/blurbs/*}") response, err := backend.MessagingServer.DeleteBlurb(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleDeleteBlurb_1 translates REST requests/responses on the wire to internal proto messages for DeleteBlurb // // Generated for HTTP binding pattern: DELETE "/v1beta1/{name=users/*/profile/blurbs/*}" func (backend *RESTBackend) HandleDeleteBlurb_1(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{name=users/*/profile/blurbs/*}': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.DeleteBlurbRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"name"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{name=users/*/profile/blurbs/*}") response, err := backend.MessagingServer.DeleteBlurb(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleListBlurbs translates REST requests/responses on the wire to internal proto messages for ListBlurbs // // Generated for HTTP binding pattern: GET "/v1beta1/{parent=rooms/*}/blurbs" func (backend *RESTBackend) HandleListBlurbs(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{parent=rooms/*}/blurbs': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.ListBlurbsRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"parent"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{parent=rooms/*}/blurbs") response, err := backend.MessagingServer.ListBlurbs(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleListBlurbs_1 translates REST requests/responses on the wire to internal proto messages for ListBlurbs // // Generated for HTTP binding pattern: GET "/v1beta1/{parent=users/*/profile}/blurbs" func (backend *RESTBackend) HandleListBlurbs_1(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{parent=users/*/profile}/blurbs': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.ListBlurbsRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"parent"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{parent=users/*/profile}/blurbs") response, err := backend.MessagingServer.ListBlurbs(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleSearchBlurbs translates REST requests/responses on the wire to internal proto messages for SearchBlurbs // // Generated for HTTP binding pattern: POST "/v1beta1/{parent=rooms/*}/blurbs:search" func (backend *RESTBackend) HandleSearchBlurbs(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{parent=rooms/*}/blurbs:search': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.SearchBlurbsRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{parent=rooms/*}/blurbs:search") response, err := backend.MessagingServer.SearchBlurbs(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleSearchBlurbs_1 translates REST requests/responses on the wire to internal proto messages for SearchBlurbs // // Generated for HTTP binding pattern: POST "/v1beta1/{parent=users/*/profile}/blurbs:search" func (backend *RESTBackend) HandleSearchBlurbs_1(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{parent=users/*/profile}/blurbs:search': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.SearchBlurbsRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"parent"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{parent=users/*/profile}/blurbs:search") response, err := backend.MessagingServer.SearchBlurbs(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleStreamBlurbs translates REST requests/responses on the wire to internal proto messages for StreamBlurbs // // Generated for HTTP binding pattern: POST "/v1beta1/{name=rooms/*}/blurbs:stream" func (backend *RESTBackend) HandleStreamBlurbs(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{name=rooms/*}/blurbs:stream': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.StreamBlurbsRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) serverStreamer, err := resttools.NewServerStreamer(w, resttools.ServerStreamingChunkSize) if err != nil { backend.Error(w, http.StatusInternalServerError, "server error: could not construct server streamer: %s", err.Error()) return } defer serverStreamer.End() streamer := &Messaging_StreamBlurbsServer{serverStreamer} if err := backend.MessagingServer.StreamBlurbs(request, streamer); err != nil { backend.ReportGRPCError(w, err) } } // HandleStreamBlurbs_1 translates REST requests/responses on the wire to internal proto messages for StreamBlurbs // // Generated for HTTP binding pattern: POST "/v1beta1/{name=users/*/profile}/blurbs:stream" func (backend *RESTBackend) HandleStreamBlurbs_1(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{name=users/*/profile}/blurbs:stream': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.StreamBlurbsRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) serverStreamer, err := resttools.NewServerStreamer(w, resttools.ServerStreamingChunkSize) if err != nil { backend.Error(w, http.StatusInternalServerError, "server error: could not construct server streamer: %s", err.Error()) return } defer serverStreamer.End() streamer := &Messaging_StreamBlurbsServer{serverStreamer} if err := backend.MessagingServer.StreamBlurbs(request, streamer); err != nil { backend.ReportGRPCError(w, err) } } // HandleSendBlurbs translates REST requests/responses on the wire to internal proto messages for SendBlurbs // // Generated for HTTP binding pattern: POST "/v1beta1/{parent=rooms/*}/blurbs:send" func (backend *RESTBackend) HandleSendBlurbs(w http.ResponseWriter, r *http.Request) { backend.Error(w, http.StatusNotImplemented, "client-streaming methods not implemented yet (request matched '/v1beta1/{parent=rooms/*}/blurbs:send': %q)", r.URL) } // HandleSendBlurbs_1 translates REST requests/responses on the wire to internal proto messages for SendBlurbs // // Generated for HTTP binding pattern: POST "/v1beta1/{parent=users/*/profile}/blurbs:send" func (backend *RESTBackend) HandleSendBlurbs_1(w http.ResponseWriter, r *http.Request) { backend.Error(w, http.StatusNotImplemented, "client-streaming methods not implemented yet (request matched '/v1beta1/{parent=users/*/profile}/blurbs:send': %q)", r.URL) } // Messaging_StreamBlurbsServer implements genprotopb.Messaging_StreamBlurbsServer to provide server-side streaming over REST, returning all the // individual responses as part of a long JSON list. type Messaging_StreamBlurbsServer struct { *resttools.ServerStreamer } // Send accumulates a response to be fetched later as part of response list returned over REST. func (streamer *Messaging_StreamBlurbsServer) Send(response *genprotopb.StreamBlurbsResponse) error { return streamer.ServerStreamer.Send(response) } ================================================ FILE: server/genrest/operations.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // DO NOT EDIT. This is an auto-generated file containing the REST handlers // for service #8: "Operations" (.google.longrunning.Operations). package genrest import ( longrunningpbpb "cloud.google.com/go/longrunning/autogen/longrunningpb" "context" "github.com/googleapis/gapic-showcase/util/genrest/resttools" gmux "github.com/gorilla/mux" "net/http" ) // HandleListOperations translates REST requests/responses on the wire to internal proto messages for ListOperations // // Generated for HTTP binding pattern: GET "/v1beta1/operations" func (backend *RESTBackend) HandleListOperations(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/operations': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 0, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 0 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 0, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &longrunningpbpb.ListOperationsRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/operations") response, err := backend.OperationsServer.ListOperations(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleGetOperation translates REST requests/responses on the wire to internal proto messages for GetOperation // // Generated for HTTP binding pattern: GET "/v1beta1/{name=operations/**}" func (backend *RESTBackend) HandleGetOperation(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{name=operations/**}': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &longrunningpbpb.GetOperationRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"name"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{name=operations/**}") response, err := backend.OperationsServer.GetOperation(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleDeleteOperation translates REST requests/responses on the wire to internal proto messages for DeleteOperation // // Generated for HTTP binding pattern: DELETE "/v1beta1/{name=operations/**}" func (backend *RESTBackend) HandleDeleteOperation(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{name=operations/**}': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &longrunningpbpb.DeleteOperationRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"name"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{name=operations/**}") response, err := backend.OperationsServer.DeleteOperation(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleCancelOperation translates REST requests/responses on the wire to internal proto messages for CancelOperation // // Generated for HTTP binding pattern: POST "/v1beta1/{name=operations/**}:cancel" func (backend *RESTBackend) HandleCancelOperation(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{name=operations/**}:cancel': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &longrunningpbpb.CancelOperationRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"name"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{name=operations/**}:cancel") response, err := backend.OperationsServer.CancelOperation(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } ================================================ FILE: server/genrest/sequenceservice.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // DO NOT EDIT. This is an auto-generated file containing the REST handlers // for service #4: "SequenceService" (.google.showcase.v1beta1.SequenceService). package genrest import ( "bytes" "context" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/googleapis/gapic-showcase/util/genrest/resttools" gmux "github.com/gorilla/mux" "io" "net/http" ) // HandleCreateSequence translates REST requests/responses on the wire to internal proto messages for CreateSequence // // Generated for HTTP binding pattern: POST "/v1beta1/sequences" func (backend *RESTBackend) HandleCreateSequence(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/sequences': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 0, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 0 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 0, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.CreateSequenceRequest{} // Intentional: Field values in the URL path override those set in the body. var bodyField genprotopb.Sequence var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, &bodyField); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body into request field 'sequence': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } request.Sequence = &bodyField if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"sequence"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/sequences") response, err := backend.SequenceServiceServer.CreateSequence(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleCreateStreamingSequence translates REST requests/responses on the wire to internal proto messages for CreateStreamingSequence // // Generated for HTTP binding pattern: POST "/v1beta1/streamingSequences" func (backend *RESTBackend) HandleCreateStreamingSequence(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/streamingSequences': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 0, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 0 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 0, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.CreateStreamingSequenceRequest{} // Intentional: Field values in the URL path override those set in the body. var bodyField genprotopb.StreamingSequence var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, &bodyField); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body into request field 'streaming_sequence': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } request.StreamingSequence = &bodyField if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"streaming_sequence"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/streamingSequences") response, err := backend.SequenceServiceServer.CreateStreamingSequence(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleGetSequenceReport translates REST requests/responses on the wire to internal proto messages for GetSequenceReport // // Generated for HTTP binding pattern: GET "/v1beta1/{name=sequences/*/sequenceReport}" func (backend *RESTBackend) HandleGetSequenceReport(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{name=sequences/*/sequenceReport}': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.GetSequenceReportRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"name"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{name=sequences/*/sequenceReport}") response, err := backend.SequenceServiceServer.GetSequenceReport(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleGetStreamingSequenceReport translates REST requests/responses on the wire to internal proto messages for GetStreamingSequenceReport // // Generated for HTTP binding pattern: GET "/v1beta1/{name=streamingSequences/*/streamingSequenceReport}" func (backend *RESTBackend) HandleGetStreamingSequenceReport(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{name=streamingSequences/*/streamingSequenceReport}': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.GetStreamingSequenceReportRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"name"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{name=streamingSequences/*/streamingSequenceReport}") response, err := backend.SequenceServiceServer.GetStreamingSequenceReport(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleAttemptSequence translates REST requests/responses on the wire to internal proto messages for AttemptSequence // // Generated for HTTP binding pattern: POST "/v1beta1/{name=sequences/*}" func (backend *RESTBackend) HandleAttemptSequence(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{name=sequences/*}': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.AttemptSequenceRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{name=sequences/*}") response, err := backend.SequenceServiceServer.AttemptSequence(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleAttemptStreamingSequence translates REST requests/responses on the wire to internal proto messages for AttemptStreamingSequence // // Generated for HTTP binding pattern: POST "/v1beta1/{name=streamingSequences/*}:stream" func (backend *RESTBackend) HandleAttemptStreamingSequence(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{name=streamingSequences/*}:stream': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.AttemptStreamingSequenceRequest{} // Intentional: Field values in the URL path override those set in the body. var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, request); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body params '*': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if len(queryParams) > 0 { backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %v", queryParams) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) serverStreamer, err := resttools.NewServerStreamer(w, resttools.ServerStreamingChunkSize) if err != nil { backend.Error(w, http.StatusInternalServerError, "server error: could not construct server streamer: %s", err.Error()) return } defer serverStreamer.End() streamer := &SequenceService_AttemptStreamingSequenceServer{serverStreamer} if err := backend.SequenceServiceServer.AttemptStreamingSequence(request, streamer); err != nil { backend.ReportGRPCError(w, err) } } // SequenceService_AttemptStreamingSequenceServer implements genprotopb.SequenceService_AttemptStreamingSequenceServer to provide server-side streaming over REST, returning all the // individual responses as part of a long JSON list. type SequenceService_AttemptStreamingSequenceServer struct { *resttools.ServerStreamer } // Send accumulates a response to be fetched later as part of response list returned over REST. func (streamer *SequenceService_AttemptStreamingSequenceServer) Send(response *genprotopb.AttemptStreamingSequenceResponse) error { return streamer.ServerStreamer.Send(response) } ================================================ FILE: server/genrest/showcase-rest-sample-response.txt ================================================ Generated via "google.golang.org/protobuf/compiler/protogen" via ProtoModel! Files: google/showcase/v1beta1/compliance.proto google/showcase/v1beta1/echo.proto google/showcase/v1beta1/identity.proto google/showcase/v1beta1/messaging.proto google/showcase/v1beta1/rest_error.proto google/showcase/v1beta1/sequence.proto google/showcase/v1beta1/testing.proto Proto Model: Compliance (.google.showcase.v1beta1.Compliance): .google.showcase.v1beta1.Compliance.RepeatDataBody[0] : POST: "/v1beta1/repeat:body" .google.showcase.v1beta1.Compliance.RepeatDataBodyInfo[0] : POST: "/v1beta1/repeat:bodyinfo" .google.showcase.v1beta1.Compliance.RepeatDataQuery[0] : GET: "/v1beta1/repeat:query" .google.showcase.v1beta1.Compliance.RepeatDataSimplePath[0] : GET: "/v1beta1/repeat/{info.f_string}/{info.f_int32}/{info.f_double}/{info.f_bool}/{info.f_kingdom}:simplepath" .google.showcase.v1beta1.Compliance.RepeatDataPathResource[0] : GET: "/v1beta1/repeat/{info.f_string=first/*}/{info.f_child.f_string=second/*}/bool/{info.f_bool}:pathresource" .google.showcase.v1beta1.Compliance.RepeatDataPathResource[1] : GET: "/v1beta1/repeat/{info.f_child.f_string=first/*}/{info.f_string=second/*}/bool/{info.f_bool}:childfirstpathresource" .google.showcase.v1beta1.Compliance.RepeatDataPathTrailingResource[0] : GET: "/v1beta1/repeat/{info.f_string=first/*}/{info.f_child.f_string=second/**}:pathtrailingresource" .google.showcase.v1beta1.Compliance.RepeatDataBodyPut[0] : PUT: "/v1beta1/repeat:bodyput" .google.showcase.v1beta1.Compliance.RepeatDataBodyPatch[0] : PATCH: "/v1beta1/repeat:bodypatch" .google.showcase.v1beta1.Compliance.GetEnum[0] : GET: "/v1beta1/compliance/enum" .google.showcase.v1beta1.Compliance.VerifyEnum[0] : POST: "/v1beta1/compliance/enum" Echo (.google.showcase.v1beta1.Echo): .google.showcase.v1beta1.Echo.Echo[0] : POST: "/v1beta1/echo:echo" .google.showcase.v1beta1.Echo.EchoErrorDetails[0] : POST: "/v1beta1/echo:error-details" .google.showcase.v1beta1.Echo.FailEchoWithDetails[0] : POST: "/v1beta1/echo:failWithDetails" .google.showcase.v1beta1.Echo.Expand[0] : POST: "/v1beta1/echo:expand" .google.showcase.v1beta1.Echo.Collect[0] : POST: "/v1beta1/echo:collect" .google.showcase.v1beta1.Echo.PagedExpand[0] : POST: "/v1beta1/echo:pagedExpand" .google.showcase.v1beta1.Echo.PagedExpandLegacy[0] : POST: "/v1beta1/echo:pagedExpandLegacy" .google.showcase.v1beta1.Echo.PagedExpandLegacyMapped[0] : POST: "/v1beta1/echo:pagedExpandLegacyMapped" .google.showcase.v1beta1.Echo.Wait[0] : POST: "/v1beta1/echo:wait" .google.showcase.v1beta1.Echo.Block[0] : POST: "/v1beta1/echo:block" Identity (.google.showcase.v1beta1.Identity): .google.showcase.v1beta1.Identity.CreateUser[0] : POST: "/v1beta1/users" .google.showcase.v1beta1.Identity.GetUser[0] : GET: "/v1beta1/{name=users/*}" .google.showcase.v1beta1.Identity.UpdateUser[0] : PATCH: "/v1beta1/{user.name=users/*}" .google.showcase.v1beta1.Identity.DeleteUser[0] : DELETE: "/v1beta1/{name=users/*}" .google.showcase.v1beta1.Identity.ListUsers[0] : GET: "/v1beta1/users" Messaging (.google.showcase.v1beta1.Messaging): .google.showcase.v1beta1.Messaging.CreateRoom[0] : POST: "/v1beta1/rooms" .google.showcase.v1beta1.Messaging.GetRoom[0] : GET: "/v1beta1/{name=rooms/*}" .google.showcase.v1beta1.Messaging.UpdateRoom[0] : PATCH: "/v1beta1/{room.name=rooms/*}" .google.showcase.v1beta1.Messaging.DeleteRoom[0] : DELETE: "/v1beta1/{name=rooms/*}" .google.showcase.v1beta1.Messaging.ListRooms[0] : GET: "/v1beta1/rooms" .google.showcase.v1beta1.Messaging.CreateBlurb[0] : POST: "/v1beta1/{parent=rooms/*}/blurbs" .google.showcase.v1beta1.Messaging.CreateBlurb[1] : POST: "/v1beta1/{parent=users/*/profile}/blurbs" .google.showcase.v1beta1.Messaging.GetBlurb[0] : GET: "/v1beta1/{name=rooms/*/blurbs/*}" .google.showcase.v1beta1.Messaging.GetBlurb[1] : GET: "/v1beta1/{name=users/*/profile/blurbs/*}" .google.showcase.v1beta1.Messaging.UpdateBlurb[0] : PATCH: "/v1beta1/{blurb.name=rooms/*/blurbs/*}" .google.showcase.v1beta1.Messaging.UpdateBlurb[1] : PATCH: "/v1beta1/{blurb.name=users/*/profile/blurbs/*}" .google.showcase.v1beta1.Messaging.DeleteBlurb[0] : DELETE: "/v1beta1/{name=rooms/*/blurbs/*}" .google.showcase.v1beta1.Messaging.DeleteBlurb[1] : DELETE: "/v1beta1/{name=users/*/profile/blurbs/*}" .google.showcase.v1beta1.Messaging.ListBlurbs[0] : GET: "/v1beta1/{parent=rooms/*}/blurbs" .google.showcase.v1beta1.Messaging.ListBlurbs[1] : GET: "/v1beta1/{parent=users/*/profile}/blurbs" .google.showcase.v1beta1.Messaging.SearchBlurbs[0] : POST: "/v1beta1/{parent=rooms/*}/blurbs:search" .google.showcase.v1beta1.Messaging.SearchBlurbs[1] : POST: "/v1beta1/{parent=users/*/profile}/blurbs:search" .google.showcase.v1beta1.Messaging.StreamBlurbs[0] : POST: "/v1beta1/{name=rooms/*}/blurbs:stream" .google.showcase.v1beta1.Messaging.StreamBlurbs[1] : POST: "/v1beta1/{name=users/*/profile}/blurbs:stream" .google.showcase.v1beta1.Messaging.SendBlurbs[0] : POST: "/v1beta1/{parent=rooms/*}/blurbs:send" .google.showcase.v1beta1.Messaging.SendBlurbs[1] : POST: "/v1beta1/{parent=users/*/profile}/blurbs:send" SequenceService (.google.showcase.v1beta1.SequenceService): .google.showcase.v1beta1.SequenceService.CreateSequence[0] : POST: "/v1beta1/sequences" .google.showcase.v1beta1.SequenceService.CreateStreamingSequence[0] : POST: "/v1beta1/streamingSequences" .google.showcase.v1beta1.SequenceService.GetSequenceReport[0] : GET: "/v1beta1/{name=sequences/*/sequenceReport}" .google.showcase.v1beta1.SequenceService.GetStreamingSequenceReport[0] : GET: "/v1beta1/{name=streamingSequences/*/streamingSequenceReport}" .google.showcase.v1beta1.SequenceService.AttemptSequence[0] : POST: "/v1beta1/{name=sequences/*}" .google.showcase.v1beta1.SequenceService.AttemptStreamingSequence[0] : POST: "/v1beta1/{name=streamingSequences/*}:stream" Testing (.google.showcase.v1beta1.Testing): .google.showcase.v1beta1.Testing.CreateSession[0] : POST: "/v1beta1/sessions" .google.showcase.v1beta1.Testing.GetSession[0] : GET: "/v1beta1/{name=sessions/*}" .google.showcase.v1beta1.Testing.ListSessions[0] : GET: "/v1beta1/sessions" .google.showcase.v1beta1.Testing.DeleteSession[0] : DELETE: "/v1beta1/{name=sessions/*}" .google.showcase.v1beta1.Testing.ReportSession[0] : POST: "/v1beta1/{name=sessions/*}:report" .google.showcase.v1beta1.Testing.ListTests[0] : GET: "/v1beta1/{parent=sessions/*}/tests" .google.showcase.v1beta1.Testing.DeleteTest[0] : DELETE: "/v1beta1/{name=sessions/*/tests/*}" .google.showcase.v1beta1.Testing.VerifyTest[0] : POST: "/v1beta1/{name=sessions/*/tests/*}:check" Locations (.google.cloud.location.Locations): .google.cloud.location.Locations.ListLocations[0] : GET: "/v1beta1/{name=projects/*}/locations" .google.cloud.location.Locations.GetLocation[0] : GET: "/v1beta1/{name=projects/*/locations/*}" IAMPolicy (.google.iam.v1.IAMPolicy): .google.iam.v1.IAMPolicy.SetIamPolicy[0] : POST: "/v1beta1/{resource=users/*}:setIamPolicy" .google.iam.v1.IAMPolicy.SetIamPolicy[1] : POST: "/v1beta1/{resource=rooms/*}:setIamPolicy" .google.iam.v1.IAMPolicy.SetIamPolicy[2] : POST: "/v1beta1/{resource=rooms/*/blurbs/*}:setIamPolicy" .google.iam.v1.IAMPolicy.SetIamPolicy[3] : POST: "/v1beta1/{resource=sequences/*}:setIamPolicy" .google.iam.v1.IAMPolicy.GetIamPolicy[0] : GET: "/v1beta1/{resource=users/*}:getIamPolicy" .google.iam.v1.IAMPolicy.GetIamPolicy[1] : GET: "/v1beta1/{resource=rooms/*}:getIamPolicy" .google.iam.v1.IAMPolicy.GetIamPolicy[2] : GET: "/v1beta1/{resource=rooms/*/blurbs/*}:getIamPolicy" .google.iam.v1.IAMPolicy.GetIamPolicy[3] : GET: "/v1beta1/{resource=sequences/*}:getIamPolicy" .google.iam.v1.IAMPolicy.TestIamPermissions[0] : POST: "/v1beta1/{resource=users/*}:testIamPermissions" .google.iam.v1.IAMPolicy.TestIamPermissions[1] : POST: "/v1beta1/{resource=rooms/*}:testIamPermissions" .google.iam.v1.IAMPolicy.TestIamPermissions[2] : POST: "/v1beta1/{resource=rooms/*/blurbs/*}:testIamPermissions" .google.iam.v1.IAMPolicy.TestIamPermissions[3] : POST: "/v1beta1/{resource=sequences/*}:testIamPermissions" Operations (.google.longrunning.Operations): .google.longrunning.Operations.ListOperations[0] : GET: "/v1beta1/operations" .google.longrunning.Operations.GetOperation[0] : GET: "/v1beta1/{name=operations/**}" .google.longrunning.Operations.DeleteOperation[0] : DELETE: "/v1beta1/{name=operations/**}" .google.longrunning.Operations.CancelOperation[0] : POST: "/v1beta1/{name=operations/**}:cancel" GoModel ---------------------------------------- Shim "Compliance" (.google.showcase.v1beta1.Compliance) Imports: genprotopb: "github.com/googleapis/gapic-showcase/server/genproto" "github.com/googleapis/gapic-showcase/server/genproto" Handlers (11): GET /v1beta1/repeat:query func RepeatDataQuery(request genprotopb.RepeatRequest) (response genprotopb.RepeatResponse) {} ["/" "v1beta1" "/" "repeat" ":" "query"] GET /v1beta1/compliance/enum func GetEnum(request genprotopb.EnumRequest) (response genprotopb.EnumResponse) {} ["/" "v1beta1" "/" "compliance" "/" "enum"] GET /v1beta1/repeat/{info.f_child.f_string=first/*}/{info.f_string=second/*}/bool/{info.f_bool}:childfirstpathresource func RepeatDataPathResource(request genprotopb.RepeatRequest) (response genprotopb.RepeatResponse) {} ["/" "v1beta1" "/" "repeat" "/" {info.f_child.f_string = ["first" "/" *]} "/" {info.f_string = ["second" "/" *]} "/" "bool" "/" {info.f_bool = []} ":" "childfirstpathresource"] GET /v1beta1/repeat/{info.f_string=first/*}/{info.f_child.f_string=second/**}:pathtrailingresource func RepeatDataPathTrailingResource(request genprotopb.RepeatRequest) (response genprotopb.RepeatResponse) {} ["/" "v1beta1" "/" "repeat" "/" {info.f_string = ["first" "/" *]} "/" {info.f_child.f_string = ["second" "/" **]} ":" "pathtrailingresource"] GET /v1beta1/repeat/{info.f_string=first/*}/{info.f_child.f_string=second/*}/bool/{info.f_bool}:pathresource func RepeatDataPathResource(request genprotopb.RepeatRequest) (response genprotopb.RepeatResponse) {} ["/" "v1beta1" "/" "repeat" "/" {info.f_string = ["first" "/" *]} "/" {info.f_child.f_string = ["second" "/" *]} "/" "bool" "/" {info.f_bool = []} ":" "pathresource"] GET /v1beta1/repeat/{info.f_string}/{info.f_int32}/{info.f_double}/{info.f_bool}/{info.f_kingdom}:simplepath func RepeatDataSimplePath(request genprotopb.RepeatRequest) (response genprotopb.RepeatResponse) {} ["/" "v1beta1" "/" "repeat" "/" {info.f_string = []} "/" {info.f_int32 = []} "/" {info.f_double = []} "/" {info.f_bool = []} "/" {info.f_kingdom = []} ":" "simplepath"] PUT /v1beta1/repeat:bodyput func RepeatDataBodyPut(request genprotopb.RepeatRequest) (response genprotopb.RepeatResponse) {} ["/" "v1beta1" "/" "repeat" ":" "bodyput"] POST /v1beta1/repeat:body func RepeatDataBody(request genprotopb.RepeatRequest) (response genprotopb.RepeatResponse) {} ["/" "v1beta1" "/" "repeat" ":" "body"] POST /v1beta1/compliance/enum func VerifyEnum(request genprotopb.EnumResponse) (response genprotopb.EnumResponse) {} ["/" "v1beta1" "/" "compliance" "/" "enum"] POST /v1beta1/repeat:bodyinfo func RepeatDataBodyInfo(request genprotopb.RepeatRequest) (response genprotopb.RepeatResponse) {} ["/" "v1beta1" "/" "repeat" ":" "bodyinfo"] PATCH /v1beta1/repeat:bodypatch func RepeatDataBodyPatch(request genprotopb.RepeatRequest) (response genprotopb.RepeatResponse) {} ["/" "v1beta1" "/" "repeat" ":" "bodypatch"] ---------------------------------------- Shim "Echo" (.google.showcase.v1beta1.Echo) Imports: genprotopb: "github.com/googleapis/gapic-showcase/server/genproto" "github.com/googleapis/gapic-showcase/server/genproto" longrunningpbpb: "cloud.google.com/go/longrunning/autogen/longrunningpb" "cloud.google.com/go/longrunning/autogen/longrunningpb" Handlers (10): POST /v1beta1/echo:echo func Echo(request genprotopb.EchoRequest) (response genprotopb.EchoResponse) {} ["/" "v1beta1" "/" "echo" ":" "echo"] POST /v1beta1/echo:wait func Wait(request genprotopb.WaitRequest) (response longrunningpbpb.Operation) {} ["/" "v1beta1" "/" "echo" ":" "wait"] POST /v1beta1/echo:block func Block(request genprotopb.BlockRequest) (response genprotopb.BlockResponse) {} ["/" "v1beta1" "/" "echo" ":" "block"] POST /v1beta1/echo:expand func Expand(request genprotopb.ExpandRequest) (response genprotopb.EchoResponse) {} ["/" "v1beta1" "/" "echo" ":" "expand"] POST /v1beta1/echo:collect func Collect(request genprotopb.EchoRequest) (response genprotopb.EchoResponse) {} ["/" "v1beta1" "/" "echo" ":" "collect"] POST /v1beta1/echo:pagedExpand func PagedExpand(request genprotopb.PagedExpandRequest) (response genprotopb.PagedExpandResponse) {} ["/" "v1beta1" "/" "echo" ":" "pagedExpand"] POST /v1beta1/echo:error-details func EchoErrorDetails(request genprotopb.EchoErrorDetailsRequest) (response genprotopb.EchoErrorDetailsResponse) {} ["/" "v1beta1" "/" "echo" ":" "error-details"] POST /v1beta1/echo:failWithDetails func FailEchoWithDetails(request genprotopb.FailEchoWithDetailsRequest) (response genprotopb.FailEchoWithDetailsResponse) {} ["/" "v1beta1" "/" "echo" ":" "failWithDetails"] POST /v1beta1/echo:pagedExpandLegacy func PagedExpandLegacy(request genprotopb.PagedExpandLegacyRequest) (response genprotopb.PagedExpandResponse) {} ["/" "v1beta1" "/" "echo" ":" "pagedExpandLegacy"] POST /v1beta1/echo:pagedExpandLegacyMapped func PagedExpandLegacyMapped(request genprotopb.PagedExpandRequest) (response genprotopb.PagedExpandLegacyMappedResponse) {} ["/" "v1beta1" "/" "echo" ":" "pagedExpandLegacyMapped"] ---------------------------------------- Shim "Identity" (.google.showcase.v1beta1.Identity) Imports: emptypbpb: "google.golang.org/protobuf/types/known/emptypb" "google.golang.org/protobuf/types/known/emptypb" genprotopb: "github.com/googleapis/gapic-showcase/server/genproto" "github.com/googleapis/gapic-showcase/server/genproto" Handlers (5): GET /v1beta1/users func ListUsers(request genprotopb.ListUsersRequest) (response genprotopb.ListUsersResponse) {} ["/" "v1beta1" "/" "users"] GET /v1beta1/{name=users/*} func GetUser(request genprotopb.GetUserRequest) (response genprotopb.User) {} ["/" "v1beta1" "/" {name = ["users" "/" *]}] POST /v1beta1/users func CreateUser(request genprotopb.CreateUserRequest) (response genprotopb.User) {} ["/" "v1beta1" "/" "users"] PATCH /v1beta1/{user.name=users/*} func UpdateUser(request genprotopb.UpdateUserRequest) (response genprotopb.User) {} ["/" "v1beta1" "/" {user.name = ["users" "/" *]}] DELETE /v1beta1/{name=users/*} func DeleteUser(request genprotopb.DeleteUserRequest) (response emptypbpb.Empty) {} ["/" "v1beta1" "/" {name = ["users" "/" *]}] ---------------------------------------- Shim "Messaging" (.google.showcase.v1beta1.Messaging) Imports: emptypbpb: "google.golang.org/protobuf/types/known/emptypb" "google.golang.org/protobuf/types/known/emptypb" genprotopb: "github.com/googleapis/gapic-showcase/server/genproto" "github.com/googleapis/gapic-showcase/server/genproto" longrunningpbpb: "cloud.google.com/go/longrunning/autogen/longrunningpb" "cloud.google.com/go/longrunning/autogen/longrunningpb" Handlers (21): GET /v1beta1/rooms func ListRooms(request genprotopb.ListRoomsRequest) (response genprotopb.ListRoomsResponse) {} ["/" "v1beta1" "/" "rooms"] GET /v1beta1/{name=rooms/*} func GetRoom(request genprotopb.GetRoomRequest) (response genprotopb.Room) {} ["/" "v1beta1" "/" {name = ["rooms" "/" *]}] GET /v1beta1/{name=rooms/*/blurbs/*} func GetBlurb(request genprotopb.GetBlurbRequest) (response genprotopb.Blurb) {} ["/" "v1beta1" "/" {name = ["rooms" "/" * "/" "blurbs" "/" *]}] GET /v1beta1/{parent=rooms/*}/blurbs func ListBlurbs(request genprotopb.ListBlurbsRequest) (response genprotopb.ListBlurbsResponse) {} ["/" "v1beta1" "/" {parent = ["rooms" "/" *]} "/" "blurbs"] GET /v1beta1/{name=users/*/profile/blurbs/*} func GetBlurb(request genprotopb.GetBlurbRequest) (response genprotopb.Blurb) {} ["/" "v1beta1" "/" {name = ["users" "/" * "/" "profile" "/" "blurbs" "/" *]}] GET /v1beta1/{parent=users/*/profile}/blurbs func ListBlurbs(request genprotopb.ListBlurbsRequest) (response genprotopb.ListBlurbsResponse) {} ["/" "v1beta1" "/" {parent = ["users" "/" * "/" "profile"]} "/" "blurbs"] POST /v1beta1/rooms func CreateRoom(request genprotopb.CreateRoomRequest) (response genprotopb.Room) {} ["/" "v1beta1" "/" "rooms"] POST /v1beta1/{parent=rooms/*}/blurbs func CreateBlurb(request genprotopb.CreateBlurbRequest) (response genprotopb.Blurb) {} ["/" "v1beta1" "/" {parent = ["rooms" "/" *]} "/" "blurbs"] POST /v1beta1/{name=rooms/*}/blurbs:stream func StreamBlurbs(request genprotopb.StreamBlurbsRequest) (response genprotopb.StreamBlurbsResponse) {} ["/" "v1beta1" "/" {name = ["rooms" "/" *]} "/" "blurbs" ":" "stream"] POST /v1beta1/{parent=rooms/*}/blurbs:send func SendBlurbs(request genprotopb.CreateBlurbRequest) (response genprotopb.SendBlurbsResponse) {} ["/" "v1beta1" "/" {parent = ["rooms" "/" *]} "/" "blurbs" ":" "send"] POST /v1beta1/{parent=rooms/*}/blurbs:search func SearchBlurbs(request genprotopb.SearchBlurbsRequest) (response longrunningpbpb.Operation) {} ["/" "v1beta1" "/" {parent = ["rooms" "/" *]} "/" "blurbs" ":" "search"] POST /v1beta1/{parent=users/*/profile}/blurbs func CreateBlurb(request genprotopb.CreateBlurbRequest) (response genprotopb.Blurb) {} ["/" "v1beta1" "/" {parent = ["users" "/" * "/" "profile"]} "/" "blurbs"] POST /v1beta1/{name=users/*/profile}/blurbs:stream func StreamBlurbs(request genprotopb.StreamBlurbsRequest) (response genprotopb.StreamBlurbsResponse) {} ["/" "v1beta1" "/" {name = ["users" "/" * "/" "profile"]} "/" "blurbs" ":" "stream"] POST /v1beta1/{parent=users/*/profile}/blurbs:send func SendBlurbs(request genprotopb.CreateBlurbRequest) (response genprotopb.SendBlurbsResponse) {} ["/" "v1beta1" "/" {parent = ["users" "/" * "/" "profile"]} "/" "blurbs" ":" "send"] POST /v1beta1/{parent=users/*/profile}/blurbs:search func SearchBlurbs(request genprotopb.SearchBlurbsRequest) (response longrunningpbpb.Operation) {} ["/" "v1beta1" "/" {parent = ["users" "/" * "/" "profile"]} "/" "blurbs" ":" "search"] PATCH /v1beta1/{room.name=rooms/*} func UpdateRoom(request genprotopb.UpdateRoomRequest) (response genprotopb.Room) {} ["/" "v1beta1" "/" {room.name = ["rooms" "/" *]}] PATCH /v1beta1/{blurb.name=rooms/*/blurbs/*} func UpdateBlurb(request genprotopb.UpdateBlurbRequest) (response genprotopb.Blurb) {} ["/" "v1beta1" "/" {blurb.name = ["rooms" "/" * "/" "blurbs" "/" *]}] PATCH /v1beta1/{blurb.name=users/*/profile/blurbs/*} func UpdateBlurb(request genprotopb.UpdateBlurbRequest) (response genprotopb.Blurb) {} ["/" "v1beta1" "/" {blurb.name = ["users" "/" * "/" "profile" "/" "blurbs" "/" *]}] DELETE /v1beta1/{name=rooms/*} func DeleteRoom(request genprotopb.DeleteRoomRequest) (response emptypbpb.Empty) {} ["/" "v1beta1" "/" {name = ["rooms" "/" *]}] DELETE /v1beta1/{name=rooms/*/blurbs/*} func DeleteBlurb(request genprotopb.DeleteBlurbRequest) (response emptypbpb.Empty) {} ["/" "v1beta1" "/" {name = ["rooms" "/" * "/" "blurbs" "/" *]}] DELETE /v1beta1/{name=users/*/profile/blurbs/*} func DeleteBlurb(request genprotopb.DeleteBlurbRequest) (response emptypbpb.Empty) {} ["/" "v1beta1" "/" {name = ["users" "/" * "/" "profile" "/" "blurbs" "/" *]}] ---------------------------------------- Shim "SequenceService" (.google.showcase.v1beta1.SequenceService) Imports: emptypbpb: "google.golang.org/protobuf/types/known/emptypb" "google.golang.org/protobuf/types/known/emptypb" genprotopb: "github.com/googleapis/gapic-showcase/server/genproto" "github.com/googleapis/gapic-showcase/server/genproto" Handlers (6): GET /v1beta1/{name=sequences/*/sequenceReport} func GetSequenceReport(request genprotopb.GetSequenceReportRequest) (response genprotopb.SequenceReport) {} ["/" "v1beta1" "/" {name = ["sequences" "/" * "/" "sequenceReport"]}] GET /v1beta1/{name=streamingSequences/*/streamingSequenceReport} func GetStreamingSequenceReport(request genprotopb.GetStreamingSequenceReportRequest) (response genprotopb.StreamingSequenceReport) {} ["/" "v1beta1" "/" {name = ["streamingSequences" "/" * "/" "streamingSequenceReport"]}] POST /v1beta1/sequences func CreateSequence(request genprotopb.CreateSequenceRequest) (response genprotopb.Sequence) {} ["/" "v1beta1" "/" "sequences"] POST /v1beta1/streamingSequences func CreateStreamingSequence(request genprotopb.CreateStreamingSequenceRequest) (response genprotopb.StreamingSequence) {} ["/" "v1beta1" "/" "streamingSequences"] POST /v1beta1/{name=sequences/*} func AttemptSequence(request genprotopb.AttemptSequenceRequest) (response emptypbpb.Empty) {} ["/" "v1beta1" "/" {name = ["sequences" "/" *]}] POST /v1beta1/{name=streamingSequences/*}:stream func AttemptStreamingSequence(request genprotopb.AttemptStreamingSequenceRequest) (response genprotopb.AttemptStreamingSequenceResponse) {} ["/" "v1beta1" "/" {name = ["streamingSequences" "/" *]} ":" "stream"] ---------------------------------------- Shim "Testing" (.google.showcase.v1beta1.Testing) Imports: emptypbpb: "google.golang.org/protobuf/types/known/emptypb" "google.golang.org/protobuf/types/known/emptypb" genprotopb: "github.com/googleapis/gapic-showcase/server/genproto" "github.com/googleapis/gapic-showcase/server/genproto" Handlers (8): GET /v1beta1/sessions func ListSessions(request genprotopb.ListSessionsRequest) (response genprotopb.ListSessionsResponse) {} ["/" "v1beta1" "/" "sessions"] GET /v1beta1/{name=sessions/*} func GetSession(request genprotopb.GetSessionRequest) (response genprotopb.Session) {} ["/" "v1beta1" "/" {name = ["sessions" "/" *]}] GET /v1beta1/{parent=sessions/*}/tests func ListTests(request genprotopb.ListTestsRequest) (response genprotopb.ListTestsResponse) {} ["/" "v1beta1" "/" {parent = ["sessions" "/" *]} "/" "tests"] POST /v1beta1/sessions func CreateSession(request genprotopb.CreateSessionRequest) (response genprotopb.Session) {} ["/" "v1beta1" "/" "sessions"] POST /v1beta1/{name=sessions/*}:report func ReportSession(request genprotopb.ReportSessionRequest) (response genprotopb.ReportSessionResponse) {} ["/" "v1beta1" "/" {name = ["sessions" "/" *]} ":" "report"] POST /v1beta1/{name=sessions/*/tests/*}:check func VerifyTest(request genprotopb.VerifyTestRequest) (response genprotopb.VerifyTestResponse) {} ["/" "v1beta1" "/" {name = ["sessions" "/" * "/" "tests" "/" *]} ":" "check"] DELETE /v1beta1/{name=sessions/*} func DeleteSession(request genprotopb.DeleteSessionRequest) (response emptypbpb.Empty) {} ["/" "v1beta1" "/" {name = ["sessions" "/" *]}] DELETE /v1beta1/{name=sessions/*/tests/*} func DeleteTest(request genprotopb.DeleteTestRequest) (response emptypbpb.Empty) {} ["/" "v1beta1" "/" {name = ["sessions" "/" * "/" "tests" "/" *]}] ---------------------------------------- Shim "Locations" (.google.cloud.location.Locations) Imports: locationpb: "google.golang.org/genproto/googleapis/cloud/location" "google.golang.org/genproto/googleapis/cloud/location" Handlers (2): GET /v1beta1/{name=projects/*}/locations func ListLocations(request locationpb.ListLocationsRequest) (response locationpb.ListLocationsResponse) {} ["/" "v1beta1" "/" {name = ["projects" "/" *]} "/" "locations"] GET /v1beta1/{name=projects/*/locations/*} func GetLocation(request locationpb.GetLocationRequest) (response locationpb.Location) {} ["/" "v1beta1" "/" {name = ["projects" "/" * "/" "locations" "/" *]}] ---------------------------------------- Shim "IAMPolicy" (.google.iam.v1.IAMPolicy) Imports: iampbpb: "cloud.google.com/go/iam/apiv1/iampb" "cloud.google.com/go/iam/apiv1/iampb" Handlers (12): GET /v1beta1/{resource=rooms/*}:getIamPolicy func GetIamPolicy(request iampbpb.GetIamPolicyRequest) (response iampbpb.Policy) {} ["/" "v1beta1" "/" {resource = ["rooms" "/" *]} ":" "getIamPolicy"] GET /v1beta1/{resource=users/*}:getIamPolicy func GetIamPolicy(request iampbpb.GetIamPolicyRequest) (response iampbpb.Policy) {} ["/" "v1beta1" "/" {resource = ["users" "/" *]} ":" "getIamPolicy"] GET /v1beta1/{resource=sequences/*}:getIamPolicy func GetIamPolicy(request iampbpb.GetIamPolicyRequest) (response iampbpb.Policy) {} ["/" "v1beta1" "/" {resource = ["sequences" "/" *]} ":" "getIamPolicy"] GET /v1beta1/{resource=rooms/*/blurbs/*}:getIamPolicy func GetIamPolicy(request iampbpb.GetIamPolicyRequest) (response iampbpb.Policy) {} ["/" "v1beta1" "/" {resource = ["rooms" "/" * "/" "blurbs" "/" *]} ":" "getIamPolicy"] POST /v1beta1/{resource=rooms/*}:setIamPolicy func SetIamPolicy(request iampbpb.SetIamPolicyRequest) (response iampbpb.Policy) {} ["/" "v1beta1" "/" {resource = ["rooms" "/" *]} ":" "setIamPolicy"] POST /v1beta1/{resource=users/*}:setIamPolicy func SetIamPolicy(request iampbpb.SetIamPolicyRequest) (response iampbpb.Policy) {} ["/" "v1beta1" "/" {resource = ["users" "/" *]} ":" "setIamPolicy"] POST /v1beta1/{resource=sequences/*}:setIamPolicy func SetIamPolicy(request iampbpb.SetIamPolicyRequest) (response iampbpb.Policy) {} ["/" "v1beta1" "/" {resource = ["sequences" "/" *]} ":" "setIamPolicy"] POST /v1beta1/{resource=rooms/*}:testIamPermissions func TestIamPermissions(request iampbpb.TestIamPermissionsRequest) (response iampbpb.TestIamPermissionsResponse) {} ["/" "v1beta1" "/" {resource = ["rooms" "/" *]} ":" "testIamPermissions"] POST /v1beta1/{resource=users/*}:testIamPermissions func TestIamPermissions(request iampbpb.TestIamPermissionsRequest) (response iampbpb.TestIamPermissionsResponse) {} ["/" "v1beta1" "/" {resource = ["users" "/" *]} ":" "testIamPermissions"] POST /v1beta1/{resource=rooms/*/blurbs/*}:setIamPolicy func SetIamPolicy(request iampbpb.SetIamPolicyRequest) (response iampbpb.Policy) {} ["/" "v1beta1" "/" {resource = ["rooms" "/" * "/" "blurbs" "/" *]} ":" "setIamPolicy"] POST /v1beta1/{resource=rooms/*/blurbs/*}:testIamPermissions func TestIamPermissions(request iampbpb.TestIamPermissionsRequest) (response iampbpb.TestIamPermissionsResponse) {} ["/" "v1beta1" "/" {resource = ["rooms" "/" * "/" "blurbs" "/" *]} ":" "testIamPermissions"] POST /v1beta1/{resource=sequences/*}:testIamPermissions func TestIamPermissions(request iampbpb.TestIamPermissionsRequest) (response iampbpb.TestIamPermissionsResponse) {} ["/" "v1beta1" "/" {resource = ["sequences" "/" *]} ":" "testIamPermissions"] ---------------------------------------- Shim "Operations" (.google.longrunning.Operations) Imports: emptypbpb: "google.golang.org/protobuf/types/known/emptypb" "google.golang.org/protobuf/types/known/emptypb" longrunningpbpb: "cloud.google.com/go/longrunning/autogen/longrunningpb" "cloud.google.com/go/longrunning/autogen/longrunningpb" Handlers (4): GET /v1beta1/operations func ListOperations(request longrunningpbpb.ListOperationsRequest) (response longrunningpbpb.ListOperationsResponse) {} ["/" "v1beta1" "/" "operations"] GET /v1beta1/{name=operations/**} func GetOperation(request longrunningpbpb.GetOperationRequest) (response longrunningpbpb.Operation) {} ["/" "v1beta1" "/" {name = ["operations" "/" **]}] POST /v1beta1/{name=operations/**}:cancel func CancelOperation(request longrunningpbpb.CancelOperationRequest) (response emptypbpb.Empty) {} ["/" "v1beta1" "/" {name = ["operations" "/" **]} ":" "cancel"] DELETE /v1beta1/{name=operations/**} func DeleteOperation(request longrunningpbpb.DeleteOperationRequest) (response emptypbpb.Empty) {} ["/" "v1beta1" "/" {name = ["operations" "/" **]}] ================================================ FILE: server/genrest/testing.go ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // DO NOT EDIT. This is an auto-generated file containing the REST handlers // for service #5: "Testing" (.google.showcase.v1beta1.Testing). package genrest import ( "bytes" "context" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/googleapis/gapic-showcase/util/genrest/resttools" gmux "github.com/gorilla/mux" "io" "net/http" ) // HandleCreateSession translates REST requests/responses on the wire to internal proto messages for CreateSession // // Generated for HTTP binding pattern: POST "/v1beta1/sessions" func (backend *RESTBackend) HandleCreateSession(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/sessions': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 0, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 0 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 0, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.CreateSessionRequest{} // Intentional: Field values in the URL path override those set in the body. var bodyField genprotopb.Session var jsonReader bytes.Buffer bodyReader := io.TeeReader(r.Body, &jsonReader) rBytes, err := io.ReadAll(bodyReader) if err != nil { backend.Error(w, http.StatusBadRequest, "error reading body content: %s", err) return } if err := resttools.FromJSON().Unmarshal(rBytes, &bodyField); err != nil { backend.Error(w, http.StatusBadRequest, "error reading body into request field 'session': %s", err) return } if err := resttools.CheckRequestFormat(&jsonReader, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } request.Session = &bodyField if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"session"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/sessions") response, err := backend.TestingServer.CreateSession(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleGetSession translates REST requests/responses on the wire to internal proto messages for GetSession // // Generated for HTTP binding pattern: GET "/v1beta1/{name=sessions/*}" func (backend *RESTBackend) HandleGetSession(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{name=sessions/*}': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.GetSessionRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"name"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{name=sessions/*}") response, err := backend.TestingServer.GetSession(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleListSessions translates REST requests/responses on the wire to internal proto messages for ListSessions // // Generated for HTTP binding pattern: GET "/v1beta1/sessions" func (backend *RESTBackend) HandleListSessions(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/sessions': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 0, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 0 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 0, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.ListSessionsRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/sessions") response, err := backend.TestingServer.ListSessions(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleDeleteSession translates REST requests/responses on the wire to internal proto messages for DeleteSession // // Generated for HTTP binding pattern: DELETE "/v1beta1/{name=sessions/*}" func (backend *RESTBackend) HandleDeleteSession(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{name=sessions/*}': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.DeleteSessionRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"name"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{name=sessions/*}") response, err := backend.TestingServer.DeleteSession(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleReportSession translates REST requests/responses on the wire to internal proto messages for ReportSession // // Generated for HTTP binding pattern: POST "/v1beta1/{name=sessions/*}:report" func (backend *RESTBackend) HandleReportSession(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{name=sessions/*}:report': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.ReportSessionRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"name"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{name=sessions/*}:report") response, err := backend.TestingServer.ReportSession(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleListTests translates REST requests/responses on the wire to internal proto messages for ListTests // // Generated for HTTP binding pattern: GET "/v1beta1/{parent=sessions/*}/tests" func (backend *RESTBackend) HandleListTests(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{parent=sessions/*}/tests': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.ListTestsRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"parent"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{parent=sessions/*}/tests") response, err := backend.TestingServer.ListTests(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleDeleteTest translates REST requests/responses on the wire to internal proto messages for DeleteTest // // Generated for HTTP binding pattern: DELETE "/v1beta1/{name=sessions/*/tests/*}" func (backend *RESTBackend) HandleDeleteTest(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{name=sessions/*/tests/*}': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.DeleteTestRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"name"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{name=sessions/*/tests/*}") response, err := backend.TestingServer.DeleteTest(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } // HandleVerifyTest translates REST requests/responses on the wire to internal proto messages for VerifyTest // // Generated for HTTP binding pattern: POST "/v1beta1/{name=sessions/*/tests/*}:check" func (backend *RESTBackend) HandleVerifyTest(w http.ResponseWriter, r *http.Request) { urlPathParams := gmux.Vars(r) numUrlPathParams := len(urlPathParams) backend.StdLog.Printf("Received %s request matching '/v1beta1/{name=sessions/*/tests/*}:check': %q", r.Method, r.URL) backend.StdLog.Printf(" urlPathParams (expect 1, have %d): %q", numUrlPathParams, urlPathParams) backend.StdLog.Printf(" urlRequestHeaders:\n%s", resttools.PrettyPrintHeaders(r, " ")) resttools.IncludeRequestHeadersInResponse(w, r) if numUrlPathParams != 1 { backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected 1, have %d: %#v", numUrlPathParams, urlPathParams) return } systemParameters, queryParams, err := resttools.GetSystemParameters(r) if err != nil { backend.Error(w, http.StatusBadRequest, "error in query string: %s", err) return } request := &genprotopb.VerifyTestRequest{} if err := resttools.CheckRequestFormat(nil, r, request.ProtoReflect()); err != nil { backend.Error(w, http.StatusBadRequest, "REST request failed format check: %s", err) return } if err := resttools.PopulateSingularFields(request, urlPathParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading URL path params: %s", err) return } // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both excludedQueryParams := []string{"name"} if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 { backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %v", duplicates) return } if err := resttools.PopulateFields(request, queryParams); err != nil { backend.Error(w, http.StatusBadRequest, "error reading query params: %s", err) return } marshaler := resttools.ToJSON() marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt requestJSON, _ := marshaler.Marshal(request) backend.StdLog.Printf(" request: %s", requestJSON) ctx := context.WithValue(r.Context(), resttools.BindingURIKey, "/v1beta1/{name=sessions/*/tests/*}:check") response, err := backend.TestingServer.VerifyTest(ctx, request) if err != nil { backend.ReportGRPCError(w, err) return } json, err := marshaler.Marshal(response) if err != nil { backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %s", err.Error()) return } w.Write(json) } ================================================ FILE: server/observer.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package server import ( "context" "sync" "google.golang.org/grpc" ) // UnaryObserver provides an interface for observing unary requests and responses. type UnaryObserver interface { GetName() string ObserveUnary( ctx context.Context, req interface{}, resp interface{}, info *grpc.UnaryServerInfo, err error) } // StreamRequestObserver provides an interface for observing streaming requests. type StreamRequestObserver interface { GetName() string ObserveStreamRequest( ctx context.Context, req interface{}, info *grpc.StreamServerInfo, err error) } // StreamResponseObserver provides an interface for observing streaming responses. type StreamResponseObserver interface { GetName() string ObserveStreamResponse( ctx context.Context, resp interface{}, info *grpc.StreamServerInfo, err error) } // GrpcObserverRegistry is a registry of observers. These observers are hooked into the // grpc interceptors that are provided by this interface. type GrpcObserverRegistry interface { // UnaryInterceptor implements the grpc.UnaryServerInterceptor type to allow the // registry to hook into unary grpc methods. UnaryInterceptor( context.Context, interface{}, *grpc.UnaryServerInfo, grpc.UnaryHandler) (interface{}, error) // StreamInterceptor implements the grpc.StreamServerInterceptor type to allow the // registry to hook into streaming grpc methods. StreamInterceptor( interface{}, grpc.ServerStream, *grpc.StreamServerInfo, grpc.StreamHandler) error RegisterUnaryObserver(UnaryObserver) DeleteUnaryObserver(name string) RegisterStreamRequestObserver(StreamRequestObserver) DeleteStreamRequestObserver(name string) RegisterStreamResponseObserver(StreamResponseObserver) DeleteStreamResponseObserver(name string) } // ShowcaseObserverRegistry returns the showcase specific observer registry. func ShowcaseObserverRegistry() GrpcObserverRegistry { return &showcaseObserverRegistry{ uObservers: map[string]UnaryObserver{}, sReqObservers: map[string]StreamRequestObserver{}, sRespObservers: map[string]StreamResponseObserver{}, } } // showcaseObserverRegistry is an implementation of the ObserverRegistry. This registry // automatically handles DeleteTest requests and deletes the appropriate observers // for that request. type showcaseObserverRegistry struct { mu sync.Mutex uObservers map[string]UnaryObserver sReqObservers map[string]StreamRequestObserver sRespObservers map[string]StreamResponseObserver } func (r *showcaseObserverRegistry) UnaryInterceptor( ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { r.mu.Lock() defer r.mu.Unlock() resp, err := handler(ctx, req) for _, obs := range r.uObservers { obs.ObserveUnary(ctx, req, resp, info, err) } return resp, err } type showcaseStream struct { info *grpc.StreamServerInfo registry *showcaseObserverRegistry grpc.ServerStream } func (s *showcaseStream) SendMsg(m interface{}) error { s.registry.mu.Lock() defer s.registry.mu.Unlock() err := s.ServerStream.SendMsg(m) for _, obs := range s.registry.sRespObservers { obs.ObserveStreamResponse(s.ServerStream.Context(), m, s.info, err) } return err } func (s *showcaseStream) RecvMsg(m interface{}) error { s.registry.mu.Lock() defer s.registry.mu.Unlock() err := s.ServerStream.RecvMsg(m) for _, obs := range s.registry.sReqObservers { obs.ObserveStreamRequest(s.ServerStream.Context(), m, s.info, err) } return err } func (r *showcaseObserverRegistry) StreamInterceptor( srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { return handler(srv, &showcaseStream{info, r, ss}) } // RegisterUnaryObserver registers a unary observer. If an observer of the same name // has already been registered, the new observer will override it. func (r *showcaseObserverRegistry) RegisterUnaryObserver(obs UnaryObserver) { r.mu.Lock() defer r.mu.Unlock() r.uObservers[obs.GetName()] = obs } func (r *showcaseObserverRegistry) DeleteUnaryObserver(name string) { r.mu.Lock() defer r.mu.Unlock() delete(r.uObservers, name) } // RegisterStreamRequestObserver registers a stream observer. If an observer of the same name // has already been registered, the new observer will override it. func (r *showcaseObserverRegistry) RegisterStreamRequestObserver(obs StreamRequestObserver) { r.mu.Lock() defer r.mu.Unlock() r.sReqObservers[obs.GetName()] = obs } func (r *showcaseObserverRegistry) DeleteStreamRequestObserver(name string) { r.mu.Lock() defer r.mu.Unlock() delete(r.sReqObservers, name) } // RegisterStreamResponseObserver registers a stream observer. If an observer of the same name // has already been registered, the new observer will override it. func (r *showcaseObserverRegistry) RegisterStreamResponseObserver(obs StreamResponseObserver) { r.mu.Lock() defer r.mu.Unlock() r.sRespObservers[obs.GetName()] = obs } func (r *showcaseObserverRegistry) DeleteStreamResponseObserver(name string) { r.mu.Lock() defer r.mu.Unlock() delete(r.sRespObservers, name) } ================================================ FILE: server/observer_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package server import ( "context" "errors" "reflect" "testing" "google.golang.org/grpc" ) type testUnaryObserver struct { name string req interface{} resp interface{} info *grpc.UnaryServerInfo err error } func (o *testUnaryObserver) GetName() string { return o.name } func (o *testUnaryObserver) ObserveUnary( ctx context.Context, req interface{}, resp interface{}, info *grpc.UnaryServerInfo, err error) { o.req = req o.resp = resp o.info = info o.err = err } func Test_showcaseObserverRegistry_UnaryInterceptor(t *testing.T) { observerName := "observerName" tests := []struct { name string req interface{} resp interface{} err error info *grpc.UnaryServerInfo observerDeleted bool }{ { "Passes through request and response", "test req", "test resp", nil, &grpc.UnaryServerInfo{}, false, }, { "Passes through request and error", "test req", nil, errors.New("test error"), &grpc.UnaryServerInfo{}, false, }, } for _, tt := range tests { obs := &testUnaryObserver{name: observerName} t.Run(tt.name, func(t *testing.T) { r := &showcaseObserverRegistry{ uObservers: map[string]UnaryObserver{obs.GetName(): obs}, } handler := func(_ context.Context, req interface{}) (interface{}, error) { if req != tt.req { t.Errorf("showcaseObserverRegistry.UnaryInterceptor() want to invoke handler with %v, got %v", tt.req, req) } return tt.resp, tt.err } got, err := r.UnaryInterceptor(context.Background(), tt.req, tt.info, handler) if err != tt.err { t.Errorf("showcaseObserverRegistry.UnaryInterceptor() error = %v, want %v", err, tt.err) return } if !reflect.DeepEqual(got, tt.resp) { t.Errorf("showcaseObserverRegistry.UnaryInterceptor() = %v, want %v", got, tt.resp) } if tt.observerDeleted && r.uObservers[observerName] != nil { t.Error("showcaseObserverRegistry.UnaryInterceptor() want delete observers but did not") } if !tt.observerDeleted && obs.req != tt.req { t.Errorf("showcaseObserverRegistry.UnaryInterceptor() want to invoke observers with %v, got %v", tt.req, obs.req) } if !tt.observerDeleted && obs.resp != tt.resp { t.Errorf("showcaseObserverRegistry.UnaryInterceptor() want to invoke observers with %v, got %v", tt.resp, obs.resp) } if !tt.observerDeleted && obs.err != tt.err { t.Errorf("showcaseObserverRegistry.UnaryInterceptor() want to invoke observers with %v, got %v", tt.err, obs.err) } if !tt.observerDeleted && obs.info != tt.info { t.Errorf("showcaseObserverRegistry.UnaryInterceptor() want to invoke observers with %v, got %v", tt.info, obs.info) } }) } } type testServerStream struct { err error sent interface{} received interface{} grpc.ServerStream } func (ss *testServerStream) Context() context.Context { return context.Background() } func (ss *testServerStream) SendMsg(m interface{}) error { ss.sent = m return ss.err } func (ss *testServerStream) RecvMsg(m interface{}) error { ss.received = m return ss.err } type testStreamResponseObserver struct { name string resp interface{} info *grpc.StreamServerInfo err error } func (o *testStreamResponseObserver) GetName() string { return o.name } func (o *testStreamResponseObserver) ObserveStreamResponse( ctx context.Context, resp interface{}, info *grpc.StreamServerInfo, err error) { o.resp = resp o.info = info o.err = err } func Test_showcaseStream_SendMsg(t *testing.T) { tests := []struct { name string info *grpc.StreamServerInfo msg interface{} err error }{ { "Passes msg, info, and error to observer", &grpc.StreamServerInfo{}, "sent msg", errors.New("test error"), }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { registry := &showcaseObserverRegistry{sRespObservers: map[string]StreamResponseObserver{}} obs := &testStreamResponseObserver{name: "streamObserver"} registry.RegisterStreamResponseObserver(obs) ss := &testServerStream{err: tt.err} s := &showcaseStream{tt.info, registry, ss} if err := s.SendMsg(tt.msg); err != tt.err { t.Errorf("showcaseStream.SendMsg() error = %v, want %v", err, tt.err) } if obs.resp != tt.msg { t.Errorf("showcaseStream.SendMsg() want to invoke observers with %v, got %v", tt.msg, obs.resp) } if ss.sent != tt.msg { t.Errorf("showcaseStream.SendMsg() want to invoke server stream with %v, got %v", tt.msg, ss.sent) } if obs.info != tt.info { t.Errorf("showcaseStream.SendMsg() want to invoke observers with %v, got %v", tt.info, obs.info) } if obs.err != tt.err { t.Errorf("showcaseStream.SendMsg() want to invoke observers with %v, got %v", tt.err, obs.err) } }) } } type testStreamRequestObserver struct { name string req interface{} info *grpc.StreamServerInfo err error } func (o *testStreamRequestObserver) GetName() string { return o.name } func (o *testStreamRequestObserver) ObserveStreamRequest( ctx context.Context, req interface{}, info *grpc.StreamServerInfo, err error) { o.req = req o.info = info o.err = err } func Test_showcaseStream_RecvMsg(t *testing.T) { tests := []struct { name string info *grpc.StreamServerInfo msg interface{} err error }{ { "Passes msg, info, and error to observer", &grpc.StreamServerInfo{}, "received msg", errors.New("test error"), }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { registry := &showcaseObserverRegistry{sReqObservers: map[string]StreamRequestObserver{}} obs := &testStreamRequestObserver{name: "streamObserver"} registry.RegisterStreamRequestObserver(obs) ss := &testServerStream{err: tt.err} s := &showcaseStream{tt.info, registry, ss} if err := s.RecvMsg(tt.msg); err != tt.err { t.Errorf("showcaseStream.RecvMsg() error = %v, want %v", err, tt.err) } if obs.req != tt.msg { t.Errorf("showcaseStream.SendMsg() want to invoke observers with %v, got %v", tt.msg, obs.req) } if ss.received != tt.msg { t.Errorf("showcaseStream.SendMsg() want to invoke server stream with %v, got %v", tt.msg, ss.received) } if obs.info != tt.info { t.Errorf("showcaseStream.SendMsg() want to invoke observers with %v, got %v", tt.info, obs.info) } if obs.err != tt.err { t.Errorf("showcaseStream.SendMsg() want to invoke observers with %v, got %v", tt.err, obs.err) } }) } } func Test_showcaseObserverRegistry_StreamInterceptor(t *testing.T) { r := ShowcaseObserverRegistry() srv := "server" ss := &testServerStream{} info := &grpc.StreamServerInfo{} tErr := errors.New("test error") handler := func(gotSrv interface{}, gotSs grpc.ServerStream) error { if srv != gotSrv { t.Errorf("showcaseObserverRegistry.StreamInterceptor() want to invoke handler with %v got %v", srv, gotSrv) } showcaseStream, ok := gotSs.(*showcaseStream) if !ok { t.Error("showcaseObserverRegistry.StreamInterceptor() expected to wrap server stream with showcase stream") } if info != showcaseStream.info { t.Errorf("showcaseObserverRegistry.StreamInterceptor() want to instantiate showcase stream with %v got %v", info, showcaseStream.info) } if r != showcaseStream.registry { t.Errorf("showcaseObserverRegistry.StreamInterceptor() want to instantiate showcase stream with %v got %v", r, showcaseStream.registry) } return tErr } if err := r.StreamInterceptor(srv, ss, info, handler); err != tErr { t.Errorf("showcaseObserverRegistry.StreamInterceptor() error = %v, wantErr %v", err, tErr) } } ================================================ FILE: server/page_token.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package server import ( "encoding/base64" "fmt" "strconv" "strings" "time" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) // NewTokenGenerator provides a new instance of a TokenGenerator. func NewTokenGenerator() TokenGenerator { return &tokenGenerator{salt: strconv.FormatInt(time.Now().Unix(), 10)} } // TokenGeneratorWithSalt provieds an instance of a TokenGenerator which // uses the given salt. func TokenGeneratorWithSalt(salt string) TokenGenerator { return &tokenGenerator{salt} } // TokenGenerator generates a page token for a given index. type TokenGenerator interface { ForIndex(int) string GetIndex(string) (int, error) } // InvalidTokenErr is the error returned if the token provided is not // parseable by the TokenGenerator. var InvalidTokenErr = status.Errorf( codes.InvalidArgument, "The field `page_token` is invalid.") type tokenGenerator struct { salt string } func (t *tokenGenerator) ForIndex(i int) string { return base64.StdEncoding.EncodeToString( []byte(fmt.Sprintf("%s%d", t.salt, i))) } func (t *tokenGenerator) GetIndex(s string) (int, error) { if s == "" { return 0, nil } bs, err := base64.StdEncoding.DecodeString(s) if err != nil { return -1, InvalidTokenErr } if !strings.HasPrefix(string(bs), t.salt) { return -1, InvalidTokenErr } i, err := strconv.Atoi(strings.TrimPrefix(string(bs), t.salt)) if err != nil { return -1, InvalidTokenErr } return i, nil } ================================================ FILE: server/page_token_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package server import ( "encoding/base64" "testing" ) func Test_tokenGenerator_ForIndex(t *testing.T) { salt := "salt" index := 1 want := base64.StdEncoding.EncodeToString( []byte("salt1")) tok := TokenGeneratorWithSalt(salt) if got := tok.ForIndex(index); got != want { t.Errorf("tokenGenerator.ForIndex() = %v, want %v", got, want) } } func Test_tokenGenerator_GetIndex_notParseable(t *testing.T) { tok := NewTokenGenerator() _, err := tok.GetIndex("invalid") if err == nil { t.Error("GetIndex: want error for invalid token.") } } func Test_tokenGenerator_GetIndex_noSalt(t *testing.T) { tok := NewTokenGenerator() _, err := tok.GetIndex(base64.StdEncoding.EncodeToString([]byte("invalid"))) if err == nil { t.Error("GetIndex: want error for invalid token.") } } func Test_tokenGenerator_GetIndex_invalidIndex(t *testing.T) { tok := TokenGeneratorWithSalt("salt") _, err := tok.GetIndex(base64.StdEncoding.EncodeToString([]byte("saltinvalid"))) if err == nil { t.Error("GetIndex: want error for invalid token.") } } func Test_tokenGenerator_GetIndex(t *testing.T) { tok := TokenGeneratorWithSalt("salt") i, err := tok.GetIndex(base64.StdEncoding.EncodeToString([]byte("salt1"))) if err != nil { t.Error("GetIndex: unexpected err") } if i != 1 { t.Errorf("GetIndex: want 1, got %d", i) } } ================================================ FILE: server/services/compliance_service.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package services import ( "context" _ "embed" // for storing compliance suite data, used to verify incoming requests "fmt" "os" "github.com/google/go-cmp/cmp" "github.com/googleapis/gapic-showcase/server" pb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/googleapis/gapic-showcase/util/genrest/resttools" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" ) // NewComplianceServer returns a new ComplianceServer for the Showcase API. func NewComplianceServer() pb.ComplianceServer { return &complianceServerImpl{waiter: server.GetWaiterInstance()} } type complianceServerImpl struct { waiter server.Waiter } // requestMatchesExpectations returns an error iff the received request asks for server verification and its // contents do not match a known suite testing request with the same name. func (csi *complianceServerImpl) requestMatchesExpectation(received *pb.RepeatRequest, binding string) error { if !received.GetServerVerify() { return nil } if ComplianceSuiteStatus == ComplianceSuiteError { return fmt.Errorf("%s", ComplianceSuiteStatusMessage) } name := received.GetName() expectedRequest, ok := ComplianceSuiteRequests[name] if !ok { return fmt.Errorf("(ComplianceSuiteRequestNotFoundError) compliance suite does not contain a request %q", name) } // Checking that the binding in the test suite matches actual binding used. if expectedRequest.IntendedBindingUri != nil { intendedBinding := expectedRequest.GetIntendedBindingUri() if intendedBinding != binding { return fmt.Errorf("(ComplianceSuiteWrongBindingError) request %q was transcoded to the wrong binding (expected: %s; actual %s)", name, intendedBinding, binding) } } // Separately checking that the binding in the client request matches binding in the test suite. // This guards against the test suite file being wrong on the client. if expectedRequest.GetIntendedBindingUri() != received.GetIntendedBindingUri() { return fmt.Errorf("(ComplianceSuiteRequestBindingMismatchError) intended binding of request %q does not match test suite (expected: %s, received: %s)", name, expectedRequest.GetIntendedBindingUri(), received.GetIntendedBindingUri()) } if diff := cmp.Diff(received.GetInfo(), expectedRequest.GetInfo(), cmp.Comparer(proto.Equal)); diff != "" { return fmt.Errorf("(ComplianceSuiteRequestMismatchError) contents of request %q do not match test suite", name) } return nil } func (csi *complianceServerImpl) Repeat(ctx context.Context, in *pb.RepeatRequest) (*pb.RepeatResponse, error) { echoTrailers(ctx) bindingURI, ok := ctx.Value(resttools.BindingURIKey).(string) if !ok { bindingURI = "" } if err := csi.requestMatchesExpectation(in, bindingURI); err != nil { return nil, err } return &pb.RepeatResponse{Request: in, BindingUri: bindingURI}, nil } func (csi *complianceServerImpl) RepeatDataBody(ctx context.Context, in *pb.RepeatRequest) (*pb.RepeatResponse, error) { return csi.Repeat(ctx, in) } func (csi *complianceServerImpl) RepeatDataBodyInfo(ctx context.Context, in *pb.RepeatRequest) (*pb.RepeatResponse, error) { return csi.Repeat(ctx, in) } func (csi *complianceServerImpl) RepeatDataQuery(ctx context.Context, in *pb.RepeatRequest) (*pb.RepeatResponse, error) { return csi.Repeat(ctx, in) } func (csi *complianceServerImpl) RepeatDataSimplePath(ctx context.Context, in *pb.RepeatRequest) (*pb.RepeatResponse, error) { return csi.Repeat(ctx, in) } func (csi *complianceServerImpl) RepeatDataPathResource(ctx context.Context, in *pb.RepeatRequest) (*pb.RepeatResponse, error) { return csi.Repeat(ctx, in) } func (csi *complianceServerImpl) RepeatDataPathTrailingResource(ctx context.Context, in *pb.RepeatRequest) (*pb.RepeatResponse, error) { return csi.Repeat(ctx, in) } func (csi *complianceServerImpl) RepeatDataBodyPut(ctx context.Context, in *pb.RepeatRequest) (*pb.RepeatResponse, error) { return csi.Repeat(ctx, in) } func (csi *complianceServerImpl) RepeatDataBodyPatch(ctx context.Context, in *pb.RepeatRequest) (*pb.RepeatResponse, error) { return csi.Repeat(ctx, in) } // complianceSuiteBytes contains the contents of the compliance suite JSON file. This requires Go // 1.16. Note that embedding can only be applied to global variables at package scope. // //go:embed compliance_suite.json var complianceSuiteBytes []byte //// Enum support testing. // These enums are not part of the current compliance suite because they don't // have the server echo the client's request. var existingEnumValue, unknownEnumValue pb.Continent // storeEnumTestValues stores the values for known and unknown enums used in GetEnum() and // VerifyEnum() in this session. This function should be run from init() func storeEnumTestValues() { deterministicInt := os.Getpid() unknownEnumValue = pb.Continent(-deterministicInt) existingEnumValue = pb.Continent(deterministicInt%(len(pb.Continent_name)-1) + 1) } func (csi *complianceServerImpl) GetEnum(ctx context.Context, in *pb.EnumRequest) (*pb.EnumResponse, error) { response := &pb.EnumResponse{ Request: in, } if in.GetUnknownEnum() { response.Continent = unknownEnumValue } else { response.Continent = existingEnumValue } return response, nil } func (csi *complianceServerImpl) VerifyEnum(ctx context.Context, in *pb.EnumResponse) (*pb.EnumResponse, error) { usingUnknownEnum := in.Request.GetUnknownEnum() expectedEnum := existingEnumValue if usingUnknownEnum { expectedEnum = unknownEnumValue } if actualEnum := in.GetContinent(); actualEnum != expectedEnum { return nil, fmt.Errorf("(UnexpectedEnumError) enum received (%d) is not the value expected (%d) when unknown_enum = %t", actualEnum, expectedEnum, usingUnknownEnum) } return in, nil } //// Compliance suite support. // ComplianceSuiteInitStatus contains the status result of loading the compliance test suite type ComplianceSuiteInitStatus int const ( // ComplianceSuiteUninitialized means we have not attempted to parse the compliance suite data into services.ComplianceSuite. ComplianceSuiteUninitialized ComplianceSuiteInitStatus = iota // ComplianceSuiteLoaded means we have successfully parsed the compliance suite data into services.ComplianceSuite. ComplianceSuiteLoaded // ComplianceSuiteError means we failed parsing the compliance suite data into services.ComplianceSuite. ComplianceSuiteError ) var ( // ComplianceSuite holds the protocol buffer representation of the compliance suite data. ComplianceSuite *pb.ComplianceSuite // ComplianceSuiteRequests holds all the requests in ComplianceSuite, indexed by the `name` field of the request. ComplianceSuiteRequests map[string]*pb.RepeatRequest // ComplianceSuiteStatus reports the status of loading the compliance suite data into services.ComplianceSuite. ComplianceSuiteStatus ComplianceSuiteInitStatus // ComplianceSuiteStatusMessage holds a message explaining ComplianceSuiteStatus. This is // typically used to provide more information in the case // ComplianceSuiteStatus==ComplianceSuiteError. ComplianceSuiteStatusMessage string ) // IndexComplianceSuite creates a map by request name of the the requests in the // suite, for easy retrieval later. func IndexComplianceSuite(suite *pb.ComplianceSuite) (map[string]*pb.RepeatRequest, error) { indexedSuite := make(map[string]*pb.RepeatRequest) for _, group := range suite.GetGroup() { for _, requestProto := range group.GetRequests() { name := requestProto.GetName() if _, exists := indexedSuite[name]; exists { return nil, fmt.Errorf("multiple requests in compliance suite have name %q", name) } indexedSuite[name] = requestProto } } return indexedSuite, nil } // indexTestingRequests creates a map by request name of the requests in suiteBytes (a // JSON-formatted encoding of pb.ComplianceSuite), for easy retrieval later. func indexTestingRequests(suiteBytes []byte) (err error) { if ComplianceSuiteStatus == ComplianceSuiteLoaded { return nil } ComplianceSuite = &pb.ComplianceSuite{} if err := protojson.Unmarshal(suiteBytes, ComplianceSuite); err != nil { ComplianceSuiteStatus = ComplianceSuiteError ComplianceSuiteStatusMessage = fmt.Sprintf("(ComplianceServiceReadError) could not read compliance suite file: %s", err) return fmt.Errorf("%s", ComplianceSuiteStatusMessage) } indexedSuite, err := IndexComplianceSuite(ComplianceSuite) if err != nil { ComplianceSuiteStatus = ComplianceSuiteError ComplianceSuiteStatusMessage = fmt.Sprintf("(ComplianceServiceSetupError) %s", err) return fmt.Errorf("%s", ComplianceSuiteStatusMessage) } ComplianceSuiteRequests = indexedSuite ComplianceSuiteStatus = ComplianceSuiteLoaded ComplianceSuiteStatusMessage = "OK" return nil } func init() { indexTestingRequests(complianceSuiteBytes) storeEnumTestValues() } ================================================ FILE: server/services/compliance_service_test.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package services import ( "context" "strings" "testing" "github.com/google/go-cmp/cmp" pb "github.com/googleapis/gapic-showcase/server/genproto" "google.golang.org/protobuf/proto" ) func TestComplianceRepeats(t *testing.T) { // Note that additional thorough test cases are exercised in // cmd/gapic-showcase/compliance_suite_test.go. server := NewComplianceServer() info := &pb.ComplianceData{ FString: "Terra Incognita", FInt32: 1, FSint32: -2, FSfixed32: -300000000, FUint32: 5, FFixed32: 700000000, FInt64: 9, FSint64: -1100000000, FSfixed64: -1300000000, FUint64: 1700000000000000000, FFixed64: 1900000000000000000, FDouble: 6.02e23, FFloat: 3.1415, FBool: true, FBytes: []byte("Lorem ipsum"), } request := &pb.RepeatRequest{Info: info} for idx, rpc := range [](func(ctx context.Context, in *pb.RepeatRequest) (*pb.RepeatResponse, error)){ server.RepeatDataQuery, server.RepeatDataBody, server.RepeatDataBodyInfo, server.RepeatDataSimplePath, server.RepeatDataPathResource, server.RepeatDataPathTrailingResource, server.RepeatDataBodyPut, server.RepeatDataBodyPatch, } { response, err := rpc(context.Background(), request) if err != nil { t.Errorf("call %d: error: %s", idx, err) } if diff := cmp.Diff(response.GetRequest(), request, cmp.Comparer(proto.Equal)); diff != "" { t.Errorf("call %d: got=-, want=+:%s", idx, diff) } } } func TestMatchingComplianceSuiteRequests(t *testing.T) { server := &complianceServerImpl{} info := &pb.ComplianceData{ FString: "Terra Incognita", FInt32: 1, FSint32: -2, FSfixed32: -300000000, } request := &pb.RepeatRequest{ Name: "Basic data types", // matches a name in compliance_suite.json Info: info, } if got := server.requestMatchesExpectation(request, ""); got != nil { t.Errorf("expected request to trivially match when serverVerify unset. Got error: %s", got) } request.ServerVerify = true if err := server.requestMatchesExpectation(request, ""); err == nil { t.Errorf("expected verified request with differing data to not match") } else { if got, want := err.Error(), "(ComplianceSuiteRequestMismatchError)"; !strings.Contains(got, want) { t.Errorf("error message does not contain expected substring: want: %q got %q", want, got) } if _, got := server.Repeat(context.Background(), request); got == nil { t.Errorf("expected Repeat() to error with unverified request, but it didn't") } } request.Name = "non-existent case" if err := server.requestMatchesExpectation(request, ""); err == nil { t.Errorf("expected verified request with unmatched name to cause an error") } else { if got, want := err.Error(), "(ComplianceSuiteRequestNotFoundError)"; !strings.Contains(got, want) { t.Errorf("error message does not contain expected substring: want: %q got %q", want, got) } if _, got := server.Repeat(context.Background(), request); got == nil { t.Errorf("expected Repeat() to error with unverified request, but it didn't") } } request = ComplianceSuiteRequests["Basic data types"] // matches a name in compliance_suite.json if got := server.requestMatchesExpectation(request, ""); got != nil { t.Errorf("expected test suite case to match. Got error: %s", got) } if _, got := server.Repeat(context.Background(), request); got != nil { t.Errorf("expected Repeat() to succeed with verified request, but got error: %s", got) } } // Tests for the binding verification parts of the request verification // in the compliance service. func TestBindingComplianceSuiteRequests(t *testing.T) { server := &complianceServerImpl{} info := &pb.ComplianceData{ FString: "first/hello", PBool: &[]bool{true}[0], FChild: &pb.ComplianceDataChild{ FString: "second/greetings", }, } noURIVerifyRequest := &pb.RepeatRequest{ Name: "Binding testing baseline no Uri verification", // matches a name in compliance_suite.json Info: info, ServerVerify: true, } wrongBindingURI := "/foo/{id=bar/*}" if got := server.requestMatchesExpectation(noURIVerifyRequest, wrongBindingURI); got != nil { t.Errorf("expected request to match when intended Uri is not set on server. Got error: %s", got) } // realBindingUri matches the value in compliance_suite.json realBindingURI := "/v1beta1/repeat/{info.f_string=first/*}/{info.f_child.f_string=second/*}/bool/{info.f_bool}:pathresource" uriVerifyRequest := &pb.RepeatRequest{ Name: "Binding testing first binding", // matches a name in compliance_suite.json Info: info, ServerVerify: true, IntendedBindingUri: &realBindingURI, } // There are three sources of binding Uri: // - actualUri: what actual Uri the request was bound to in runtime // (the second parameter of the `requestMatchesExpectation` method) // - serverUri: what server thinks the binding Uri should be // (in the server-side json testing suite data's `IntendedBindingUri` field) // - clientUri: what client thinks the binding Uri should be // (in the client-side json testing suite data `IntendedBindingUri` field) // The `requestMatchesExpectation` method verifies // - actualUri <- vs -> serverUri (looking for incorrect runtime binding) // - clientUri <- vs -> serverUri (looking for wrong client test suite) // In this case the request is simulated to get bound to a wrong Uri // (the second parameter of the `requestMatchesExpectation` method), // therefore actualUri will differ from serverUri. if err := server.requestMatchesExpectation(uriVerifyRequest, wrongBindingURI); err == nil { t.Errorf("expected request that got bound to a wrong uri to not match") } else { if got, want := err.Error(), "(ComplianceSuiteWrongBindingError)"; !strings.Contains(got, want) { t.Errorf("error message does not contain expected substring: want: %q got %q", want, got) } } // In this case the actualUri is set to the correct value // (matching the serverUri), but the clientUri is set to the wrong value, // simulating a corrupt or outdated client testing suite. uriVerifyRequest.IntendedBindingUri = &wrongBindingURI if err := server.requestMatchesExpectation(uriVerifyRequest, realBindingURI); err == nil { t.Errorf("expected request with an incorrect bindingUri to not match") } else { if got, want := err.Error(), "(ComplianceSuiteRequestBindingMismatchError)"; !strings.Contains(got, want) { t.Errorf("error message does not contain expected substring: want: %q got %q", want, got) } } uriVerifyRequest.IntendedBindingUri = &realBindingURI if got := server.requestMatchesExpectation(uriVerifyRequest, realBindingURI); got != nil { t.Errorf("expected request to match when binding Uri is same everywhere. Got error: %s", got) } } func TestIndexingComplianceSuite(t *testing.T) { // set up ComplianceSuiteStatus = ComplianceSuiteUninitialized suiteBytes := []byte("nonexistent_field: 5 ") if err := indexTestingRequests(suiteBytes); err == nil { t.Errorf("expected JSON unmarshaling to fail, but it succeeded") } else { if got, want := err.Error(), "(ComplianceServiceReadError)"; !strings.Contains(got, want) { t.Errorf("error message does not contain expected substring: want: %q got %q", want, got) } } suiteBytes = []byte(` { "group": [ { "name": "sample suite", "requests": [ { "name": "Alpha"}, { "name": "Beta"}, { "name": "Alpha"} ] } ] } `) if err := indexTestingRequests(suiteBytes); err == nil { t.Errorf("expected JSON unmarshaling to fail, but it succeeded") } else { if got, want := err.Error(), "(ComplianceServiceSetupError)"; !strings.Contains(got, want) { t.Errorf("error message does not contain expected substring: want: %q got %q", want, got) } } // test that the indexing error gets properly propagated server := &complianceServerImpl{} request := &pb.RepeatRequest{ Name: "Basic data types", // matches a name in compliance_suite.json ServerVerify: true, } if err := server.requestMatchesExpectation(request, ""); err == nil { t.Errorf("expected verified request with differing data to not match") } else { if got, want := err.Error(), "(ComplianceServiceSetupError)"; !strings.Contains(got, want) { t.Errorf("error message does not contain expected substring: want: %q got %q", want, got) } if _, got := server.Repeat(context.Background(), request); got == nil { t.Errorf("expected Repeat() to error with unverified request, but it didn't") } } // clean up ComplianceSuiteStatus = ComplianceSuiteUninitialized if err := indexTestingRequests(complianceSuiteBytes); err != nil { t.Errorf("initializing ComplianceSuite with real suite data should not have errored, but got: %s", err) } if err := indexTestingRequests(complianceSuiteBytes); err != nil { t.Errorf("initializing ComplianceSuite a second time should not have errored, but got: %s", err) } } ================================================ FILE: server/services/compliance_suite.json ================================================ { "group": [ { "name": "Fully working conversions, no resources", "rpcs": ["Compliance.RepeatDataBody", "Compliance.RepeatDataBodyPut", "Compliance.RepeatDataBodyPatch", "Compliance.RepeatDataQuery", "Compliance.RepeatDataSimplePath", "Compliance.RepeatDataBodyInfo"], "requests": [ { "name": "Basic data types", "serverVerify": true, "info": { "fString": "Hello", "fInt32": -1, "fSint32" : -2, "fSfixed32": -3, "fUint32": 5, "fFixed32": 7, "fInt64": -11, "fSint64": -13, "fSfixed64": -17, "fUint64": 19, "fFixed64":23, "fDouble": -29e4, "fFloat": -31, "fBool": true, "fKingdom": "ANIMALIA", "pString": "Goodbye", "pInt32": -37, "pDouble": -41.43, "pBool": true, "pKingdom": "PLANTAE", "fChild": { "fString": "second/bool/salutation" } }, "fInt32": -10, "fInt64": -110, "fDouble": -54e4, "pInt32": -47, "pInt64": -477, "pDouble": -61.73 }, { "name": "Basic types, no optional fields", "serverVerify": true, "info": { "fString": "Hello", "fInt32": -1, "fSint32" : -2, "fSfixed32": -3, "fUint32": 5, "fFixed32": 7, "fInt64": -11, "fSint64": -13, "fSfixed64": -17, "fUint64": 19, "fFixed64":23, "fDouble": -29e4, "fFloat": -31, "fBool": true, "fKingdom": "ANIMALIA", "fChild": { "fString": "second/bool/salutation" } } }, { "name": "Zero values for non-string fields", "serverVerify": true, "info": { "fString": "Hello", "fInt32": 0, "fSint32" : 0, "fSfixed32": 0, "fUint32": 0, "fFixed32": 0, "fInt64": 0, "fSint64": 0, "fSfixed64": 0, "fUint64": 0, "fFixed64": 0, "fDouble": 0, "fFloat": 0, "fBool": false, "fKingdom": "LIFE_KINGDOM_UNSPECIFIED", "pString": "Goodbye", "pInt32": 0, "pDouble": 0, "pBool": false, "pKingdom": "LIFE_KINGDOM_UNSPECIFIED" } }, { "name": "Extreme values", "serverVerify": true, "info": { "fString": "non-ASCII+non-printable string ☺ → ← \"\\\/\b\f\r\t\u1234 works, not newlines yet", "fInt32": 2147483647, "fSint32" : 2147483647, "fSfixed32": 2147483647, "fUint32": 4294967295, "fFixed32": 4294967295, "fInt64": "9223372036854775807", "fSint64": "9223372036854775807", "fSfixed64": "9223372036854775807", "fUint64": "18446744073709551615", "fFixed64": "18446744073709551615", "fDouble": 1.797693134862315708145274237317043567981e+308, "fFloat": 3.40282346638528859811704183484516925440e+38, "fBool": false, "pString": "Goodbye", "pInt32": 2147483647, "pDouble": 1.797693134862315708145274237317043567981e+308, "pBool": false } }, { "name": "Strings with spaces", "serverVerify": true, "info": { "fString": "Hello there" } }, { "name": "Strings with quotes", "serverVerify": true, "info": { "fString": "Hello \"You\"" } }, { "name": "Strings with percents", "serverVerify": true, "info": { "fString": "Hello 100%" } } ] }, { "name": "Fully working conversions, resources", "rpcs": ["Compliance.RepeatDataBody", "Compliance.RepeatDataBodyPut", "Compliance.RepeatDataBodyPatch", "Compliance.RepeatDataQuery"], "requests": [ { "name": "Strings with slashes and values that resemble subsequent resource templates", "serverVerify": true, "info": { "fString": "first/hello/second/greetings", "pBool": true, "fChild": { "fString": "second/zzz/bool/true" } } } ] }, { "name": "Binding selection testing", "rpcs": ["Compliance.RepeatDataPathResource"], "requests": [ { "name": "Binding testing baseline no Uri verification", "serverVerify": true, "info": { "fString": "first/hello", "pBool": true, "fChild": { "fString": "second/greetings" } } }, { "name": "Binding testing first binding", "serverVerify": true, "info": { "fString": "first/hello", "pBool": true, "fChild": { "fString": "second/greetings" } }, "intendedBindingUri": "/v1beta1/repeat/{info.f_string=first/*}/{info.f_child.f_string=second/*}/bool/{info.f_bool}:pathresource" }, { "name": "Binding testing additional binding", "serverVerify": true, "info": { "fString": "second/greetings", "pBool": true, "fChild": { "fString": "first/hello" } }, "intendedBindingUri": "/v1beta1/repeat/{info.f_child.f_string=first/*}/{info.f_string=second/*}/bool/{info.f_bool}:childfirstpathresource" } ] }, { "name": "Cases that apply to non-path requests", "rpcs": ["Compliance.RepeatDataBody", "Compliance.RepeatDataBodyPut", "Compliance.RepeatDataBodyPatch", "Compliance.RepeatDataQuery"], "requests": [ { "name": "Zero values for all fields", "serverVerify": true, "info": { "fString": "", "fInt32": 0, "fSint32" : 0, "fSfixed32": 0, "fUint32": 0, "fFixed32": 0, "fInt64": 0, "fSint64": 0, "fSfixed64": 0, "fUint64": 0, "fFixed64":20, "fDouble": 0, "fFloat": 0, "fBool": false, "pString": "", "pInt32": 0, "pDouble": 0, "pBool": false } } ] } ] } ================================================ FILE: server/services/echo_service.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package services import ( "context" "fmt" "io" "strconv" "strings" "time" "unicode/utf8" lropb "cloud.google.com/go/longrunning/autogen/longrunningpb" "github.com/golang/protobuf/ptypes" "github.com/googleapis/gapic-showcase/server" pb "github.com/googleapis/gapic-showcase/server/genproto" errdetails "google.golang.org/genproto/googleapis/rpc/errdetails" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" anypb "google.golang.org/protobuf/types/known/anypb" "google.golang.org/protobuf/types/known/durationpb" ) // NewEchoServer returns a new EchoServer for the Showcase API. func NewEchoServer() pb.EchoServer { return &echoServerImpl{waiter: server.GetWaiterInstance()} } type echoServerImpl struct { waiter server.Waiter } func (s *echoServerImpl) Echo(ctx context.Context, in *pb.EchoRequest) (*pb.EchoResponse, error) { err := status.ErrorProto(in.GetError()) if err != nil { return nil, err } echoHeaders(ctx) echoTrailers(ctx) return &pb.EchoResponse{Content: in.GetContent(), Severity: in.GetSeverity(), RequestId: in.GetRequestId(), OtherRequestId: in.GetOtherRequestId()}, nil } func (s *echoServerImpl) EchoErrorDetails(ctx context.Context, in *pb.EchoErrorDetailsRequest) (*pb.EchoErrorDetailsResponse, error) { var singleDetailError *pb.EchoErrorDetailsResponse_SingleDetail singleDetailText := in.GetSingleDetailText() if len(singleDetailText) > 0 { singleErrorInfo := &errdetails.ErrorInfo{Reason: singleDetailText} singleMarshalledError, err := anypb.New(singleErrorInfo) if err != nil { return nil, fmt.Errorf("failure with single error detail in EchoErrorDetails: %w", err) } singleDetailError = &pb.EchoErrorDetailsResponse_SingleDetail{ Error: &pb.ErrorWithSingleDetail{Details: singleMarshalledError}, } } var multipleDetailsError *pb.EchoErrorDetailsResponse_MultipleDetails multipleDetailText := in.GetMultiDetailText() if len(multipleDetailText) > 0 { details := []*anypb.Any{} for idx, text := range multipleDetailText { errorInfo := &errdetails.ErrorInfo{ Reason: text, } marshalledError, err := anypb.New(errorInfo) if err != nil { return nil, fmt.Errorf("failure in EchoErrorDetails[%d]: %w", idx, err) } details = append(details, marshalledError) } multipleDetailsError = &pb.EchoErrorDetailsResponse_MultipleDetails{ Error: &pb.ErrorWithMultipleDetails{Details: details}, } } echoHeaders(ctx) echoTrailers(ctx) response := &pb.EchoErrorDetailsResponse{ SingleDetail: singleDetailError, MultipleDetails: multipleDetailsError, } return response, nil } // DetailedError satisfies the interface defined in https://pkg.go.dev/google.golang.org/grpc/status#FromError to convert an error to a status.Status. type DetailedError struct { grpcStatus *status.Status } func (de DetailedError) Error() string { return fmt.Sprintf("DetailedError.Error(): %d: %s [(%d details)]", de.grpcStatus.Code(), de.grpcStatus.Message(), len(de.grpcStatus.Details())) } // GRPCStatus returns the gRPC status associated with the given // DetailedError as a way of satisfying the interface defined in // https://pkg.go.dev/google.golang.org/grpc/status#FromError func (de *DetailedError) GRPCStatus() *status.Status { return de.grpcStatus } func (s *echoServerImpl) FailEchoWithDetails(ctx context.Context, in *pb.FailEchoWithDetailsRequest) (*pb.FailEchoWithDetailsResponse, error) { detailInfo := &errdetails.ErrorInfo{ Reason: "some ErrorInfo reason", } detailLocalized := &errdetails.LocalizedMessage{ Locale: "fr-CH", Message: "This LocalizedMessage should be treated specially", } poem := in.GetMessage() if poem == "" { poem = "roses are red" } detailPoetry := &pb.PoetryError{ Poem: poem, } duration, _ := time.ParseDuration("11s") detailRetry := &errdetails.RetryInfo{ RetryDelay: durationpb.New(duration), } detailDebug := &errdetails.DebugInfo{ Detail: "a DebugInfo detail", } detailQuotaFailure := &errdetails.QuotaFailure{ Violations: []*errdetails.QuotaFailure_Violation{ {Description: "First QuotaFailure description"}, {Description: "Second QuotaFailure description"}, }, } detailPreconditionFailure := &errdetails.PreconditionFailure{ Violations: []*errdetails.PreconditionFailure_Violation{ {Description: "First PreconditionFailure description"}, {Description: "Second PreconditionFailure description"}, }, } detailBadRequest := &errdetails.BadRequest{ FieldViolations: []*errdetails.BadRequest_FieldViolation{ {Description: "First BadRequest description"}, {Description: "Second BadRequest description"}, }, } detailRequestInfo := &errdetails.RequestInfo{ RequestId: "RequestInfo: showcase-request-id", ServingData: "RequestInfo: showcase serving data", } detailResourceInfo := &errdetails.ResourceInfo{ ResourceType: "ResourceInfo: showcase resource", } detailHelp := &errdetails.Help{ Links: []*errdetails.Help_Link{ {Description: "Help: first showcase help link"}, {Description: "Help: second showcase help link"}, }, } theStatus, err := status.New(codes.Aborted, "This is an error generated by the server").WithDetails( detailInfo, detailLocalized, detailPoetry, detailRetry, detailDebug, detailQuotaFailure, detailPreconditionFailure, detailBadRequest, detailRequestInfo, detailResourceInfo, detailHelp) if err != nil { return nil, fmt.Errorf("failure in FailEchoWithDetails: %w", err) } detailedError := &DetailedError{ grpcStatus: theStatus, } return nil, detailedError } func (s *echoServerImpl) Expand(in *pb.ExpandRequest, stream pb.Echo_ExpandServer) error { for _, word := range strings.Fields(in.GetContent()) { err := stream.Send(&pb.EchoResponse{Content: word}) if err != nil { return err } time.Sleep(in.GetStreamWaitTime().AsDuration()) } echoStreamingHeaders(stream) if in.GetError() != nil { return status.ErrorProto(in.GetError()) } echoStreamingTrailers(stream) return nil } func (s *echoServerImpl) Collect(stream pb.Echo_CollectServer) error { var resp []string for { req, err := stream.Recv() if err == io.EOF { echoStreamingHeaders(stream) echoStreamingTrailers(stream) return stream.SendAndClose(&pb.EchoResponse{Content: strings.Join(resp, " ")}) } if err != nil { return err } s := status.ErrorProto(req.GetError()) if s != nil { return s } if req.GetContent() != "" { resp = append(resp, req.GetContent()) } } } func (s *echoServerImpl) Chat(stream pb.Echo_ChatServer) error { for { req, err := stream.Recv() if err == io.EOF { // Echo headers and trailers when the stream ends echoStreamingHeaders(stream) echoStreamingTrailers(stream) return nil } if err != nil { return err } s := status.ErrorProto(req.GetError()) if s != nil { return s } stream.Send(&pb.EchoResponse{Content: req.GetContent()}) } } func (s *echoServerImpl) PagedExpandLegacy(ctx context.Context, in *pb.PagedExpandLegacyRequest) (*pb.PagedExpandResponse, error) { req := &pb.PagedExpandRequest{ Content: in.Content, PageSize: in.MaxResults, PageToken: in.PageToken, } return s.PagedExpand(ctx, req) } func (s *echoServerImpl) PagedExpand(ctx context.Context, in *pb.PagedExpandRequest) (*pb.PagedExpandResponse, error) { words := strings.Fields(in.GetContent()) start, end, nextToken, err := processPageTokens(len(words), in.GetPageSize(), in.GetPageToken()) if err != nil { return nil, err } responses := []*pb.EchoResponse{} for _, word := range words[start:end] { responses = append(responses, &pb.EchoResponse{Content: word}) } echoHeaders(ctx) echoTrailers(ctx) return &pb.PagedExpandResponse{ Responses: responses, NextPageToken: nextToken, }, nil } func (s *echoServerImpl) PagedExpandLegacyMapped(ctx context.Context, in *pb.PagedExpandRequest) (*pb.PagedExpandLegacyMappedResponse, error) { words := strings.Fields(in.GetContent()) start, end, nextToken, err := processPageTokens(len(words), in.GetPageSize(), in.GetPageToken()) if err != nil { return nil, err } // Construct a map with the following properties: // // 1. The map has a one-rune string key corresponding to the first rune of EVERY word in words. // 2. The value corresponding to a given rune key is a list of only those words between // `start` and `end` whose first rune is that key. // 3. Consequently, initial runes that only appear outside the [start,end) range will have // empty list entries, even if they are non-empty in subsequent pages. alphabetized := make(map[string]*pb.PagedExpandResponseList, 255) //assume most input is ASCII for idx, word := range words { initialRune, _ := utf8.DecodeRuneInString(word) key := string(initialRune) // enforces #1 prev, ok := alphabetized[key] if !ok { prev = &pb.PagedExpandResponseList{} // enforces #3 alphabetized[key] = prev } if int32(idx) >= start && int32(idx) < end { // enforces #2 prev.Words = append(prev.Words, word) } } echoHeaders(ctx) echoTrailers(ctx) return &pb.PagedExpandLegacyMappedResponse{ Alphabetized: alphabetized, NextPageToken: nextToken, }, nil } func processPageTokens(numElements int, pageSize int32, pageToken string) (start, end int32, nextToken string, err error) { if pageSize < 0 { return 0, 0, "", status.Error(codes.InvalidArgument, "the page size provided must not be negative.") } if pageToken != "" { token, err := strconv.Atoi(pageToken) token32 := int32(token) if err != nil || token32 < 0 || token32 >= int32(numElements) { return 0, 0, "", status.Errorf( codes.InvalidArgument, "invalid page token: %s. Token must be within the range [0, %d)", pageToken, numElements) } start = token32 } if pageSize == 0 { pageSize = int32(numElements) } end = min(start+pageSize, int32(numElements)) if end < int32(numElements) { nextToken = strconv.Itoa(int(end)) } return start, end, nextToken, nil } func min(x int32, y int32) int32 { if x < y { return x } return y } func (s *echoServerImpl) Wait(ctx context.Context, in *pb.WaitRequest) (*lropb.Operation, error) { echoHeaders(ctx) echoTrailers(ctx) return s.waiter.Wait(in), nil } func (s *echoServerImpl) Block(ctx context.Context, in *pb.BlockRequest) (*pb.BlockResponse, error) { d, _ := ptypes.Duration(in.GetResponseDelay()) time.Sleep(d) if in.GetError() != nil { return nil, status.ErrorProto(in.GetError()) } echoHeaders(ctx) echoTrailers(ctx) return in.GetSuccess(), nil } // echo any provided headers in the metadata func echoHeaders(ctx context.Context) { md, ok := metadata.FromIncomingContext(ctx) if !ok { return } fmt.Printf("Received headers: %v\n", md) headersToEcho := []string{"x-goog-request-params", "traceparent", "tracestate"} for _, headerName := range headersToEcho { values := md.Get(headerName) for _, value := range values { header := metadata.Pairs(headerName, value) grpc.SetHeader(ctx, header) } } } func echoStreamingHeaders(stream grpc.ServerStream) { md, ok := metadata.FromIncomingContext(stream.Context()) if !ok { return } headersToEcho := []string{"x-goog-request-params", "traceparent", "tracestate"} for _, headerName := range headersToEcho { values := md.Get(headerName) for _, value := range values { header := metadata.Pairs(headerName, value) if stream.SetHeader(header) != nil { return } } } } // echo any provided trailing metadata func echoTrailers(ctx context.Context) { md, ok := metadata.FromIncomingContext(ctx) if !ok { return } for k, v := range md { for _, value := range v { trailer := metadata.Pairs(k, value) grpc.SetTrailer(ctx, trailer) } } } func echoStreamingTrailers(stream grpc.ServerStream) { md, ok := metadata.FromIncomingContext(stream.Context()) if !ok { return } for k, v := range md { for _, value := range v { trailer := metadata.Pairs(k, value) stream.SetTrailer(trailer) } } } ================================================ FILE: server/services/echo_service_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package services import ( "context" "errors" "io" "reflect" "sort" "strings" "testing" "time" "github.com/golang/protobuf/ptypes" durpb "github.com/golang/protobuf/ptypes/duration" pb "github.com/googleapis/gapic-showcase/server/genproto" "google.golang.org/genproto/googleapis/rpc/errdetails" spb "google.golang.org/genproto/googleapis/rpc/status" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" durationpb "google.golang.org/protobuf/types/known/durationpb" ) func TestEcho_success(t *testing.T) { table := []string{"hello world", ""} server := NewEchoServer() for _, val := range table { in := &pb.EchoRequest{ Response: &pb.EchoRequest_Content{Content: val}, Severity: pb.Severity_CRITICAL, } mockStream := &mockUnaryStream{t: t} ctx := appendTestOutgoingMetadata(context.Background(), &mockSTS{t: t, stream: mockStream}) out, err := server.Echo(ctx, in) if err != nil { t.Error(err) } if out.GetContent() != in.GetContent() { t.Errorf("Echo(%s) returned %s", in.GetContent(), out.GetContent()) } if out.Severity != in.Severity { t.Errorf("Echo severity(%d) returned %d", in.Severity, out.Severity) } mockStream.verify(err != nil) } in := &pb.EchoRequest{ Response: &pb.EchoRequest_Error{ Error: &spb.Status{Code: int32(codes.OK)}}} mockStream := &mockUnaryStream{t: t} ctx := appendTestOutgoingMetadata(context.Background(), &mockSTS{t: t, stream: mockStream}) _, err := server.Echo(ctx, in) if err != nil { t.Error(err) } mockStream.verify(err != nil) } func TestEcho_error(t *testing.T) { table := []codes.Code{codes.Canceled, codes.InvalidArgument} server := NewEchoServer() for _, val := range table { in := &pb.EchoRequest{ Response: &pb.EchoRequest_Error{ Error: &spb.Status{Code: int32(val)}}} out, err := server.Echo(context.Background(), in) if out != nil { t.Errorf("Echo called with code %d returned a non-nil response proto.", val) } if err == nil { t.Errorf("Echo called with code %d did not return an error.", val) } status, _ := status.FromError(err) if status.Code() != val { t.Errorf("Echo called with code %d returned an error with code %d", val, status.Code()) } } } type mockSTS struct { stream grpc.ServerStream t *testing.T } func (m *mockSTS) Method() string { return "" } func (m *mockSTS) SetHeader(md metadata.MD) error { m.stream.SetHeader(md); return nil } func (m *mockSTS) SendHeader(md metadata.MD) error { return m.stream.SendHeader(md) } func (m *mockSTS) SetTrailer(md metadata.MD) error { m.stream.SetTrailer(md); return nil } type mockUnaryStream struct { head []string trail []string t *testing.T grpc.ServerStream } func (m *mockUnaryStream) Method() string { return "" } func (m *mockUnaryStream) Send(resp *pb.EchoResponse) error { return nil } func (m *mockUnaryStream) Context() context.Context { return nil } func (m *mockUnaryStream) SetTrailer(md metadata.MD) { m.trail = append(m.trail, md.Get("showcase-trailer")...) m.trail = append(m.trail, md.Get("x-goog-api-version")...) // Sort the trailer values as having a guaranteed order will help with array comparison sort.Strings(m.trail) } func (m *mockUnaryStream) SetHeader(md metadata.MD) error { m.head = append(m.head, md.Get("x-goog-request-params")...) m.head = append(m.head, md.Get("traceparent")...) m.head = append(m.head, md.Get("tracestate")...) return nil } func (m *mockUnaryStream) verify(expectHeadersAndTrailers bool) { if expectHeadersAndTrailers && (!reflect.DeepEqual([]string{"apiVersion", "case", "show"}, m.trail) || !reflect.DeepEqual([]string{"showcaseHeader", "anotherHeader", "00-traceid-spanid-01", "some-state"}, m.head)) { m.t.Errorf("Unary stream did not get all expected headers and trailers.\nGot these headers: %+v\nGot these trailers: %+v", m.head, m.trail) } } type mockExpandStream struct { exp []string head []string trail []string t *testing.T pb.Echo_ExpandServer } func (m *mockExpandStream) Send(resp *pb.EchoResponse) error { if resp.GetContent() != m.exp[0] { m.t.Errorf("Expand expected to send %s but sent %s", m.exp[0], resp.GetContent()) } m.exp = m.exp[1:] return nil } func (m *mockExpandStream) Context() context.Context { return appendTestOutgoingMetadata(context.Background(), &mockSTS{stream: m, t: m.t}) } func (m *mockExpandStream) SetTrailer(md metadata.MD) { m.trail = append(m.trail, md.Get("showcase-trailer")...) } func (m *mockExpandStream) SetHeader(md metadata.MD) error { m.head = append(m.head, md.Get("x-goog-request-params")...) m.head = append(m.head, md.Get("traceparent")...) m.head = append(m.head, md.Get("tracestate")...) m.head = append(m.head, md.Get("x-goog-api-version")...) return nil } func (m *mockExpandStream) verify(expectHeadersAndTrailers bool) { if len(m.exp) > 0 { m.t.Errorf("Expand did not stream all expected values. %d expected values remaining.", len(m.exp)) } if expectHeadersAndTrailers && (!reflect.DeepEqual([]string{"show", "case"}, m.trail) || !reflect.DeepEqual([]string{"showcaseHeader", "anotherHeader", "00-traceid-spanid-01", "some-state"}, m.head)) { m.t.Errorf("Expand did not get all expected headers and trailers.\nGot these headers: %+v\nGot these trailers: %+v", m.head, m.trail) } } func TestExpand(t *testing.T) { contentTable := []string{"Hello World", "Hola", ""} errTable := []*spb.Status{ {Code: int32(codes.OK)}, {Code: int32(codes.InvalidArgument)}, nil, } server := NewEchoServer() for _, c := range contentTable { for _, e := range errTable { stream := &mockExpandStream{exp: strings.Fields(c), t: t} err := server.Expand(&pb.ExpandRequest{Content: c, Error: e}, stream) status, _ := status.FromError(err) if int32(status.Code()) != e.GetCode() { t.Errorf("Expand expected stream to return status with code %d but code %d", status.Code(), e.GetCode()) } stream.verify(e == nil) } } } func TestExpandWithWaitTime(t *testing.T) { server := NewEchoServer() //This stream should take at least 300ms to complete because there are 7 messages, and we wait 50ms between sending each message. content := "This stream should take 300ms to complete" stream := &mockExpandStream{exp: strings.Fields(content), t: t} streamWaitTime := durationpb.New(time.Duration(50) * time.Millisecond) start := time.Now() err := server.Expand(&pb.ExpandRequest{Content: content, StreamWaitTime: streamWaitTime}, stream) actualTimeSpent := int(time.Since(start).Milliseconds()) expectedTimeSpent := 300 if actualTimeSpent < expectedTimeSpent { t.Errorf("Expand stream should take at least %d ms to complete, but it only took %d ms", expectedTimeSpent, actualTimeSpent) } stream.verify(err == nil) } type errorExpandStream struct { err error pb.Echo_ExpandServer } func (s *errorExpandStream) Send(resp *pb.EchoResponse) error { return s.err } func TestExpand_streamErr(t *testing.T) { e := errors.New("Test Error") stream := &errorExpandStream{err: e} server := NewEchoServer() err := server.Expand(&pb.ExpandRequest{Content: "Hello World"}, stream) if e != err { t.Error("Expand expected to pass through stream errors.") } } type mockCollectStream struct { reqs []*pb.EchoRequest head []string trail []string exp *string t *testing.T pb.Echo_CollectServer } func (m *mockCollectStream) SendAndClose(r *pb.EchoResponse) error { if m.exp == nil { m.t.Errorf("Collect Stream SendAndClose called unexpectedly") } if r.GetContent() != *m.exp { m.t.Errorf("Collect expected to return '%s', but returned '%s'", *m.exp, r.GetContent()) } return nil } func (m *mockCollectStream) Recv() (*pb.EchoRequest, error) { if len(m.reqs) > 0 { ret := m.reqs[0] m.reqs = m.reqs[1:] return ret, nil } return nil, io.EOF } func (m *mockCollectStream) Context() context.Context { return appendTestOutgoingMetadata(context.Background(), &mockSTS{stream: m, t: m.t}) } func (m *mockCollectStream) SetHeader(md metadata.MD) error { m.head = append(m.head, md.Get("x-goog-request-params")...) m.head = append(m.head, md.Get("traceparent")...) m.head = append(m.head, md.Get("tracestate")...) return nil } func (m *mockCollectStream) SetTrailer(md metadata.MD) { m.trail = append(m.trail, md.Get("showcase-trailer")...) } func (m *mockCollectStream) verify(expectHeadersAndTrailers bool) { if expectHeadersAndTrailers && (!reflect.DeepEqual([]string{"show", "case"}, m.trail) || !reflect.DeepEqual([]string{"showcaseHeader", "anotherHeader", "00-traceid-spanid-01", "some-state"}, m.head)) { m.t.Errorf("Collect did not get all expected trailers.\nGot these headers: %+v\nGot these trailers: %+v", m.head, m.trail) } } func TestCollect(t *testing.T) { strPtr := func(s string) *string { return &s } tests := []struct { reqs []string exp *string err *spb.Status }{ {[]string{"Hello", "", "World"}, strPtr("Hello World"), nil}, {[]string{"Hello", "World"}, strPtr("Hello World"), &spb.Status{Code: int32(codes.OK)}}, {[]string{"Hello", "World"}, nil, &spb.Status{Code: int32(codes.InvalidArgument)}}, {[]string{}, nil, &spb.Status{Code: int32(codes.InvalidArgument)}}, {[]string{}, strPtr(""), nil}, } server := NewEchoServer() for _, test := range tests { reqs := []*pb.EchoRequest{} for _, req := range test.reqs { reqs = append(reqs, &pb.EchoRequest{Response: &pb.EchoRequest_Content{Content: req}}) } if test.err != nil { reqs = append(reqs, &pb.EchoRequest{Response: &pb.EchoRequest_Error{Error: test.err}}) } mockStream := &mockCollectStream{reqs: reqs, exp: test.exp, t: t} err := server.Collect(mockStream) expCode := status.FromProto(test.err).Code() s, _ := status.FromError(err) if expCode != s.Code() { t.Errorf("Collect expected to return with code %d, but returned %d", expCode, s.Code()) } mockStream.verify(test.err == nil) } } type errorCollectStream struct { err error pb.Echo_CollectServer } func (s *errorCollectStream) Recv() (*pb.EchoRequest, error) { return nil, s.err } func TestCollect_streamErr(t *testing.T) { e := errors.New("Test Error") stream := &errorCollectStream{err: e} server := NewEchoServer() err := server.Collect(stream) if e != err { t.Error("Collect expected to pass through stream errors.") } } type mockChatStream struct { reqs []*pb.EchoRequest head []string trail []string curr *pb.EchoRequest t *testing.T pb.Echo_ChatServer } func (m *mockChatStream) Recv() (*pb.EchoRequest, error) { if len(m.reqs) > 0 { m.curr = m.reqs[0] m.reqs = m.reqs[1:] return m.curr, nil } return nil, io.EOF } func (m *mockChatStream) Send(r *pb.EchoResponse) error { if m.curr == nil { m.t.Errorf("Chat unexpectedly tried to send content.") } if r.GetContent() != m.curr.GetContent() { m.t.Errorf("Chat expected to send content %s, but sent %s", m.curr.GetContent(), r.GetContent()) m.curr = nil } return nil } func (m *mockChatStream) Context() context.Context { return appendTestOutgoingMetadata(context.Background(), &mockSTS{stream: m, t: m.t}) } func (m *mockChatStream) SetHeader(md metadata.MD) error { m.head = append(m.head, md.Get("x-goog-request-params")...) m.head = append(m.head, md.Get("traceparent")...) m.head = append(m.head, md.Get("tracestate")...) return nil } func (m *mockChatStream) SetTrailer(md metadata.MD) { m.trail = append(m.trail, md.Get("showcase-trailer")...) } func (m *mockChatStream) verify(expectHeadersAndTrailers bool) { if expectHeadersAndTrailers && (!reflect.DeepEqual([]string{"show", "case"}, m.trail) || !reflect.DeepEqual([]string{"showcaseHeader", "anotherHeader", "00-traceid-spanid-01", "some-state"}, m.head)) { m.t.Errorf("Chat did not get all expected trailers.\nGot these headers: %+v\nGot these trailers: %+v", m.head, m.trail) } } func TestChat(t *testing.T) { tests := []struct { reqs []string err *spb.Status }{ {[]string{"Hello", "World"}, nil}, {[]string{"Hello", "World"}, &spb.Status{Code: int32(codes.InvalidArgument)}}, {[]string{}, &spb.Status{Code: int32(codes.InvalidArgument)}}, } server := NewEchoServer() for _, test := range tests { reqs := []*pb.EchoRequest{} for _, req := range test.reqs { reqs = append(reqs, &pb.EchoRequest{Response: &pb.EchoRequest_Content{Content: req}}) } if test.err != nil { reqs = append(reqs, &pb.EchoRequest{Response: &pb.EchoRequest_Error{Error: test.err}}) } mockStream := &mockChatStream{reqs: reqs, t: t} err := server.Chat(mockStream) expCode := status.FromProto(test.err).Code() s, _ := status.FromError(err) if expCode != s.Code() { t.Errorf("Chat expected to return status with code %d, but returned %d", expCode, s.Code()) } mockStream.verify(test.err == nil) } } func TestEchoErrorDetails_single(t *testing.T) { tests := []struct { text string expected *errdetails.ErrorInfo }{ {"Spanish rain", &errdetails.ErrorInfo{Reason: "Spanish rain"}}, {"", &errdetails.ErrorInfo{Reason: ""}}, } server := NewEchoServer() for idx, test := range tests { request := &pb.EchoErrorDetailsRequest{SingleDetailText: test.text} out, err := server.EchoErrorDetails(context.Background(), request) if err != nil { t.Errorf("[%d] error calling EchoErrorSingleDetail(): %v", idx, err) continue } if out.MultipleDetails != nil { t.Errorf("[%d] expected no MultipleDetails, but got: %#v", idx, out.MultipleDetails) } if len(test.text) == 0 { if out.SingleDetail != nil { t.Errorf("[%d] expected no SingleDetail, but got: %#v", idx, out.SingleDetail) } continue } if out.SingleDetail == nil { t.Errorf("[%d] no SingleDetail returned", idx) continue } if out.SingleDetail.Error == nil { t.Errorf("[%d] no SingleDetail.Error returned", idx) continue } if out.SingleDetail.Error.Details == nil { t.Errorf("[%d] no SingleDetail.Error.Details returned", idx) continue } if got, want := out.SingleDetail.Error.Details.TypeUrl, "type.googleapis.com/google.rpc.ErrorInfo"; got != want { t.Errorf("[%d] expected type URL %q; got %q ", idx, want, got) } unmarshalledError := &errdetails.ErrorInfo{} if err := out.SingleDetail.Error.Details.UnmarshalTo(unmarshalledError); err != nil { t.Errorf("[%d] error unmarshalling to ErrorInfo: %v", idx, err) } if got, want := unmarshalledError, test.expected; !proto.Equal(got, want) { t.Errorf("[%d] expected ErrorInfo %v; got %v ", idx, want, got) } } } func TestEchoErrorDetails_multiple(t *testing.T) { tests := []struct { text []string expected []*errdetails.ErrorInfo }{ { []string{"rain", "snow", "hail", "sleet", "fog"}, []*errdetails.ErrorInfo{ {Reason: "rain"}, {Reason: "snow"}, {Reason: "hail"}, {Reason: "sleet"}, {Reason: "fog"}, }, }, {nil, nil}, } server := NewEchoServer() for idx, test := range tests { request := &pb.EchoErrorDetailsRequest{MultiDetailText: test.text} out, err := server.EchoErrorDetails(context.Background(), request) if err != nil { t.Errorf("[%d] error calling EchoErrorDetails(): %v", idx, err) continue } if out.SingleDetail != nil { t.Errorf("[%d] expected no SingleDetail, but got: %#v", idx, out.SingleDetail) } if len(test.text) == 0 { if out.MultipleDetails != nil { t.Errorf("[%d] expected no MultipleDetails, but got %#v", idx, out.MultipleDetails) } continue } if out.MultipleDetails == nil { t.Errorf("[%d] no MultipleDetails returned", idx) continue } if out.MultipleDetails.Error == nil { t.Errorf("[%d] no MultipleDetails.Error returned", idx) continue } if out.MultipleDetails.Error.Details == nil { t.Errorf("[%d] no MultipleDetails.Error.Details returned", idx) continue } if got, want := len(out.MultipleDetails.Error.Details), len(test.expected); got != want { t.Errorf("[%d] expected %d MultipleDetails.Error.Details, got %d", idx, want, got) } for whichDetail, detail := range out.MultipleDetails.Error.Details { if got, want := detail.TypeUrl, "type.googleapis.com/google.rpc.ErrorInfo"; got != want { t.Errorf("[%d:%d] expected type URL %q; got %q ", idx, whichDetail, want, got) } unmarshalledError := &errdetails.ErrorInfo{} if err := detail.UnmarshalTo(unmarshalledError); err != nil { t.Errorf("[%d:%d] error unmarshalling to ErrorInfo: %v", idx, whichDetail, err) } if got, want := unmarshalledError, test.expected[whichDetail]; !proto.Equal(got, want) { t.Errorf("[%d:%d] expected ErrorInfo %v; got %v ", idx, whichDetail, want, got) } } } } func TestFailEchoWithDetails(t *testing.T) { // We only check that all RPC calls to FailEchoWithDetails // return the expected sequence of error detail types. We // don't check the contents of the messages, except for the // PoetryError detail. expectedDetailTypes := []reflect.Type{ reflect.TypeOf((*errdetails.ErrorInfo)(nil)), reflect.TypeOf((*errdetails.LocalizedMessage)(nil)), reflect.TypeOf((*pb.PoetryError)(nil)), reflect.TypeOf((*errdetails.RetryInfo)(nil)), reflect.TypeOf((*errdetails.DebugInfo)(nil)), reflect.TypeOf((*errdetails.QuotaFailure)(nil)), reflect.TypeOf((*errdetails.PreconditionFailure)(nil)), reflect.TypeOf((*errdetails.BadRequest)(nil)), reflect.TypeOf((*errdetails.RequestInfo)(nil)), reflect.TypeOf((*errdetails.ResourceInfo)(nil)), reflect.TypeOf((*errdetails.Help)(nil)), } tests := []struct{ message string }{ {""}, // error response will have a default value {"two paths diverged in a wood"}, } server := NewEchoServer() for testIdx, oneTest := range tests { request := &pb.FailEchoWithDetailsRequest{} if oneTest.message != "" { request.Message = oneTest.message } response, err := server.FailEchoWithDetails(context.Background(), request) if err == nil { t.Errorf("[%d] expected error upon calling FailEchoWithDetails. Response was: %+v", testIdx, response) } status, _ := status.FromError(err) if got, want := status.Code(), codes.Aborted; got != want { t.Errorf("[%d] unexpected gRPC code: want %v, got %v", testIdx, want, got) } allDetails := status.Details() if got, want := len(allDetails), len(expectedDetailTypes); got != want { t.Errorf("[%d] detail list length: : want %v, got %v", testIdx, want, got) } for detailIdx, oneDetail := range allDetails { if got, want := reflect.TypeOf(oneDetail), expectedDetailTypes[detailIdx]; got != want { t.Errorf("[%d:%d] want detail of type %v, got %v", testIdx, detailIdx, want, got) } // In what follows, we check the internals of PoetryError. if detailIdx != 2 { continue } poetryError, ok := oneDetail.(*pb.PoetryError) if !ok { t.Fatalf("[%d:%d] could not convert detail to a PoetryError", testIdx, detailIdx) continue } wantPoem := "roses are red" if oneTest.message != "" { wantPoem = oneTest.message } if got, want := poetryError.Poem, wantPoem; got != want { t.Errorf("[%d:%d] PoetryError.poem: want %q, got %q", testIdx, detailIdx, want, got) } } } } type errorChatStream struct { err error pb.Echo_ChatServer } func (s *errorChatStream) Recv() (*pb.EchoRequest, error) { return nil, s.err } func TestChat_streamErr(t *testing.T) { e := errors.New("Test Error") stream := &errorChatStream{err: e} server := NewEchoServer() err := server.Chat(stream) if e != err { t.Error("Chat expected to pass through stream errors.") } } func TestPagedExpand_invalidArgs(t *testing.T) { tests := []*pb.PagedExpandRequest{ {PageSize: -1}, {PageToken: "-1"}, {PageToken: "BOGUS"}, {Content: "one", PageToken: "1"}, {Content: "one", PageToken: "2"}, } server := NewEchoServer() for _, in := range tests { _, err := server.PagedExpand(context.Background(), in) s, _ := status.FromError(err) if s.Code() != codes.InvalidArgument { t.Errorf("PagedExpand() expected error code: %d, got error code %d", codes.InvalidArgument, s.Code()) } } } func TestPagedExpand(t *testing.T) { tests := []struct { in *pb.PagedExpandRequest out *pb.PagedExpandResponse }{ { &pb.PagedExpandRequest{Content: "Hello world!"}, &pb.PagedExpandResponse{ Responses: []*pb.EchoResponse{ {Content: "Hello"}, {Content: "world!"}, }, }, }, { &pb.PagedExpandRequest{PageSize: 3, Content: "Hello world!"}, &pb.PagedExpandResponse{ Responses: []*pb.EchoResponse{ {Content: "Hello"}, {Content: "world!"}, }, }, }, { &pb.PagedExpandRequest{ PageSize: 3, Content: "The rain in Spain falls mainly on the plain!", }, &pb.PagedExpandResponse{ Responses: []*pb.EchoResponse{ {Content: "The"}, {Content: "rain"}, {Content: "in"}, }, NextPageToken: "3", }, }, { &pb.PagedExpandRequest{ PageSize: 3, PageToken: "3", Content: "The rain in Spain falls mainly on the plain!", }, &pb.PagedExpandResponse{ Responses: []*pb.EchoResponse{ {Content: "Spain"}, {Content: "falls"}, {Content: "mainly"}, }, NextPageToken: "6", }, }, } server := NewEchoServer() for _, test := range tests { mockStream := &mockUnaryStream{t: t} ctx := appendTestOutgoingMetadata(context.Background(), &mockSTS{t: t, stream: mockStream}) out, err := server.PagedExpand(ctx, test.in) if err != nil { t.Error(err) } if !proto.Equal(test.out, out) { t.Errorf("PagedExpand with input %q, expected: %q, got: %q", test.in.String(), test.out.String(), out.String()) } mockStream.verify(err == nil) } } // NOTE: The TestPagedExpandLegacy*() tests mirror the TestPagedExpand*() tests. func TestPagedExpandLegacy_invalidArgs(t *testing.T) { tests := []*pb.PagedExpandLegacyRequest{ {MaxResults: -1}, {PageToken: "-1"}, {PageToken: "BOGUS"}, {Content: "one", PageToken: "1"}, {Content: "one", PageToken: "2"}, } server := NewEchoServer() for _, in := range tests { _, err := server.PagedExpandLegacy(context.Background(), in) s, _ := status.FromError(err) if s.Code() != codes.InvalidArgument { t.Errorf("PagedExpandLegacy() expected error code: %d, got error code %d", codes.InvalidArgument, s.Code()) } } } func TestPagedExpandLegacy(t *testing.T) { tests := []struct { in *pb.PagedExpandLegacyRequest out *pb.PagedExpandResponse }{ { &pb.PagedExpandLegacyRequest{Content: "Hello world!"}, &pb.PagedExpandResponse{ Responses: []*pb.EchoResponse{ {Content: "Hello"}, {Content: "world!"}, }, }, }, { &pb.PagedExpandLegacyRequest{MaxResults: 3, Content: "Hello world!"}, &pb.PagedExpandResponse{ Responses: []*pb.EchoResponse{ {Content: "Hello"}, {Content: "world!"}, }, }, }, { &pb.PagedExpandLegacyRequest{ MaxResults: 3, Content: "The rain in Spain falls mainly on the plain!", }, &pb.PagedExpandResponse{ Responses: []*pb.EchoResponse{ {Content: "The"}, {Content: "rain"}, {Content: "in"}, }, NextPageToken: "3", }, }, { &pb.PagedExpandLegacyRequest{ MaxResults: 3, PageToken: "3", Content: "The rain in Spain falls mainly on the plain!", }, &pb.PagedExpandResponse{ Responses: []*pb.EchoResponse{ {Content: "Spain"}, {Content: "falls"}, {Content: "mainly"}, }, NextPageToken: "6", }, }, } server := NewEchoServer() for _, test := range tests { mockStream := &mockUnaryStream{t: t} ctx := appendTestOutgoingMetadata(context.Background(), &mockSTS{t: t, stream: mockStream}) out, err := server.PagedExpandLegacy(ctx, test.in) if err != nil { t.Error(err) } if !proto.Equal(test.out, out) { t.Errorf("PagedExpandLegacy with input %q, expected: %q, got: %q", test.in.String(), test.out.String(), out.String()) } mockStream.verify(err == nil) } } func TestPagedExpandLegacyMapped_invalidArgs(t *testing.T) { tests := []*pb.PagedExpandRequest{ {PageSize: -1}, {PageToken: "-1"}, {PageToken: "BOGUS"}, {Content: "one", PageToken: "1"}, {Content: "one", PageToken: "2"}, } server := NewEchoServer() for _, in := range tests { _, err := server.PagedExpandLegacyMapped(context.Background(), in) s, _ := status.FromError(err) if s.Code() != codes.InvalidArgument { t.Errorf("PagedExpandLegacyMapped() expected error code: %d, got error code %d", codes.InvalidArgument, s.Code()) } } } func TestPagedExpandLegacyMapped(t *testing.T) { text := "It was the best of times, it was the worst of times" tests := []struct { in *pb.PagedExpandRequest out *pb.PagedExpandLegacyMappedResponse }{ { &pb.PagedExpandRequest{Content: text}, &pb.PagedExpandLegacyMappedResponse{ Alphabetized: map[string]*pb.PagedExpandResponseList{ "b": {Words: []string{"best"}}, "I": {Words: []string{"It"}}, "i": {Words: []string{"it"}}, "o": {Words: []string{"of", "of"}}, "t": {Words: []string{"the", "times,", "the", "times"}}, "w": {Words: []string{"was", "was", "worst"}}, }, }, }, { &pb.PagedExpandRequest{PageSize: 1, Content: text}, &pb.PagedExpandLegacyMappedResponse{ Alphabetized: map[string]*pb.PagedExpandResponseList{ "I": {Words: []string{"It"}}, "b": {Words: []string{}}, "i": {Words: []string{}}, "o": {Words: []string{}}, "t": {Words: []string{}}, "w": {Words: []string{}}, }, NextPageToken: "1", }, }, { &pb.PagedExpandRequest{PageSize: 4, PageToken: "2", Content: text}, &pb.PagedExpandLegacyMappedResponse{ Alphabetized: map[string]*pb.PagedExpandResponseList{ "b": {Words: []string{"best"}}, "I": {Words: []string{}}, "i": {Words: []string{}}, "o": {Words: []string{"of"}}, "t": {Words: []string{"the", "times,"}}, "w": {Words: []string{}}, }, NextPageToken: "6", }, }, { &pb.PagedExpandRequest{PageSize: 4, PageToken: "8", Content: text}, &pb.PagedExpandLegacyMappedResponse{ Alphabetized: map[string]*pb.PagedExpandResponseList{ "b": {Words: []string{}}, "I": {Words: []string{}}, "i": {Words: []string{}}, "o": {Words: []string{"of"}}, "t": {Words: []string{"the", "times"}}, "w": {Words: []string{"worst"}}, }, }, }, } server := NewEchoServer() for _, test := range tests { mockStream := &mockUnaryStream{t: t} ctx := appendTestOutgoingMetadata(context.Background(), &mockSTS{t: t, stream: mockStream}) out, err := server.PagedExpandLegacyMapped(ctx, test.in) if err != nil { t.Error(err) } if !proto.Equal(test.out, out) { t.Errorf("PagedExpandLegacyMapped with input %q:\n expected: %#v\n got: %#v\n", test.in.String(), test.out.String(), out.String()) } mockStream.verify(err == nil) } } func TestWait(t *testing.T) { endTime, _ := ptypes.TimestampProto(time.Now()) req := &pb.WaitRequest{End: &pb.WaitRequest_EndTime{EndTime: endTime}} waiter := &mockWaiter{} server := &echoServerImpl{waiter: waiter} mockStream := &mockUnaryStream{t: t} ctx := appendTestOutgoingMetadata(context.Background(), &mockSTS{t: t, stream: mockStream}) server.Wait(ctx, req) if !proto.Equal(waiter.req, req) { t.Error("Expected echo.Wait to defer to waiter.") } mockStream.verify(true) } func TestBlockSuccess(t *testing.T) { tests := []struct { seconds int64 nanos int32 resp string }{ {1, int32(1000), "hello"}, {5, int32(10), "world"}, } for _, test := range tests { waiter := &mockWaiter{} server := &echoServerImpl{waiter: waiter} in := &pb.BlockRequest{ ResponseDelay: &durpb.Duration{ Seconds: test.seconds, Nanos: test.nanos, }, Response: &pb.BlockRequest_Success{ Success: &pb.BlockResponse{Content: test.resp}, }, } mockStream := &mockUnaryStream{t: t} ctx := appendTestOutgoingMetadata(context.Background(), &mockSTS{t: t, stream: mockStream}) out, err := server.Block(ctx, in) if err != nil { t.Error(err) } if out.GetContent() != test.resp { t.Errorf("Expected Wait test to return %s, but returned %s", out.GetContent(), test.resp) } mockStream.verify(err == nil) } } func TestBlockError(t *testing.T) { tests := []struct { seconds int64 nanos int32 code codes.Code }{ {0, int32(0), codes.InvalidArgument}, {2, int32(1000), codes.Unavailable}, } for _, test := range tests { waiter := &mockWaiter{} server := &echoServerImpl{waiter: waiter} in := &pb.BlockRequest{ ResponseDelay: &durpb.Duration{ Seconds: test.seconds, Nanos: test.nanos, }, Response: &pb.BlockRequest_Error{ Error: status.New(test.code, "").Proto(), }, } out, err := server.Block(context.Background(), in) if out != nil { t.Errorf("Block: Expected to error with code %d but returned success", test.code) } s, _ := status.FromError(err) if s.Code() != test.code { t.Errorf("Block: Expected to error with code %d but errored with code %d", test.code, s.Code()) } } } func appendTestOutgoingMetadata(ctx context.Context, stream grpc.ServerTransportStream) context.Context { ctx = grpc.NewContextWithServerTransportStream(ctx, stream) ctx = metadata.NewIncomingContext(ctx, metadata.Pairs("showcase-trailer", "show", "showcase-trailer", "case", "trailer", "trail", "x-goog-request-params", "showcaseHeader", "x-goog-request-params", "anotherHeader", "header", "head", "x-goog-api-version", "apiVersion", "traceparent", "00-traceid-spanid-01", "tracestate", "some-state")) return ctx } ================================================ FILE: server/services/iam_policy_service.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package services import ( "context" "sync" iampb "cloud.google.com/go/iam/apiv1/iampb" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" ) var missingResource error = status.Error(codes.InvalidArgument, "Missing required argument: resource") var missingPolicy error = status.Error(codes.InvalidArgument, "Missing required argument: policy") var resourceDoesNotExist error = status.Error(codes.NotFound, "Requested resource has no Policy") // NewIAMPolicyServer returns a new LocationsServer for the Showcase API. func NewIAMPolicyServer() iampb.IAMPolicyServer { return &iamPolicyServerImpl{ policies: map[string]*iampb.Policy{}, } } type iamPolicyServerImpl struct { mu sync.Mutex // The key is the resource name. // The value is the IAM Policy assigned to the resource. policies map[string]*iampb.Policy } // GetIamPolicy retrieves the Policy for the named resource, if it has one. func (i *iamPolicyServerImpl) GetIamPolicy(ctx context.Context, in *iampb.GetIamPolicyRequest) (*iampb.Policy, error) { if in.GetResource() == "" { return nil, missingResource } i.mu.Lock() defer i.mu.Unlock() p, ok := i.policies[in.GetResource()] if !ok { return nil, resourceDoesNotExist } res := proto.Clone(p) return res.(*iampb.Policy), nil } // SetIamPolicy assigns the given Policy to the resource. func (i *iamPolicyServerImpl) SetIamPolicy(ctx context.Context, in *iampb.SetIamPolicyRequest) (*iampb.Policy, error) { if in.GetResource() == "" { return nil, missingResource } if in.GetPolicy() == nil { return nil, missingPolicy } i.mu.Lock() defer i.mu.Unlock() clone := proto.Clone(in.GetPolicy()) p := clone.(*iampb.Policy) i.policies[in.GetResource()] = p return in.GetPolicy(), nil } // TestIamPermissions verifies that the requested resource has been Set at one point, and echoes the back permissions to be tested. func (i *iamPolicyServerImpl) TestIamPermissions(ctx context.Context, in *iampb.TestIamPermissionsRequest) (*iampb.TestIamPermissionsResponse, error) { if in.GetResource() == "" { return nil, missingResource } i.mu.Lock() defer i.mu.Unlock() if _, ok := i.policies[in.GetResource()]; !ok { return nil, resourceDoesNotExist } return &iampb.TestIamPermissionsResponse{ Permissions: in.GetPermissions(), }, nil } ================================================ FILE: server/services/iam_policy_service_test.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package services import ( "context" "testing" iampb "cloud.google.com/go/iam/apiv1/iampb" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "google.golang.org/protobuf/proto" ) func TestIamPolicySetGetTest(t *testing.T) { s := NewIAMPolicyServer() resource := "projects/myproject/foos/foo123" policy := &iampb.Policy{ Version: 1, Bindings: []*iampb.Binding{ {Role: "project/fooEditor"}, }, } permissions := []string{"foo.write", "foo.read"} p, err := s.SetIamPolicy(context.Background(), &iampb.SetIamPolicyRequest{Resource: resource, Policy: policy}) if err != nil { t.Errorf("TestIamPolicySetGetTest > SetIamPolicy: unexpected error %q", err) } if diff := cmp.Diff(p, policy, cmp.Comparer(proto.Equal)); diff != "" { t.Errorf("TestIamPolicySetGetTest > SetIamPolicy: got(-),want(+):\n%s", diff) } p, err = s.GetIamPolicy(context.Background(), &iampb.GetIamPolicyRequest{Resource: resource}) if err != nil { t.Errorf("TestIamPolicySetGetTest > GetIamPolicy: unexpected error %q", err) } if diff := cmp.Diff(p, policy, cmp.Comparer(proto.Equal)); diff != "" { t.Errorf("TestIamPolicySetGetTest > GetIamPolicy: got(-),want(+):\n%s", diff) } res, err := s.TestIamPermissions(context.Background(), &iampb.TestIamPermissionsRequest{ Resource: resource, Permissions: permissions, }) if err != nil { t.Errorf("TestIamPolicySetGetTest > TestIamPermissions: unexpected error %q", err) } if diff := cmp.Diff(res.Permissions, permissions); diff != "" { t.Errorf("TestIamPolicySetGetTest > TestIamPermissions: got(-),want(+):\n%s", diff) } } func TestGetIamPolicy_errors(t *testing.T) { s := NewIAMPolicyServer() for _, tst := range []struct { name, resource string err error }{ { name: "missing resource field", err: missingResource, }, { name: "resource does not exist", resource: "foo/bar", err: resourceDoesNotExist, }, } { res, err := s.GetIamPolicy(context.Background(), &iampb.GetIamPolicyRequest{Resource: tst.resource}) if err == nil { t.Errorf("GetIamPolicy_errors(%s): expected an error but got response: %v", tst.name, res) } if diff := cmp.Diff(err, tst.err, cmpopts.EquateErrors()); diff != "" { t.Errorf("GetIamPolicy_errors(%s): got(-),want(+):\n%s", tst.name, diff) } } } func TestSetIamPolicy_errors(t *testing.T) { s := NewIAMPolicyServer() for _, tst := range []struct { name, resource string err error }{ { name: "missing resource field", err: missingResource, }, { name: "missing policy field", resource: "foo/bar", err: missingPolicy, }, } { res, err := s.SetIamPolicy(context.Background(), &iampb.SetIamPolicyRequest{Resource: tst.resource}) if err == nil { t.Errorf("SetIamPolicy_errors(%s): expected an error but got response: %v", tst.name, res) } if diff := cmp.Diff(err, tst.err, cmpopts.EquateErrors()); diff != "" { t.Errorf("SetIamPolicy_errors(%s): got(-),want(+):\n%s", tst.name, diff) } } } func TestTestIamPermissions_errors(t *testing.T) { s := NewIAMPolicyServer() for _, tst := range []struct { name, resource string err error }{ { name: "missing resource field", err: missingResource, }, { name: "resource does not exist", resource: "foo/bar", err: resourceDoesNotExist, }, } { res, err := s.TestIamPermissions(context.Background(), &iampb.TestIamPermissionsRequest{Resource: tst.resource}) if err == nil { t.Errorf("TestIamPermissions_errors(%s): expected an error but got response: %v", tst.name, res) } if diff := cmp.Diff(err, tst.err, cmpopts.EquateErrors()); diff != "" { t.Errorf("TestIamPermissions_errors(%s): got(-),want(+):\n%s", tst.name, diff) } } } ================================================ FILE: server/services/identity_service.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package services import ( "context" "fmt" "sync" "github.com/golang/protobuf/ptypes" "github.com/golang/protobuf/ptypes/empty" "github.com/googleapis/gapic-showcase/server" pb "github.com/googleapis/gapic-showcase/server/genproto" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" ) // NewIdentityServer returns a new instance of showcase identity server. func NewIdentityServer() pb.IdentityServer { return &identityServerImpl{ token: server.NewTokenGenerator(), keys: map[string]int{}, } } type userEntry struct { user *pb.User deleted bool } // ReadOnlyIdentityServer provides a read-only interface of an identity server. type ReadOnlyIdentityServer interface { GetUser(context.Context, *pb.GetUserRequest) (*pb.User, error) ListUsers(context.Context, *pb.ListUsersRequest) (*pb.ListUsersResponse, error) } type identityServerImpl struct { uid server.UniqID token server.TokenGenerator mu sync.Mutex keys map[string]int users []userEntry } // Creates a user. func (s *identityServerImpl) CreateUser(_ context.Context, in *pb.CreateUserRequest) (*pb.User, error) { s.mu.Lock() defer s.mu.Unlock() u := in.GetUser() // Ignore passed in name. u.Name = "" err := s.validate(u) if err != nil { return nil, err } // Assign info. id := s.uid.Next() name := fmt.Sprintf("users/%d", id) now := ptypes.TimestampNow() u.Name = name u.CreateTime = now u.UpdateTime = now // Insert. index := len(s.users) s.users = append(s.users, userEntry{user: u}) s.keys[name] = index return u, nil } // Retrieves the User with the given uri. func (s *identityServerImpl) GetUser(_ context.Context, in *pb.GetUserRequest) (*pb.User, error) { s.mu.Lock() defer s.mu.Unlock() name := in.GetName() if i, ok := s.keys[name]; ok { entry := s.users[i] if !entry.deleted { return entry.user, nil } } return nil, status.Errorf( codes.NotFound, "A user with name %s not found.", name) } // Updates a user. func (s *identityServerImpl) UpdateUser(_ context.Context, in *pb.UpdateUserRequest) (*pb.User, error) { s.mu.Lock() defer s.mu.Unlock() mask := in.GetUpdateMask() u := in.GetUser() i, ok := s.keys[u.GetName()] if !ok || s.users[i].deleted { return nil, status.Errorf( codes.NotFound, "A user with name %s not found.", u.GetName()) } err := s.validate(u) if err != nil { return nil, err } // Update store. existing := s.users[i].user updated := proto.Clone(existing).(*pb.User) applyFieldMask(u.ProtoReflect(), updated.ProtoReflect(), mask.GetPaths()) updated.CreateTime = existing.GetCreateTime() updated.UpdateTime = ptypes.TimestampNow() s.users[i] = userEntry{user: updated} return updated, nil } // Deletes a user, their profile, and all of their authored messages. func (s *identityServerImpl) DeleteUser(_ context.Context, in *pb.DeleteUserRequest) (*empty.Empty, error) { s.mu.Lock() defer s.mu.Unlock() i, ok := s.keys[in.GetName()] if !ok { return nil, status.Errorf( codes.NotFound, "A user with name %s not found.", in.GetName()) } entry := s.users[i] s.users[i] = userEntry{user: entry.user, deleted: true} return &empty.Empty{}, nil } // Lists all users. func (s *identityServerImpl) ListUsers(_ context.Context, in *pb.ListUsersRequest) (*pb.ListUsersResponse, error) { start, err := s.token.GetIndex(in.GetPageToken()) if err != nil { return nil, err } offset := 0 users := []*pb.User{} for _, entry := range s.users[start:] { offset++ if entry.deleted { continue } users = append(users, entry.user) if len(users) >= int(in.GetPageSize()) { break } } nextToken := "" if start+offset < len(s.users) { nextToken = s.token.ForIndex(start + offset) } return &pb.ListUsersResponse{Users: users, NextPageToken: nextToken}, nil } func (s *identityServerImpl) validate(u *pb.User) error { // Validate Required Fields. if u.GetDisplayName() == "" { return status.Errorf( codes.InvalidArgument, "The field `display_name` is required.") } if u.GetEmail() == "" { return status.Errorf( codes.InvalidArgument, "The field `email` is required.") } // Validate Unique Fields. for _, x := range s.users { if x.deleted { continue } if (u.GetEmail() == x.user.GetEmail()) && (u.GetName() != x.user.GetName()) { return status.Errorf( codes.AlreadyExists, "A user with email %s already exists.", u.GetEmail()) } } return nil } ================================================ FILE: server/services/identity_service_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package services import ( "context" "encoding/base64" "strings" "testing" "github.com/google/go-cmp/cmp" "github.com/googleapis/gapic-showcase/server" pb "github.com/googleapis/gapic-showcase/server/genproto" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/fieldmaskpb" ) func Test_User_lifecycle(t *testing.T) { s := NewIdentityServer() first, err := s.CreateUser( context.Background(), &pb.CreateUserRequest{ User: &pb.User{DisplayName: "ekkodog", Email: "ekko@example.com", Nickname: proto.String("ekko"), Age: proto.Int32(26)}, }) if err != nil { t.Errorf("Create: unexpected err %+v", err) } delete, err := s.CreateUser( context.Background(), &pb.CreateUserRequest{ User: &pb.User{DisplayName: "mishacat", Email: "misha@example.com"}, }) if err != nil { t.Errorf("Create: unexpected err %+v", err) } _, err = s.DeleteUser( context.Background(), &pb.DeleteUserRequest{Name: delete.Name}) if err != nil { t.Errorf("Delete: unexpected err %+v", err) } created, err := s.CreateUser( context.Background(), &pb.CreateUserRequest{ User: &pb.User{ DisplayName: "rumbledog", Email: "rumble@example.com", Age: proto.Int32(42), EnableNotifications: proto.Bool(false), HeightFeet: proto.Float64(3.5), Nickname: proto.String("rumble"), }, }) if err != nil { t.Errorf("Create: unexpected err %+v", err) } got, err := s.GetUser( context.Background(), &pb.GetUserRequest{Name: created.GetName()}) if err != nil { t.Errorf("Get: unexpected err %+v", err) } if !proto.Equal(created, got) { t.Error("Expected to get created user.") } // Make a copy of the User value, then unset proto3_optional fields // to scope the update to DisplayName and Nickname. clone := proto.Clone(got) u := clone.(*pb.User) u.DisplayName = "musubi" u.Nickname = proto.String("musu") u.Age = nil u.HeightFeet = nil u.EnableNotifications = nil updated, err := s.UpdateUser( context.Background(), &pb.UpdateUserRequest{User: u, UpdateMask: nil}) if err != nil { t.Errorf("Update: unexpected err %+v", err) } // Ensure the proto3_optional fields that were unset did not get updated. if updated.Age == nil { t.Errorf("UpdateUser().Age was unexpectedly set to nil") } if updated.HeightFeet == nil { t.Errorf("UpdateUser().HeightFeet was unexpectedly set to nil") } if updated.EnableNotifications == nil { t.Errorf("UpdateUser().EnableNotifications was unexpectedly set to nil") } got, err = s.GetUser( context.Background(), &pb.GetUserRequest{Name: updated.GetName()}) if err != nil { t.Errorf("Get: unexpected err %+v", err) } if !proto.Equal(updated, got) { t.Errorf("UpdateUser() = %+v, want %+v", got, updated) } r, err := s.ListUsers( context.Background(), &pb.ListUsersRequest{PageSize: 1, PageToken: ""}) if len(r.GetUsers()) != 1 { t.Errorf("List want: page size %d, got %d", 1, len(r.GetUsers())) } if !proto.Equal(first, r.GetUsers()[0]) { t.Errorf("List want: first user %+v, got %+v", first, r.GetUsers()[0]) } if r.GetNextPageToken() == "" { t.Error("List want: non empty next page token") } r, err = s.ListUsers( context.Background(), &pb.ListUsersRequest{PageSize: 10, PageToken: r.GetNextPageToken()}) if len(r.GetUsers()) != 1 { t.Errorf("List want: page size %d, got %d", 1, len(r.GetUsers())) } if !proto.Equal(got, r.GetUsers()[0]) { t.Errorf("List want: updated user %+v, got %+v", got, r.GetUsers()[0]) } if r.GetNextPageToken() != "" { t.Error("List want: empty next page token") } } func Test_Create_invalid(t *testing.T) { tests := []*pb.User{ {DisplayName: "", Email: "rumble@example.com"}, {DisplayName: "Rumble", Email: ""}, } s := NewIdentityServer() for _, u := range tests { _, err := s.CreateUser( context.Background(), &pb.CreateUserRequest{User: u}) status, _ := status.FromError(err) if status.Code() != codes.InvalidArgument { t.Errorf( "Create: Want error code %d got %d", codes.InvalidArgument, status.Code()) } } } func Test_Create_alreadyPresent(t *testing.T) { first := &pb.User{DisplayName: "Rumble", Email: "rumble@example.com"} second := &pb.User{DisplayName: "Musubi", Email: "rumble@example.com"} third := &pb.User{DisplayName: "Rumble", Email: "rumble@example.com"} s := NewIdentityServer() created, err := s.CreateUser(context.Background(), &pb.CreateUserRequest{User: first}) if err != nil { t.Errorf("Create: unexpected err %+v", err) } _, err = s.CreateUser(context.Background(), &pb.CreateUserRequest{User: second}) stat, _ := status.FromError(err) if stat.Code() != codes.AlreadyExists { t.Errorf( "Create: Want error code %d got %d", codes.AlreadyExists, stat.Code()) } third.Name = created.GetName() _, err = s.CreateUser(context.Background(), &pb.CreateUserRequest{User: third}) stat, _ = status.FromError(err) if stat.Code() != codes.AlreadyExists { t.Errorf( "Create: Want error code %d got %d", codes.AlreadyExists, stat.Code()) } } func Test_Create_deleted(t *testing.T) { s := NewIdentityServer() u := &pb.User{DisplayName: "Rumble", Email: "rumble@example.com"} u, err := s.CreateUser(context.Background(), &pb.CreateUserRequest{User: u}) if err != nil { t.Errorf("Create: unexpected error: %v", err) } _, err = s.DeleteUser(context.Background(), &pb.DeleteUserRequest{Name: u.GetName()}) if err != nil { t.Errorf("Delete: unexpected error: %v", err) } u, err = s.CreateUser(context.Background(), &pb.CreateUserRequest{User: u}) if err != nil { t.Errorf("Create: a using a deleted email should be allowed, got: %v", err) } } func Test_Get_notFound(t *testing.T) { s := NewIdentityServer() _, err := s.GetUser( context.Background(), &pb.GetUserRequest{Name: "Rumble"}) status, _ := status.FromError(err) if status.Code() != codes.NotFound { t.Errorf( "Get: Want error code %d got %d", codes.NotFound, status.Code()) } } func Test_Get_deleted(t *testing.T) { s := NewIdentityServer() created, err := s.CreateUser( context.Background(), &pb.CreateUserRequest{ User: &pb.User{DisplayName: "rumbledog", Email: "rumble@example.com"}, }) if err != nil { t.Errorf("Create: unexpected err %+v", err) } _, err = s.DeleteUser( context.Background(), &pb.DeleteUserRequest{Name: created.Name}) if err != nil { t.Errorf("Delete: unexpected err %+v", err) } _, err = s.GetUser( context.Background(), &pb.GetUserRequest{Name: created.Name}) status, _ := status.FromError(err) if status.Code() != codes.NotFound { t.Errorf( "Get deleted: Want error code %d got %d", codes.NotFound, status.Code()) } } func Test_Update_fieldmask(t *testing.T) { first := &pb.User{DisplayName: "Ekko", Email: "ekko@example.com"} second := &pb.User{DisplayName: "Foo", Email: "ekko@example.com"} paths := []string{"display_name"} s := NewIdentityServer() created, err := s.CreateUser( context.Background(), &pb.CreateUserRequest{User: first}) if err != nil { t.Errorf("Create: unexpected err %+v", err) } second.Name = created.GetName() got, err := s.UpdateUser( context.Background(), &pb.UpdateUserRequest{User: second, UpdateMask: &fieldmaskpb.FieldMask{Paths: paths}}) if err != nil { t.Fatal(err) } if diff := cmp.Diff(got.GetDisplayName(), second.GetDisplayName()); diff != "" { t.Errorf("Using update_mask %s, got(-),want(+):\n%s", strings.Join(paths, ","), diff) } } func Test_Update_notFound(t *testing.T) { s := NewIdentityServer() _, err := s.UpdateUser( context.Background(), &pb.UpdateUserRequest{ User: &pb.User{ Name: "Rumble", DisplayName: "rumbledog", Email: "rumble@example.com", }, UpdateMask: nil, }) status, _ := status.FromError(err) if status.Code() != codes.NotFound { t.Errorf( "Update: Want error code %d got %d", codes.NotFound, status.Code()) } } func Test_Update_invalid(t *testing.T) { first := []*pb.User{ {DisplayName: "Ekko", Email: "ekko@example.com"}, {DisplayName: "Rumble", Email: "rumble@example.com"}, } second := []*pb.User{ {DisplayName: "", Email: "ekko@example.com"}, {DisplayName: "Rumble", Email: ""}, } s := NewIdentityServer() for i, u := range first { created, err := s.CreateUser( context.Background(), &pb.CreateUserRequest{User: u}) if err != nil { t.Errorf("Create: unexpected err %+v", err) } second[i].Name = created.GetName() } for _, u := range second { _, err := s.UpdateUser( context.Background(), &pb.UpdateUserRequest{User: u, UpdateMask: nil}) status, _ := status.FromError(err) if status.Code() != codes.InvalidArgument { t.Errorf( "Update: Want error code %d got %d", codes.InvalidArgument, status.Code()) } } } func Test_Update_alreadyPresent(t *testing.T) { first := &pb.User{DisplayName: "Rumble", Email: "rumble@example.com"} second := &pb.User{DisplayName: "Ekko", Email: "ekko@example.com"} s := NewIdentityServer() first, err := s.CreateUser( context.Background(), &pb.CreateUserRequest{User: first}) if err != nil { t.Errorf("Create: unexpected err %+v", err) } second, err = s.CreateUser( context.Background(), &pb.CreateUserRequest{User: second}) if err != nil { t.Errorf("Create: unexpected err %+v", err) } second.Email = first.GetEmail() _, err = s.UpdateUser( context.Background(), &pb.UpdateUserRequest{User: second, UpdateMask: nil}) status, _ := status.FromError(err) if status.Code() != codes.AlreadyExists { t.Errorf( "Update: Want error code %d got %d", codes.AlreadyExists, status.Code()) } } func Test_Delete_notFound(t *testing.T) { s := NewIdentityServer() _, err := s.DeleteUser( context.Background(), &pb.DeleteUserRequest{Name: "Rumble"}) status, _ := status.FromError(err) if status.Code() != codes.NotFound { t.Errorf( "Delete: Want error code %d got %d", codes.NotFound, status.Code()) } } func Test_List_invalidToken(t *testing.T) { s := &identityServerImpl{ token: server.NewTokenGenerator(), keys: map[string]int{}, } tests := []string{ "1", // Not base64 encoded base64.StdEncoding.EncodeToString([]byte("1")), // No salt base64.StdEncoding.EncodeToString([]byte("EkkoRumble")), // Invalid index } for _, token := range tests { _, err := s.ListUsers( context.Background(), &pb.ListUsersRequest{PageSize: 1, PageToken: token}) status, _ := status.FromError(err) if status.Code() != codes.InvalidArgument { t.Errorf( "List: Want error code %d got %d", codes.InvalidArgument, status.Code()) } } } ================================================ FILE: server/services/locations_service.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package services import ( "context" "strings" locpb "google.golang.org/genproto/googleapis/cloud/location" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) var missingName error = status.Error(codes.InvalidArgument, "Missing required argument: name") // NewLocationsServer returns a new LocationsServer for the Showcase API. func NewLocationsServer() locpb.LocationsServer { return &locationsServerImpl{} } type locationsServerImpl struct{} // GetLocation echoes back a Location with the same name as // in.name and has the last segment of name as the display_name. func (l *locationsServerImpl) GetLocation(ctx context.Context, in *locpb.GetLocationRequest) (*locpb.Location, error) { if in.GetName() == "" { return nil, missingName } name := in.GetName() display := name[strings.LastIndex(name, "/")+1:] return &locpb.Location{ Name: name, DisplayName: display, }, nil } // ListLocations returns a fixed list of Locations prefixed with the // in.name value. func (l *locationsServerImpl) ListLocations(ctx context.Context, in *locpb.ListLocationsRequest) (*locpb.ListLocationsResponse, error) { if in.GetName() == "" { return nil, missingName } return &locpb.ListLocationsResponse{ Locations: []*locpb.Location{ { Name: in.GetName() + "/locations/us-north", DisplayName: "us-north", }, { Name: in.GetName() + "/locations/us-south", DisplayName: "us-south", }, { Name: in.GetName() + "/locations/us-east", DisplayName: "us-east", }, { Name: in.GetName() + "/locations/us-west", DisplayName: "us-west", }, }, }, nil } ================================================ FILE: server/services/locations_service_test.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package services import ( "context" "testing" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" locpb "google.golang.org/genproto/googleapis/cloud/location" "google.golang.org/protobuf/proto" ) func TestListLocations(t *testing.T) { s := NewLocationsServer() name := "projects/foo" got, err := s.ListLocations(context.Background(), &locpb.ListLocationsRequest{Name: name}) if err != nil { t.Error(err) } want := &locpb.ListLocationsResponse{ Locations: []*locpb.Location{ { Name: name + "/locations/us-north", DisplayName: "us-north", }, { Name: name + "/locations/us-south", DisplayName: "us-south", }, { Name: name + "/locations/us-east", DisplayName: "us-east", }, { Name: name + "/locations/us-west", DisplayName: "us-west", }, }, } if diff := cmp.Diff(got, want, cmp.Comparer(proto.Equal)); diff != "" { t.Errorf("ListLocations: got(-),want(+):\n%s", diff) } } func TestListLocations_missingName(t *testing.T) { s := NewLocationsServer() res, err := s.ListLocations(context.Background(), &locpb.ListLocationsRequest{}) if err == nil { t.Errorf("ListLocations_missingName: expected an error but got response: %v", res) } if diff := cmp.Diff(err, missingName, cmpopts.EquateErrors()); diff != "" { t.Errorf("ListLocations_missingName: got(-),want(+):\n%s", diff) } } func TestGetLocation(t *testing.T) { s := NewLocationsServer() name := "projects/foo/locations/us-west" want := &locpb.Location{ Name: name, DisplayName: "us-west", } got, err := s.GetLocation(context.Background(), &locpb.GetLocationRequest{Name: name}) if err != nil { t.Error(err) } if diff := cmp.Diff(got, want, cmp.Comparer(proto.Equal)); diff != "" { t.Errorf("GetLocation: got(-),want(+):\n%s", diff) } } func TestGetLocation_missingName(t *testing.T) { s := NewLocationsServer() res, err := s.GetLocation(context.Background(), &locpb.GetLocationRequest{}) if err == nil { t.Errorf("GetLocation_missingName: expected an error but got response: %v", res) } if diff := cmp.Diff(err, missingName, cmpopts.EquateErrors()); diff != "" { t.Errorf("GetLocation_missingName: got(-),want(+):\n%s", diff) } } ================================================ FILE: server/services/messaging_service.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package services import ( "context" "encoding/base64" "fmt" "io" "strconv" "strings" "sync" "time" "cloud.google.com/go/longrunning/autogen/longrunningpb" "github.com/golang/protobuf/ptypes" "github.com/golang/protobuf/ptypes/empty" "github.com/googleapis/gapic-showcase/server" pb "github.com/googleapis/gapic-showcase/server/genproto" errdetails "google.golang.org/genproto/googleapis/rpc/errdetails" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" ) // NewMessagingServer returns an instance of a messaging server. func NewMessagingServer(identityServer ReadOnlyIdentityServer) MessagingServer { return &messagingServerImpl{ identityServer: identityServer, nowF: time.Now, token: server.NewTokenGenerator(), roomKeys: map[string]int{}, blurbKeys: map[string]blurbIndex{}, blurbs: map[string][]blurbEntry{}, parentUids: map[string]*server.UniqID{}, observers: map[string]map[string]blurbObserver{}, } } // MessagingServer provides an interface which is the implementation of the // MessagingServer proto and as well as a method for filtering the blurbs. type MessagingServer interface { FilteredListBlurbs(context.Context, *pb.ListBlurbsRequest, func(*pb.Blurb) bool) (*pb.ListBlurbsResponse, error) pb.MessagingServer } type messagingServerImpl struct { nowF func() time.Time token server.TokenGenerator identityServer ReadOnlyIdentityServer roomUID server.UniqID roomMu sync.Mutex roomKeys map[string]int rooms []roomEntry blurbMu sync.Mutex blurbKeys map[string]blurbIndex blurbs map[string][]blurbEntry parentUids map[string]*server.UniqID obsMu sync.Mutex obsUID server.UniqID observers map[string]map[string]blurbObserver } type roomEntry struct { room *pb.Room deleted bool } type blurbIndex struct { // The parent of the blurb. row string // The index within the list of blurbs of a parent. col int } type blurbEntry struct { blurb *pb.Blurb deleted bool } type blurbObserver interface { OnCreate(b *pb.Blurb) OnUpdate(b *pb.Blurb) OnDelete(b *pb.Blurb) } // Creates a room. func (s *messagingServerImpl) CreateRoom(ctx context.Context, in *pb.CreateRoomRequest) (*pb.Room, error) { s.roomMu.Lock() defer s.roomMu.Unlock() r := in.GetRoom() err := validateRoom(r) if err != nil { return nil, err } // Validate Unique Fields. uniqName := func(x *pb.Room) bool { return (r.GetDisplayName() == x.GetDisplayName()) } if s.anyRoom(uniqName) { return nil, status.Errorf( codes.AlreadyExists, "A room with display_name %s already exists.", r.GetDisplayName()) } // Assign info. id := s.roomUID.Next() name := fmt.Sprintf("rooms/%d", id) now := ptypes.TimestampNow() r.Name = name r.CreateTime = now r.UpdateTime = now // Insert. index := len(s.rooms) s.rooms = append(s.rooms, roomEntry{room: r}) s.roomKeys[name] = index return r, nil } // Retrieves the Room with the given resource name. func (s *messagingServerImpl) GetRoom(ctx context.Context, in *pb.GetRoomRequest) (*pb.Room, error) { s.roomMu.Lock() defer s.roomMu.Unlock() name := in.GetName() if i, ok := s.roomKeys[name]; ok { entry := s.rooms[i] if !entry.deleted { return entry.room, nil } } return nil, status.Errorf( codes.NotFound, "A room with name %s not found.", name) } // Updates a room. func (s *messagingServerImpl) UpdateRoom(ctx context.Context, in *pb.UpdateRoomRequest) (*pb.Room, error) { mask := in.GetUpdateMask() r := in.GetRoom() s.roomMu.Lock() defer s.roomMu.Unlock() err := validateRoom(r) if err != nil { return nil, err } i, ok := s.roomKeys[r.GetName()] if !ok || s.rooms[i].deleted { return nil, status.Errorf( codes.NotFound, "A room with name %s not found.", r.GetName()) } existing := s.rooms[i].room // Validate Unique Fields. uniqName := func(x *pb.Room) bool { return x != existing && (r.GetDisplayName() == x.GetDisplayName()) } if s.anyRoom(uniqName) { return nil, status.Errorf( codes.AlreadyExists, "A room with either display_name, %s already exists.", r.GetDisplayName()) } // Update store. updated := proto.Clone(existing).(*pb.Room) applyFieldMask(r.ProtoReflect(), updated.ProtoReflect(), mask.GetPaths()) updated.CreateTime = existing.GetCreateTime() updated.UpdateTime = ptypes.TimestampNow() s.rooms[i] = roomEntry{room: updated} return updated, nil } // Deletes a room and all of its blurbs. func (s *messagingServerImpl) DeleteRoom(ctx context.Context, in *pb.DeleteRoomRequest) (*empty.Empty, error) { s.roomMu.Lock() defer s.roomMu.Unlock() i, ok := s.roomKeys[in.GetName()] if !ok { return nil, status.Errorf( codes.NotFound, "A room with name %s not found.", in.GetName()) } entry := s.rooms[i] s.rooms[i] = roomEntry{room: entry.room, deleted: true} return &empty.Empty{}, nil } // Lists all chat rooms. func (s *messagingServerImpl) ListRooms(ctx context.Context, in *pb.ListRoomsRequest) (*pb.ListRoomsResponse, error) { start, err := s.token.GetIndex(in.GetPageToken()) if err != nil { return nil, err } offset := 0 rooms := []*pb.Room{} for _, entry := range s.rooms[start:] { offset++ if entry.deleted { continue } rooms = append(rooms, entry.room) if len(rooms) >= int(in.GetPageSize()) { break } } nextToken := "" if start+offset < len(s.rooms) { nextToken = s.token.ForIndex(start + offset) } return &pb.ListRoomsResponse{Rooms: rooms, NextPageToken: nextToken}, nil } func (s *messagingServerImpl) anyRoom(f func(*pb.Room) bool) bool { for _, entry := range s.rooms { if !entry.deleted && f(entry.room) { return true } } return false } func validateRoom(r *pb.Room) error { // Validate Required Fields. if r.GetDisplayName() == "" { return status.Errorf( codes.InvalidArgument, "The field `display_name` is required.") } return nil } // Creates a blurb. If the parent is a room, the blurb is understood to be a // message in that room. If the parent is a profile, the blurb is understood // to be a post on the profile. func (s *messagingServerImpl) CreateBlurb(ctx context.Context, in *pb.CreateBlurbRequest) (*pb.Blurb, error) { parent := in.GetParent() if err := s.validateParent(parent); err != nil { return nil, err } s.blurbMu.Lock() defer s.blurbMu.Unlock() b := in.GetBlurb() if err := validateBlurb(b); err != nil { return nil, err } // Assign info. parentBs, ok := s.blurbs[parent] if !ok { parentBs = []blurbEntry{} } puid, ok := s.parentUids[parent] if !ok { puid = &server.UniqID{} s.parentUids[parent] = puid } id := puid.Next() name := fmt.Sprintf("%s/blurbs/%d", parent, id) now := ptypes.TimestampNow() switch legacyID := b.LegacyId.(type) { case *pb.Blurb_LegacyRoomId: name = fmt.Sprintf("%s/blurbs/legacy/%s.%d", parent, legacyID.LegacyRoomId, id) case *pb.Blurb_LegacyUserId: name = fmt.Sprintf("%s/blurbs/legacy/%s~%d", parent, legacyID.LegacyUserId, id) } b.Name = name b.CreateTime = now b.UpdateTime = now // Insert. index := len(parentBs) s.blurbs[parent] = append(parentBs, blurbEntry{blurb: b}) s.blurbKeys[name] = blurbIndex{row: parent, col: index} // Call observers. s.obsMu.Lock() defer s.obsMu.Unlock() if parentObservers, ok := s.observers[parent]; ok { for _, o := range parentObservers { o.OnCreate(b) } } return b, nil } // Retrieves the Blurb with the given resource name. func (s *messagingServerImpl) GetBlurb(ctx context.Context, in *pb.GetBlurbRequest) (*pb.Blurb, error) { s.blurbMu.Lock() defer s.blurbMu.Unlock() if i, ok := s.blurbKeys[in.GetName()]; ok { entry := s.blurbs[i.row][i.col] if !entry.deleted { return entry.blurb, nil } } return nil, status.Errorf( codes.NotFound, "A blurb with name %s not found.", in.GetName()) } // Updates a blurb. func (s *messagingServerImpl) UpdateBlurb(ctx context.Context, in *pb.UpdateBlurbRequest) (*pb.Blurb, error) { s.blurbMu.Lock() defer s.blurbMu.Unlock() mask := in.GetUpdateMask() b := in.GetBlurb() i, ok := s.blurbKeys[b.GetName()] if !ok || s.blurbs[i.row][i.col].deleted { return nil, status.Errorf( codes.NotFound, "A blurb with name %s not found.", b.GetName()) } if err := validateBlurb(b); err != nil { return nil, err } // Update store. existing := s.blurbs[i.row][i.col].blurb updated := proto.Clone(existing).(*pb.Blurb) applyFieldMask(b.ProtoReflect(), updated.ProtoReflect(), mask.GetPaths()) updated.CreateTime = existing.GetCreateTime() updated.UpdateTime = ptypes.TimestampNow() s.blurbs[i.row][i.col] = blurbEntry{blurb: updated} // Call observers. s.obsMu.Lock() defer s.obsMu.Unlock() if parentObservers, ok := s.observers[i.row]; ok { for _, o := range parentObservers { o.OnUpdate(updated) } } return updated, nil } // Deletes a blurb. func (s *messagingServerImpl) DeleteBlurb(ctx context.Context, in *pb.DeleteBlurbRequest) (*empty.Empty, error) { s.blurbMu.Lock() defer s.blurbMu.Unlock() i, ok := s.blurbKeys[in.GetName()] if !ok { return nil, status.Errorf( codes.NotFound, "A blurb with name %s not found.", in.GetName()) } entry := s.blurbs[i.row][i.col] s.blurbs[i.row][i.col] = blurbEntry{blurb: entry.blurb, deleted: true} // Call observers. s.obsMu.Lock() defer s.obsMu.Unlock() if parentObservers, ok := s.observers[i.row]; ok { for _, o := range parentObservers { o.OnDelete(entry.blurb) } } return &empty.Empty{}, nil } // Lists blurbs for a specific chat room or user profile depending on the // parent resource name. func (s *messagingServerImpl) ListBlurbs(ctx context.Context, in *pb.ListBlurbsRequest) (*pb.ListBlurbsResponse, error) { passFilter := func(_ *pb.Blurb) bool { return true } return s.FilteredListBlurbs(ctx, in, passFilter) } func (s *messagingServerImpl) FilteredListBlurbs(ctx context.Context, in *pb.ListBlurbsRequest, f func(*pb.Blurb) bool) (*pb.ListBlurbsResponse, error) { if err := s.validateParent(in.GetParent()); err != nil { return nil, err } bs, ok := s.blurbs[in.GetParent()] if !ok { return &pb.ListBlurbsResponse{}, nil } start, err := s.token.GetIndex(in.GetPageToken()) if err != nil { return nil, err } offset := 0 blurbs := []*pb.Blurb{} for _, entry := range bs[start:] { offset++ if entry.deleted { continue } if f(entry.blurb) { blurbs = append(blurbs, entry.blurb) } if len(blurbs) >= int(in.GetPageSize()) { break } } nextToken := "" if start+offset < len(s.blurbs[in.GetParent()]) { nextToken = s.token.ForIndex(start + offset) } return &pb.ListBlurbsResponse{Blurbs: blurbs, NextPageToken: nextToken}, nil } // This method searches through all blurbs across all rooms and profiles // for blurbs containing to words found in the query. Only posts that // contain an exact match of a queried word will be returned. func (s *messagingServerImpl) SearchBlurbs(ctx context.Context, in *pb.SearchBlurbsRequest) (*longrunningpb.Operation, error) { if err := s.validateParent(in.GetParent()); err != nil { return nil, err } reqBytes, _ := proto.Marshal(in) name := fmt.Sprintf( "operations/google.showcase.v1beta1.Messaging/SearchBlurbs/%s", base64.StdEncoding.EncodeToString(reqBytes)) // TODO(landrito) Add randomization to the retry delay. meta, _ := ptypes.MarshalAny( &pb.SearchBlurbsMetadata{ RetryInfo: &errdetails.RetryInfo{ RetryDelay: ptypes.DurationProto(time.Duration(1) * time.Second), }, }, ) return &longrunningpb.Operation{Name: name, Done: false, Metadata: meta}, nil } // This returns a stream that emits the blurbs that are created for a // particular chat room or user profile. func (s *messagingServerImpl) StreamBlurbs(in *pb.StreamBlurbsRequest, stream pb.Messaging_StreamBlurbsServer) error { parent := in.GetName() if err := s.validateParent(parent); err != nil { return err } expireTime, err := ptypes.Timestamp(in.GetExpireTime()) if err != nil { return status.Error(codes.InvalidArgument, err.Error()) } observer := &streamBlurbsObserver{ stream: stream.(BlurbsOutStream), mu: sync.Mutex{}, } name := s.registerObserver(parent, observer) defer s.removeObserver(parent, name) for { if s.nowF().After(expireTime) { break } if observer.getError() != nil { return observer.getError() } if err := s.validateParent(parent); err != nil { return err } } return nil } // This is a stream to create multiple blurbs. If an invalid blurb is // requested to be created, the stream will close with an error. func (s *messagingServerImpl) SendBlurbs(stream pb.Messaging_SendBlurbsServer) error { names := []string{} for { req, err := stream.Recv() if err == io.EOF { return stream.SendAndClose( &pb.SendBlurbsResponse{Names: names}) } if err != nil { return withCreatedNames(err, names) } parent := req.GetParent() if err := s.validateParent(parent); err != nil { return withCreatedNames(err, names) } blurb, err := s.CreateBlurb( context.Background(), &pb.CreateBlurbRequest{Parent: parent, Blurb: req.GetBlurb()}) if err != nil { return withCreatedNames(err, names) } names = append(names, blurb.GetName()) } } func withCreatedNames(err error, names []string) error { s, _ := status.FromError(err) spb := s.Proto() details, err := ptypes.MarshalAny(&pb.SendBlurbsResponse{Names: names}) if err == nil { spb.Details = append(spb.Details, details) } return status.ErrorProto(spb) } // This method starts a bidirectional stream that receives all blurbs that // are being created after the stream has started and sends requests to create // blurbs. If an invalid blurb is requested to be created, the stream will // close with an error. func (s *messagingServerImpl) Connect(stream pb.Messaging_ConnectServer) error { configured := false parent := "" var observer *streamBlurbsObserver for { req, err := stream.Recv() // Handle stream errors. if err == io.EOF { return nil } if err != nil { return err } // Setup Configuration if !configured && req != nil { if req.GetConfig() == nil { return status.Error( codes.InvalidArgument, "The first request to Connect, must contain a config field") } parent = req.GetConfig().GetParent() if err := s.validateParent(parent); err != nil { return err } observer = &streamBlurbsObserver{ stream: stream.(BlurbsOutStream), mu: sync.Mutex{}, } configured = true name := s.registerObserver(parent, observer) defer s.removeObserver(parent, name) continue } // Check if there was a send error. if err := observer.getError(); err != nil { return err } // Check if the parent still exists. if err := s.validateParent(parent); err != nil { return err } // Create the blurb if req == nil || req.GetBlurb() == nil { continue } _, err = s.CreateBlurb( context.Background(), &pb.CreateBlurbRequest{Parent: parent, Blurb: req.GetBlurb()}) if err != nil { return err } } } func validateBlurb(b *pb.Blurb) error { // Validate Required Fields. if b.GetUser() == "" { return status.Errorf( codes.InvalidArgument, "The field `user` is required.") } return nil } func (s *messagingServerImpl) validateParent(p string) error { _, uErr := s.identityServer.GetUser( context.Background(), &pb.GetUserRequest{ Name: strings.TrimSuffix(p, "/profile"), }, ) _, rErr := s.GetRoom(context.Background(), &pb.GetRoomRequest{Name: p}) if uErr != nil && rErr != nil { return status.Errorf(codes.NotFound, "Parent %s not found.", p) } return nil } // Observer type streamBlurbsObserver struct { // The stream to send the blurbs. stream BlurbsOutStream // Blurb parent to observe. parent string // Holds an error that occurred when sending a blurb. mu sync.Mutex err error } // BlurbsOutStream is the common interface of the connect and streamblurbs streams. // This interface allows the observer to handle both streams. type BlurbsOutStream interface { Send(*pb.StreamBlurbsResponse) error } func (o *streamBlurbsObserver) getError() error { o.mu.Lock() defer o.mu.Unlock() return o.err } func (o *streamBlurbsObserver) updateError(err error) { o.mu.Lock() defer o.mu.Unlock() if o.err == nil { o.err = err } } func (o *streamBlurbsObserver) OnCreate(b *pb.Blurb) { o.updateError( o.stream.Send( &pb.StreamBlurbsResponse{ Blurb: b, Action: pb.StreamBlurbsResponse_CREATE, })) } func (o *streamBlurbsObserver) OnUpdate(b *pb.Blurb) { o.updateError( o.stream.Send( &pb.StreamBlurbsResponse{ Blurb: b, Action: pb.StreamBlurbsResponse_UPDATE, })) } // Do nothing for now. Need to change the func (o *streamBlurbsObserver) OnDelete(b *pb.Blurb) { o.updateError( o.stream.Send( &pb.StreamBlurbsResponse{ Blurb: b, Action: pb.StreamBlurbsResponse_DELETE, })) } func (s *messagingServerImpl) registerObserver(parent string, o blurbObserver) string { s.obsMu.Lock() defer s.obsMu.Unlock() name := strconv.FormatInt(s.obsUID.Next(), 10) if _, ok := s.observers[parent]; !ok { s.observers[parent] = map[string]blurbObserver{} } s.observers[parent][name] = o return name } func (s *messagingServerImpl) hasObservers(parent string) bool { s.obsMu.Lock() defer s.obsMu.Unlock() if os, ok := s.observers[parent]; ok && len(os) > 0 { return true } return false } func (s *messagingServerImpl) removeObserver(parent string, name string) { s.obsMu.Lock() defer s.obsMu.Unlock() delete(s.observers[parent], name) if len(s.observers[parent]) <= 0 { delete(s.observers, parent) } } ================================================ FILE: server/services/messaging_service_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package services import ( "context" "encoding/base64" "fmt" "io" "strings" "sync" "testing" "time" "github.com/golang/protobuf/ptypes" "github.com/golang/protobuf/ptypes/timestamp" "github.com/google/go-cmp/cmp" "github.com/googleapis/gapic-showcase/server" pb "github.com/googleapis/gapic-showcase/server/genproto" "golang.org/x/sync/errgroup" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/fieldmaskpb" ) func Test_Room_lifecycle(t *testing.T) { s := NewMessagingServer(NewIdentityServer()) first, err := s.CreateRoom( context.Background(), &pb.CreateRoomRequest{ Room: &pb.Room{DisplayName: "Living Room"}, }) if err != nil { t.Errorf("Create: unexpected err %+v", err) } delete, err := s.CreateRoom( context.Background(), &pb.CreateRoomRequest{ Room: &pb.Room{DisplayName: "Library"}, }) if err != nil { t.Errorf("Create: unexpected err %+v", err) } _, err = s.DeleteRoom( context.Background(), &pb.DeleteRoomRequest{Name: delete.Name}) if err != nil { t.Errorf("Delete: unexpected err %+v", err) } created, err := s.CreateRoom( context.Background(), &pb.CreateRoomRequest{ Room: &pb.Room{DisplayName: "Weight Room"}, }) if err != nil { t.Errorf("Create: unexpected err %+v", err) } got, err := s.GetRoom( context.Background(), &pb.GetRoomRequest{Name: created.GetName()}) if err != nil { t.Errorf("Get: unexpected err %+v", err) } if !proto.Equal(created, got) { t.Error("Expected to get created room.") } got.DisplayName = "Library" _, err = s.UpdateRoom( context.Background(), &pb.UpdateRoomRequest{Room: got, UpdateMask: nil}) if err != nil { t.Errorf("Update: unexpected err %+v", err) } updated, err := s.GetRoom( context.Background(), &pb.GetRoomRequest{Name: got.GetName()}) if err != nil { t.Errorf("Get: unexpected err %+v", err) } // Cannot use proto.Equal here because the update time is changed on updates. if updated.GetName() != got.GetName() || updated.GetDisplayName() != got.GetDisplayName() || !proto.Equal(updated.GetCreateTime(), got.GetCreateTime()) || proto.Equal(updated.GetUpdateTime(), got.GetUpdateTime()) { t.Errorf("Expected to get updated room. Want: %+v, got %+v", got, updated) } r, err := s.ListRooms( context.Background(), &pb.ListRoomsRequest{PageSize: 1, PageToken: ""}) if len(r.GetRooms()) != 1 { t.Errorf("List want: page size %d, got %d", 1, len(r.GetRooms())) } if !proto.Equal(first, r.GetRooms()[0]) { t.Errorf("List want: first room %+v, got %+v", first, r.GetRooms()[0]) } if r.GetNextPageToken() == "" { t.Error("List want: non empty next page token") } r, err = s.ListRooms( context.Background(), &pb.ListRoomsRequest{PageSize: 10, PageToken: r.GetNextPageToken()}) if len(r.GetRooms()) != 1 { t.Errorf("List want: page size %d, got %d", 1, len(r.GetRooms())) } if !proto.Equal(updated, r.GetRooms()[0]) { t.Errorf("List want: updated room %+v, got %+v", updated, r.GetRooms()[0]) } if r.GetNextPageToken() != "" { t.Error("List want: empty next page token") } } func Test_CreateRoom_invalid(t *testing.T) { s := NewMessagingServer(NewIdentityServer()) _, err := s.CreateRoom( context.Background(), &pb.CreateRoomRequest{Room: &pb.Room{DisplayName: ""}}) status, _ := status.FromError(err) if status.Code() != codes.InvalidArgument { t.Errorf( "Create: Want error code %d got %d", codes.InvalidArgument, status.Code()) } } func Test_CreateRoom_alreadyPresent(t *testing.T) { room := &pb.Room{DisplayName: "Living Room"} s := NewMessagingServer(NewIdentityServer()) _, err := s.CreateRoom(context.Background(), &pb.CreateRoomRequest{Room: room}) if err != nil { t.Errorf("Create: unexpected err %+v", err) } _, err = s.CreateRoom(context.Background(), &pb.CreateRoomRequest{Room: room}) status, _ := status.FromError(err) if status.Code() != codes.AlreadyExists { t.Errorf( "Create: Want error code %d got %d", codes.AlreadyExists, status.Code()) } } func Test_GetRoom_notFound(t *testing.T) { s := NewMessagingServer(NewIdentityServer()) _, err := s.GetRoom( context.Background(), &pb.GetRoomRequest{Name: "Weight Room"}) status, _ := status.FromError(err) if status.Code() != codes.NotFound { t.Errorf( "Get: Want error code %d got %d", codes.NotFound, status.Code()) } } func Test_GetRoom_deleted(t *testing.T) { s := NewMessagingServer(NewIdentityServer()) created, err := s.CreateRoom( context.Background(), &pb.CreateRoomRequest{ Room: &pb.Room{DisplayName: "Weight Room"}, }) if err != nil { t.Errorf("Create: unexpected err %+v", err) } _, err = s.DeleteRoom( context.Background(), &pb.DeleteRoomRequest{Name: created.GetName()}) if err != nil { t.Errorf("Delete: unexpected err %+v", err) } _, err = s.GetRoom( context.Background(), &pb.GetRoomRequest{Name: created.GetName()}) status, _ := status.FromError(err) if status.Code() != codes.NotFound { t.Errorf( "Get deleted: Want error code %d got %d", codes.NotFound, status.Code()) } } func Test_UpdateRoom_fieldmask(t *testing.T) { first := &pb.Room{DisplayName: "Living Room"} second := &pb.Room{DisplayName: "Dining Room"} paths := []string{"display_name"} s := NewMessagingServer(NewIdentityServer()) created, err := s.CreateRoom( context.Background(), &pb.CreateRoomRequest{Room: first}) if err != nil { t.Errorf("Create: unexpected err %+v", err) } second.Name = created.GetName() got, err := s.UpdateRoom( context.Background(), &pb.UpdateRoomRequest{ Room: second, UpdateMask: &fieldmaskpb.FieldMask{Paths: paths}}) if err != nil { t.Fatal(err) } if diff := cmp.Diff(got.GetDisplayName(), second.GetDisplayName()); diff != "" { t.Errorf("Using update_mask %s, got(-),want(+):\n%s", strings.Join(paths, ","), diff) } } func Test_UpdateRoom_notFound(t *testing.T) { s := NewMessagingServer(NewIdentityServer()) _, err := s.UpdateRoom( context.Background(), &pb.UpdateRoomRequest{ Room: &pb.Room{ Name: "rooms/abc", DisplayName: "Weight Room", }, UpdateMask: nil, }) status, _ := status.FromError(err) if status.Code() != codes.NotFound { t.Errorf( "Update: Want error code %d got %d", codes.NotFound, status.Code()) } } func Test_UpdateRoom_invalid(t *testing.T) { first := &pb.Room{DisplayName: "Living Room"} second := &pb.Room{DisplayName: ""} s := NewMessagingServer(NewIdentityServer()) created, err := s.CreateRoom( context.Background(), &pb.CreateRoomRequest{Room: first}) if err != nil { t.Errorf("Create: unexpected err %+v", err) } second.Name = created.GetName() _, err = s.UpdateRoom( context.Background(), &pb.UpdateRoomRequest{Room: second, UpdateMask: nil}) status, _ := status.FromError(err) if status.Code() != codes.InvalidArgument { t.Errorf( "Update: Want error code %d got %d", codes.InvalidArgument, status.Code()) } } func Test_UpdateRoom_alreadyPresent(t *testing.T) { first := []*pb.Room{ {DisplayName: "Living Room"}, {DisplayName: "Weight Room"}, } second := &pb.Room{DisplayName: "Weight Room"} s := NewMessagingServer(NewIdentityServer()) for i, r := range first { created, err := s.CreateRoom( context.Background(), &pb.CreateRoomRequest{Room: r}) if err != nil { t.Errorf("Create: unexpected err %+v", err) } first[i].Name = created.GetName() } second.Name = first[0].GetName() _, err := s.UpdateRoom( context.Background(), &pb.UpdateRoomRequest{Room: second, UpdateMask: nil}) status, _ := status.FromError(err) if status.Code() != codes.AlreadyExists { t.Errorf( "Update: Want error code %d got %d", codes.AlreadyExists, status.Code()) } } func Test_DeleteRoom_notFound(t *testing.T) { s := NewMessagingServer(NewIdentityServer()) _, err := s.DeleteRoom( context.Background(), &pb.DeleteRoomRequest{Name: "Weight Room"}) status, _ := status.FromError(err) if status.Code() != codes.NotFound { t.Errorf( "Delete: Want error code %d got %d", codes.NotFound, status.Code()) } } func Test_ListRooms_invalidToken(t *testing.T) { s := messagingServerImpl{ token: server.TokenGeneratorWithSalt("salt"), roomKeys: map[string]int{}, } tests := []string{ "1", // Not base64 encoded base64.StdEncoding.EncodeToString([]byte("1")), // No salt base64.StdEncoding.EncodeToString([]byte("saltblah")), // Invalid index } for _, token := range tests { _, err := s.ListRooms( context.Background(), &pb.ListRoomsRequest{PageSize: 1, PageToken: token}) status, _ := status.FromError(err) if status.Code() != codes.InvalidArgument { t.Errorf( "List: Want error code %d got %d", codes.InvalidArgument, status.Code()) } } } type mockIdentityServer struct{} func (m *mockIdentityServer) GetUser(_ context.Context, _ *pb.GetUserRequest) (*pb.User, error) { return &pb.User{}, nil } func (m *mockIdentityServer) ListUsers(_ context.Context, _ *pb.ListUsersRequest) (*pb.ListUsersResponse, error) { return nil, nil } func Test_Blurb_lifecycle(t *testing.T) { s := NewMessagingServer(&mockIdentityServer{}) first, err := s.CreateBlurb( context.Background(), &pb.CreateBlurbRequest{ Parent: "users/rumble/profile", Blurb: &pb.Blurb{ User: "users/rumble", Content: &pb.Blurb_Text{Text: "woof"}, }, }) if err != nil { t.Errorf("Create: unexpected err %+v", err) } // create a Blurb with legacy_user_id second, err := s.CreateBlurb( context.Background(), &pb.CreateBlurbRequest{ Parent: "users/rumble/profile", Blurb: &pb.Blurb{ User: "users/rumble", Content: &pb.Blurb_Text{Text: "non-slash resource test."}, LegacyId: &pb.Blurb_LegacyUserId{LegacyUserId: "legacy_rumble"}, }, }) if err != nil { t.Errorf("Create: unexpected err %+v", err) } // get the second Blurb from database and verify the legacy_user_id, then delete it. gotSecond, err := s.GetBlurb( context.Background(), &pb.GetBlurbRequest{Name: second.GetName()}) if err != nil { t.Errorf("Get: unexpected err %+v", err) } if !proto.Equal(second, gotSecond) { t.Error("Expected to get created blurb.") } _, err = s.DeleteBlurb( context.Background(), &pb.DeleteBlurbRequest{Name: second.GetName()}) if err != nil { t.Errorf("Delete: unexpected err %+v", err) } delete, err := s.CreateBlurb( context.Background(), &pb.CreateBlurbRequest{ Parent: "users/rumble/profile", Blurb: &pb.Blurb{ User: "users/ekko", Content: &pb.Blurb_Text{Text: "bark"}, }, }) if err != nil { t.Errorf("Create: unexpected err %+v", err) } _, err = s.DeleteBlurb( context.Background(), &pb.DeleteBlurbRequest{Name: delete.GetName()}) if err != nil { t.Errorf("Delete: unexpected err %+v", err) } created, err := s.CreateBlurb( context.Background(), &pb.CreateBlurbRequest{ Parent: "users/rumble/profile", Blurb: &pb.Blurb{ User: "users/musubi", Content: &pb.Blurb_Text{Text: "meow"}, }, }) if err != nil { t.Errorf("Create: unexpected err %+v", err) } got, err := s.GetBlurb( context.Background(), &pb.GetBlurbRequest{Name: created.GetName()}) if err != nil { t.Errorf("Get: unexpected err %+v", err) } if !proto.Equal(created, got) { t.Error("Expected to get created blurb.") } got.Content = &pb.Blurb_Text{Text: "purrr"} _, err = s.UpdateBlurb( context.Background(), &pb.UpdateBlurbRequest{Blurb: got, UpdateMask: nil}) if err != nil { t.Errorf("Update: unexpected err %+v", err) } updated, err := s.GetBlurb( context.Background(), &pb.GetBlurbRequest{Name: got.GetName()}) if err != nil { t.Errorf("Get: unexpected err %+v", err) } // Cannot use proto.Equal here because the update time is changed on updates. if updated.GetName() != got.GetName() || updated.GetUser() != got.GetUser() || updated.GetText() != got.GetText() || !proto.Equal(updated.GetCreateTime(), got.GetCreateTime()) || proto.Equal(updated.GetUpdateTime(), got.GetUpdateTime()) { t.Errorf("Expected to get updated blurb. Want: %+v, got %+v", got, updated) } r, err := s.ListBlurbs( context.Background(), &pb.ListBlurbsRequest{ Parent: "users/rumble/profile", PageSize: 1, PageToken: "", }) if err != nil { t.Errorf("List: unexpected err %+v", err) } if len(r.GetBlurbs()) != 1 { t.Errorf("List want: page size %d, got %d", 1, len(r.GetBlurbs())) } if !proto.Equal(first, r.GetBlurbs()[0]) { t.Errorf("List want: first blurb %+v, got %+v", first, r.GetBlurbs()[0]) } if r.GetNextPageToken() == "" { t.Error("List want: non empty next page token") } r, err = s.ListBlurbs( context.Background(), &pb.ListBlurbsRequest{ Parent: "users/rumble/profile", PageSize: 10, PageToken: r.GetNextPageToken(), }) if err != nil { t.Errorf("List: unexpected err %+v", err) } if len(r.GetBlurbs()) != 1 { t.Errorf("List want: page size %d, got %d", 1, len(r.GetBlurbs())) } if !proto.Equal(updated, r.GetBlurbs()[0]) { t.Errorf("List want: updated blurb %+v, got %+v", updated, r.GetBlurbs()[0]) } if r.GetNextPageToken() != "" { t.Error("List want: empty next page token") } } func Test_CreateBlurb_invalid(t *testing.T) { s := NewMessagingServer(&mockIdentityServer{}) _, err := s.CreateBlurb( context.Background(), &pb.CreateBlurbRequest{Blurb: &pb.Blurb{}}) status, _ := status.FromError(err) if status.Code() != codes.InvalidArgument { t.Errorf( "Create: Want error code %d got %d", codes.InvalidArgument, status.Code()) } } func Test_CreateBlurb_parentNotFound(t *testing.T) { s := NewMessagingServer(NewIdentityServer()) _, err := s.CreateBlurb( context.Background(), &pb.CreateBlurbRequest{Parent: "users/rumble/profile", Blurb: &pb.Blurb{}}) status, _ := status.FromError(err) if status.Code() != codes.NotFound { t.Errorf( "Create: Want error code %d got %d", codes.NotFound, status.Code()) } } func Test_GetBlurb_notFound(t *testing.T) { s := NewMessagingServer(&mockIdentityServer{}) _, err := s.GetBlurb( context.Background(), &pb.GetBlurbRequest{Name: "users/rumble/profile/blurbs/1"}) status, _ := status.FromError(err) if status.Code() != codes.NotFound { t.Errorf( "Get: Want error code %d got %d", codes.NotFound, status.Code()) } } func Test_GetBlurb_deleted(t *testing.T) { s := NewMessagingServer(&mockIdentityServer{}) created, err := s.CreateBlurb( context.Background(), &pb.CreateBlurbRequest{ Parent: "users/rumble/profile", Blurb: &pb.Blurb{ User: "users/rumble", Content: &pb.Blurb_Text{Text: "woof"}, }, }) if err != nil { t.Errorf("Create: unexpected err %+v", err) } _, err = s.DeleteBlurb( context.Background(), &pb.DeleteBlurbRequest{Name: created.GetName()}) if err != nil { t.Errorf("Delete: unexpected err %+v", err) } _, err = s.GetBlurb( context.Background(), &pb.GetBlurbRequest{Name: created.GetName()}) status, _ := status.FromError(err) if status.Code() != codes.NotFound { t.Errorf( "Get deleted: Want error code %d got %d", codes.NotFound, status.Code()) } } func Test_UpdateBlurb_fieldmask(t *testing.T) { first := &pb.Blurb{ User: "users/rumble", Content: &pb.Blurb_Text{Text: "woof"}, } second := &pb.Blurb{ Content: &pb.Blurb_Text{Text: "bark"}, } paths := []string{"text"} s := NewMessagingServer(&mockIdentityServer{}) created, err := s.CreateBlurb( context.Background(), &pb.CreateBlurbRequest{Blurb: first}) if err != nil { t.Errorf("Create: unexpected err %+v", err) } second.Name = created.GetName() second.User = created.GetUser() got, err := s.UpdateBlurb( context.Background(), &pb.UpdateBlurbRequest{Blurb: second, UpdateMask: &fieldmaskpb.FieldMask{Paths: paths}}) if err != nil { t.Fatal(err) } if diff := cmp.Diff(got.GetText(), second.GetText()); diff != "" { t.Errorf("Using update_mask %s, got(-),want(+):\n%s", strings.Join(paths, ","), diff) } } func Test_UpdateBlurb_notFound(t *testing.T) { s := NewMessagingServer(&mockIdentityServer{}) _, err := s.UpdateBlurb( context.Background(), &pb.UpdateBlurbRequest{ Blurb: &pb.Blurb{ User: "users/rumble", Content: &pb.Blurb_Text{Text: "woof"}, }, UpdateMask: nil, }) status, _ := status.FromError(err) if status.Code() != codes.NotFound { t.Errorf( "Update: Want error code %d got %d", codes.NotFound, status.Code()) } } func Test_UpdateBlurb_invalid(t *testing.T) { first := &pb.Blurb{ User: "users/rumble", Content: &pb.Blurb_Text{Text: "woof"}, } second := &pb.Blurb{ User: "", Content: &pb.Blurb_Text{Text: "woof"}, } s := NewMessagingServer(&mockIdentityServer{}) created, err := s.CreateBlurb( context.Background(), &pb.CreateBlurbRequest{Blurb: first}) if err != nil { t.Errorf("Create: unexpected err %+v", err) } second.Name = created.GetName() _, err = s.UpdateBlurb( context.Background(), &pb.UpdateBlurbRequest{Blurb: second, UpdateMask: nil}) status, _ := status.FromError(err) if status.Code() != codes.InvalidArgument { t.Errorf( "Update: Want error code %d got %d", codes.InvalidArgument, status.Code()) } } func Test_DeleteBlurb_notFound(t *testing.T) { s := NewMessagingServer(NewIdentityServer()) _, err := s.DeleteBlurb( context.Background(), &pb.DeleteBlurbRequest{Name: "user/rumble/profile/blurbs/1"}) status, _ := status.FromError(err) if status.Code() != codes.NotFound { t.Errorf( "Delete: Want error code %d got %d", codes.NotFound, status.Code()) } } func Test_ListBlurbs_invalidToken(t *testing.T) { s := messagingServerImpl{ identityServer: &mockIdentityServer{}, token: server.TokenGeneratorWithSalt("salt"), roomKeys: map[string]int{}, blurbKeys: map[string]blurbIndex{}, blurbs: map[string][]blurbEntry{}, parentUids: map[string]*server.UniqID{}, observers: map[string]map[string]blurbObserver{}, } tests := []string{ "1", // Not base64 encoded base64.StdEncoding.EncodeToString([]byte("1")), // No salt base64.StdEncoding.EncodeToString([]byte("saltblah")), // Invalid index } _, err := s.CreateBlurb( context.Background(), &pb.CreateBlurbRequest{ Parent: "users/rumble/profile", Blurb: &pb.Blurb{ User: "users/rumble", Content: &pb.Blurb_Text{Text: "woof"}, }, }) if err != nil { t.Errorf("Create: unexpected err %+v", err) } for _, token := range tests { _, err := s.ListBlurbs( context.Background(), &pb.ListBlurbsRequest{ Parent: "users/rumble/profile", PageSize: 1, PageToken: token}) status, _ := status.FromError(err) if status.Code() != codes.InvalidArgument { t.Errorf( "List: Want error code %d got %d", codes.InvalidArgument, status.Code()) } } } func Test_ListBlurbs_parentNotFound(t *testing.T) { s := NewMessagingServer(NewIdentityServer()) _, err := s.ListBlurbs( context.Background(), &pb.ListBlurbsRequest{Parent: "users/rumble/profile"}) status, _ := status.FromError(err) if status.Code() != codes.NotFound { t.Errorf( "List: Want error code %d got %d", codes.NotFound, status.Code()) } } func Test_ListBlurbs_noneCreated(t *testing.T) { s := NewMessagingServer(&mockIdentityServer{}) resp, err := s.ListBlurbs( context.Background(), &pb.ListBlurbsRequest{Parent: "users/rumble/profile"}) if err != nil { t.Errorf("List: unexpected err %+v", err) } if len(resp.GetBlurbs()) > 0 { t.Errorf("List none created: want empty list got %+v", resp) } } func Test_SearchBlurbs(t *testing.T) { s := NewMessagingServer(&mockIdentityServer{}) req := &pb.SearchBlurbsRequest{ Query: "woof bark", Parent: "users/rumble/profile", PageSize: 100, } op, err := s.SearchBlurbs( context.Background(), req) if err != nil { t.Errorf("SearchBlurbs: unexpected err %+v", err) } expName := "operations/google.showcase.v1beta1.Messaging/SearchBlurbs/" if !strings.HasPrefix(op.Name, expName) { t.Errorf( "SearchBlurbs op.Name prefex want: '%s', got: %s'", expName, op.Name) } reqProto := &pb.SearchBlurbsRequest{} encodedBytes := strings.TrimPrefix( op.Name, expName) bytes, _ := base64.StdEncoding.DecodeString(encodedBytes) proto.Unmarshal(bytes, reqProto) if !proto.Equal(reqProto, req) { t.Errorf( "SearchBlurbs for %q expected unmarshalled %q, got %q", req, req, reqProto) } } func Test_SearchBlurbs_parentNotFound(t *testing.T) { s := NewMessagingServer(NewIdentityServer()) req := &pb.SearchBlurbsRequest{ Query: "woof bark", Parent: "users/rumble/profile", } _, err := s.SearchBlurbs( context.Background(), req) status, _ := status.FromError(err) if status.Code() != codes.NotFound { t.Errorf( "SearchBlurbs: Want error code %d got %d", codes.NotFound, status.Code()) } } type mockStreamBlurbsStream struct { mu sync.Mutex resps []*pb.StreamBlurbsResponse pb.Messaging_StreamBlurbsServer } func (m *mockStreamBlurbsStream) Send(resp *pb.StreamBlurbsResponse) error { m.mu.Lock() defer m.mu.Unlock() m.resps = append(m.resps, resp) return nil } func TestStreamBlurbs_lifecycle(t *testing.T) { // We specify the now function so we can control when the stream ends. s := &messagingServerImpl{ identityServer: &mockIdentityServer{}, token: server.NewTokenGenerator(), roomKeys: map[string]int{}, blurbKeys: map[string]blurbIndex{}, blurbs: map[string][]blurbEntry{}, parentUids: map[string]*server.UniqID{}, observers: map[string]map[string]blurbObserver{}, nowF: func() time.Time { return time.Unix(int64(0), int64(0)) }, } // Set up the mock stream. m := &mockStreamBlurbsStream{resps: []*pb.StreamBlurbsResponse{}} // Make the end time some time after the time the now function will return. endTime, err := ptypes.TimestampProto(time.Unix(int64(1), int64(0))) if err != nil { t.Errorf("TimestampProto: unexpected err %+v", err) } // The parent to stream p := "users/rumble/profile" // Start the stream. wg := &sync.WaitGroup{} wg.Add(1) go (func() { err := s.StreamBlurbs( &pb.StreamBlurbsRequest{ Name: p, ExpireTime: endTime, }, m, ) if err != nil { t.Errorf("StreamBlurbs: unexpected err %+v", err) } wg.Done() })() // Wait for the stream request to propogate the observer to the database. for { if s.hasObservers(p) { break } } // Create a blurb. created, err := s.CreateBlurb( context.Background(), &pb.CreateBlurbRequest{ Parent: p, Blurb: &pb.Blurb{ User: "users/musubi", Content: &pb.Blurb_Text{Text: "meow"}, }, }) if err != nil { t.Errorf("Create: unexpected err %+v", err) } // Check that the stream sent the blurb info. m.mu.Lock() streamResp := m.resps[len(m.resps)-1] m.mu.Unlock() if streamResp.GetAction() != pb.StreamBlurbsResponse_CREATE { t.Errorf( "StreamBlurbs: want blurb with action %s, got %s", pb.StreamBlurbsResponse_Action_name[int32(pb.StreamBlurbsResponse_CREATE)], pb.StreamBlurbsResponse_Action_name[int32(streamResp.GetAction())]) } if !proto.Equal(streamResp.GetBlurb(), created) { t.Errorf( "StreamBlurbs: want created blurb %+v, got %+v", created, streamResp.GetBlurb()) } // Update the blurb. created.Content = &pb.Blurb_Text{Text: "purrr"} updated, err := s.UpdateBlurb( context.Background(), &pb.UpdateBlurbRequest{Blurb: created, UpdateMask: nil}) if err != nil { t.Errorf("Update: unexpected err %+v", err) } // Check that the stream sent the blurb info. m.mu.Lock() streamResp = m.resps[len(m.resps)-1] m.mu.Unlock() if streamResp.GetAction() != pb.StreamBlurbsResponse_UPDATE { t.Errorf( "StreamBlurbs: want blurb with action %s, got %s", pb.StreamBlurbsResponse_Action_name[int32(pb.StreamBlurbsResponse_UPDATE)], pb.StreamBlurbsResponse_Action_name[int32(streamResp.GetAction())]) } if !proto.Equal(streamResp.GetBlurb(), updated) { t.Errorf( "StreamBlurbs: want updated blurb %+v, got %+v", updated, streamResp.GetBlurb()) } // Delete the blurb. _, err = s.DeleteBlurb( context.Background(), &pb.DeleteBlurbRequest{Name: updated.Name}) if err != nil { t.Errorf("Delete: unexpected err %+v", err) } // Check that the stream sent the blurb info. m.mu.Lock() streamResp = m.resps[len(m.resps)-1] m.mu.Unlock() if streamResp.GetAction() != pb.StreamBlurbsResponse_DELETE { t.Errorf( "StreamBlurbs: want blurb with action %s, got %s", pb.StreamBlurbsResponse_Action_name[int32(pb.StreamBlurbsResponse_DELETE)], pb.StreamBlurbsResponse_Action_name[int32(streamResp.GetAction())]) } if !proto.Equal(streamResp.GetBlurb(), updated) { t.Errorf( "StreamBlurbs: want deleted blurb %+v, got %+v", updated, streamResp.GetBlurb()) } // Set the now function to return a time after the expire time to close the // stream. s.nowF = func() time.Time { return time.Unix(int64(2), int64(0)) } // Wait til the stream is closed. wg.Wait() } func Test_StreamBlurbs_parentNotFound(t *testing.T) { s := NewMessagingServer(NewIdentityServer()) err := s.StreamBlurbs( &pb.StreamBlurbsRequest{Name: "users/rumble/profile"}, nil) status, _ := status.FromError(err) if status.Code() != codes.NotFound { t.Errorf( "Create: Want error code %d got %d", codes.NotFound, status.Code()) } } func Test_StreamBlurbs_invalidTimestamp(t *testing.T) { is := NewIdentityServer() first, err := is.CreateUser( context.Background(), &pb.CreateUserRequest{ User: &pb.User{DisplayName: "rumbledog", Email: "rumble@example.com"}, }) if err != nil { t.Errorf("Create: unexpected err %+v", err) } s := NewMessagingServer(is) maxValidSeconds := int64(253402300800) err = s.StreamBlurbs( &pb.StreamBlurbsRequest{Name: first.GetName(), ExpireTime: ×tamp.Timestamp{Seconds: maxValidSeconds + 1}}, nil) status, _ := status.FromError(err) if status.Code() != codes.InvalidArgument { t.Errorf( "Create: Want error code %d got %d", codes.InvalidArgument, status.Code()) } } type errorStreamBlurbsStream struct { pb.Messaging_StreamBlurbsServer } func (m *errorStreamBlurbsStream) Send(_ *pb.StreamBlurbsResponse) error { return status.Error(codes.Unknown, "Error") } func Test_StreamBlurbs_sendError(t *testing.T) { // We specify the now function so we can control when the stream ends. s := &messagingServerImpl{ identityServer: &mockIdentityServer{}, token: server.NewTokenGenerator(), roomKeys: map[string]int{}, blurbKeys: map[string]blurbIndex{}, blurbs: map[string][]blurbEntry{}, parentUids: map[string]*server.UniqID{}, observers: map[string]map[string]blurbObserver{}, nowF: func() time.Time { return time.Unix(int64(0), int64(0)) }, } // Make the end time some time after the time the now function will return. endTime, err := ptypes.TimestampProto(time.Unix(int64(1), int64(0))) if err != nil { t.Errorf("TimestampProto: unexpected err %+v", err) } // The parent to stream. p := "users/rumble/profile" // Start Stream. wg := &sync.WaitGroup{} wg.Add(1) go (func() { err = s.StreamBlurbs( &pb.StreamBlurbsRequest{Name: p, ExpireTime: endTime}, &errorStreamBlurbsStream{}) status, _ := status.FromError(err) if status.Code() != codes.Unknown { t.Errorf( "Create: Want error code %d got %d", codes.Unknown, status.Code()) } wg.Done() })() // Wait for the stream request to propogate the observer to the database. for { if s.hasObservers(p) { break } } // Create a blurb to trigger observer. _, err = s.CreateBlurb( context.Background(), &pb.CreateBlurbRequest{ Parent: p, Blurb: &pb.Blurb{ User: "users/musubi", Content: &pb.Blurb_Text{Text: "meow"}, }, }) if err != nil { t.Errorf("Create: unexpected err %+v", err) } wg.Wait() } type nilStreamBlurbsStream struct { pb.Messaging_StreamBlurbsServer } func (m *nilStreamBlurbsStream) Send(resp *pb.StreamBlurbsResponse) error { return nil } func Test_StreamBlurbs_parentNotFoundLater(t *testing.T) { // Setup Identity server to validate parent against. is := NewIdentityServer() first, err := is.CreateUser( context.Background(), &pb.CreateUserRequest{ User: &pb.User{DisplayName: "rumbledog", Email: "rumble@example.com"}, }) if err != nil { t.Errorf("Create: unexpected err %+v", err) } // We specify the now function so we can control when the stream ends. s := &messagingServerImpl{ identityServer: is, token: server.NewTokenGenerator(), roomKeys: map[string]int{}, blurbKeys: map[string]blurbIndex{}, blurbs: map[string][]blurbEntry{}, parentUids: map[string]*server.UniqID{}, observers: map[string]map[string]blurbObserver{}, nowF: func() time.Time { return time.Unix(int64(0), int64(0)) }, } // Make the end time some time after the time the now function will return. endTime, err := ptypes.TimestampProto(time.Unix(int64(1), int64(0))) if err != nil { t.Errorf("TimestampProto: unexpected err %+v", err) } parent := fmt.Sprintf("%s/profile", first.GetName()) // Start Stream. wg := &sync.WaitGroup{} wg.Add(1) go (func() { err := s.StreamBlurbs( &pb.StreamBlurbsRequest{ Name: parent, ExpireTime: endTime, }, &nilStreamBlurbsStream{}) status, _ := status.FromError(err) if status.Code() != codes.NotFound { t.Errorf( "StreamBlurbs: Want error code %d got %d", codes.NotFound, status.Code()) } wg.Done() })() for { if s.hasObservers(parent) { break } } // Delete the user so that the parent is invalid. is.DeleteUser( context.Background(), &pb.DeleteUserRequest{Name: first.GetName()}) // Wait til the stream closes. wg.Wait() } type mockSendBlurbsStream struct { reqs []*pb.CreateBlurbRequest resp *pb.SendBlurbsResponse t *testing.T mu sync.Mutex next int pb.Messaging_SendBlurbsServer } func (m *mockSendBlurbsStream) SendAndClose(r *pb.SendBlurbsResponse) error { m.resp = r return nil } func (m *mockSendBlurbsStream) Recv() (*pb.CreateBlurbRequest, error) { m.mu.Lock() defer m.mu.Unlock() if m.next < len(m.reqs) { cur := m.next m.next++ return m.reqs[cur], nil } return nil, io.EOF } func TestSendBlurbs(t *testing.T) { reqs := []*pb.CreateBlurbRequest{ { Parent: "users/rumble/profile", Blurb: &pb.Blurb{ User: "users/rumble", Content: &pb.Blurb_Text{Text: "woof"}, }, }, { Parent: "users/rumble/profile", Blurb: &pb.Blurb{ User: "users/musubi", Content: &pb.Blurb_Text{Text: "meow"}, }, }, { Parent: "users/musubi/profile", Blurb: &pb.Blurb{ User: "users/ekko", Content: &pb.Blurb_Text{Text: "bark"}, }, }, } m := &mockSendBlurbsStream{ reqs: reqs, t: t, } s := NewMessagingServer(&mockIdentityServer{}) err := s.SendBlurbs(m) if err != nil { t.Errorf("SendBlurbs: unexpected err %+v", err) } for i, name := range m.resp.GetNames() { got, err := s.GetBlurb( context.Background(), &pb.GetBlurbRequest{Name: name}) if err != nil { t.Errorf("Get: unexpected err %+v", err) } if reqs[i].GetBlurb().GetUser() != got.GetUser() || reqs[i].GetBlurb().GetText() != got.GetText() { t.Errorf( "Expected to get created blurb. Want: %+v, got %+v", reqs[i].GetBlurb(), got) } } } type errorSendBlurbsStream struct { reqs []*pb.CreateBlurbRequest resp *pb.SendBlurbsResponse t *testing.T mu sync.Mutex next int pb.Messaging_SendBlurbsServer } func (m *errorSendBlurbsStream) SendAndClose(r *pb.SendBlurbsResponse) error { m.resp = r return nil } func (m *errorSendBlurbsStream) Recv() (*pb.CreateBlurbRequest, error) { m.mu.Lock() defer m.mu.Unlock() if m.next < len(m.reqs) { cur := m.next m.next++ return m.reqs[cur], nil } return nil, status.Error(codes.Unknown, "Error") } func TestSendBlurbs_error(t *testing.T) { reqs := []*pb.CreateBlurbRequest{ { Parent: "users/rumble/profile", Blurb: &pb.Blurb{ User: "users/rumble", Content: &pb.Blurb_Text{Text: "woof"}, }, }, { Parent: "users/rumble/profile", Blurb: &pb.Blurb{ User: "users/musubi", Content: &pb.Blurb_Text{Text: "meow"}, }, }, { Parent: "users/musubi/profile", Blurb: &pb.Blurb{ User: "users/ekko", Content: &pb.Blurb_Text{Text: "bark"}, }, }, } m := &errorSendBlurbsStream{ reqs: reqs, t: t, } s := NewMessagingServer(&mockIdentityServer{}) err := s.SendBlurbs(m) if err == nil { t.Error("SendBlurbs: expected err") } st, ok := status.FromError(err) if !ok { t.Errorf("SendBlurbs: expected err to be status %+v", err) } details := st.Proto().GetDetails() if len(details) > 1 { t.Errorf("SendBlurbs: expected err details to be of length 1") } resp := &pb.SendBlurbsResponse{} ptypes.UnmarshalAny(details[0], resp) for i, name := range resp.GetNames() { got, err := s.GetBlurb( context.Background(), &pb.GetBlurbRequest{Name: name}) if err != nil { t.Errorf("Get: unexpected err %+v", err) } if reqs[i].GetBlurb().GetName() != got.GetName() || reqs[i].GetBlurb().GetUser() != got.GetUser() || reqs[i].GetBlurb().GetText() != got.GetText() { t.Errorf("Expected to get updated blurb. Want: %+v, got %+v", reqs, got) } } } func TestSendBlurbs_invalidParent(t *testing.T) { // Setup Identity server to validate parent against. is := NewIdentityServer() first, err := is.CreateUser( context.Background(), &pb.CreateUserRequest{ User: &pb.User{DisplayName: "rumbledog", Email: "rumble@example.com"}, }) if err != nil { t.Errorf("Create: unexpected err %+v", err) } parent := fmt.Sprintf("%s/profile", first.GetName()) reqs := []*pb.CreateBlurbRequest{ { Parent: parent, Blurb: &pb.Blurb{ User: "users/rumble", Content: &pb.Blurb_Text{Text: "woof"}, }, }, { Parent: parent, Blurb: &pb.Blurb{ User: "users/musubi", Content: &pb.Blurb_Text{Text: "meow"}, }, }, { Parent: "does/not/exist", Blurb: &pb.Blurb{ User: "users/ekko", Content: &pb.Blurb_Text{Text: "bark"}, }, }, } m := &mockSendBlurbsStream{ reqs: reqs, t: t, } s := NewMessagingServer(is) err = s.SendBlurbs(m) if err == nil { t.Error("SendBlurbs: expected err") } st, ok := status.FromError(err) if !ok { t.Errorf("SendBlurbs: expected err to be status %+v", err) } details := st.Proto().GetDetails() if len(details) > 1 { t.Errorf("SendBlurbs: expected err details to be of length 1") } resp := &pb.SendBlurbsResponse{} ptypes.UnmarshalAny(details[0], resp) for i, name := range resp.GetNames() { got, err := s.GetBlurb( context.Background(), &pb.GetBlurbRequest{Name: name}) if err != nil { t.Errorf("Get: unexpected err %+v", err) } if reqs[i].GetBlurb().GetName() != got.GetName() || reqs[i].GetBlurb().GetUser() != got.GetUser() || reqs[i].GetBlurb().GetText() != got.GetText() { t.Errorf("Expected to get updated blurb. Want: %+v, got %+v", reqs, got) } } } func TestSendBlurbs_invalidBlurb(t *testing.T) { reqs := []*pb.CreateBlurbRequest{ { Parent: "users/rumble/profile", Blurb: &pb.Blurb{ User: "users/rumble", Content: &pb.Blurb_Text{Text: "woof"}, }, }, { Parent: "users/rumble/profile", Blurb: &pb.Blurb{ User: "users/musubi", Content: &pb.Blurb_Text{Text: "meow"}, }, }, { Parent: "users/musubi/profile", Blurb: &pb.Blurb{ Content: &pb.Blurb_Text{Text: "bark"}, }, }, } m := &mockSendBlurbsStream{ reqs: reqs, t: t, } s := NewMessagingServer(&mockIdentityServer{}) err := s.SendBlurbs(m) if err == nil { t.Error("SendBlurbs: expected err") } st, ok := status.FromError(err) if !ok { t.Errorf("SendBlurbs: expected err to be status %+v", err) } details := st.Proto().GetDetails() if len(details) > 1 { t.Errorf("SendBlurbs: expected err details to be of length 1") } resp := &pb.SendBlurbsResponse{} ptypes.UnmarshalAny(details[0], resp) for i, name := range resp.GetNames() { got, err := s.GetBlurb( context.Background(), &pb.GetBlurbRequest{Name: name}) if err != nil { t.Errorf("Get: unexpected err %+v", err) } if reqs[i].GetBlurb().GetName() != got.GetName() || reqs[i].GetBlurb().GetUser() != got.GetUser() || reqs[i].GetBlurb().GetText() != got.GetText() { t.Errorf("Expected to get updated blurb. Want: %+v, got %+v", reqs, got) } } } type mockConnectStream struct { reqs []*pb.ConnectRequest t *testing.T stop bool respMu sync.Mutex resps []*pb.StreamBlurbsResponse nextMu sync.Mutex next int pb.Messaging_ConnectServer } func (m *mockConnectStream) Recv() (*pb.ConnectRequest, error) { if m.next < len(m.reqs) { req := m.reqs[m.next] m.next++ return req, nil } if m.stop { return nil, io.EOF } return nil, nil } func (m *mockConnectStream) Send(r *pb.StreamBlurbsResponse) error { m.respMu.Lock() defer m.respMu.Unlock() m.resps = append(m.resps, r) return nil } func TestConnect(t *testing.T) { reqs := []*pb.ConnectRequest{ { Request: &pb.ConnectRequest_Config{ Config: &pb.ConnectRequest_ConnectConfig{ Parent: "users/rumble/profile", }, }, }, { Request: &pb.ConnectRequest_Blurb{ Blurb: &pb.Blurb{ User: "users/rumble", Content: &pb.Blurb_Text{Text: "woof"}, }, }, }, } m := &mockConnectStream{ reqs: reqs, t: t, resps: []*pb.StreamBlurbsResponse{}, } s := NewMessagingServer(&mockIdentityServer{}) g := new(errgroup.Group) g.Go(func() error { err := s.Connect(m) if err != nil { return fmt.Errorf("Connect: unexpected err %+v", err) } return nil }) for { if len(m.resps) > 0 { break } } // Check that the stream sent the blurb info. m.respMu.Lock() streamResp := m.resps[len(m.resps)-1] m.respMu.Unlock() if streamResp.GetAction() != pb.StreamBlurbsResponse_CREATE { t.Errorf( "StreamBlurbs: want blurb with action %s, got %s", pb.StreamBlurbsResponse_Action_name[int32(pb.StreamBlurbsResponse_CREATE)], pb.StreamBlurbsResponse_Action_name[int32(streamResp.GetAction())]) } if reqs[1].GetBlurb().GetName() != streamResp.GetBlurb().GetName() || reqs[1].GetBlurb().GetUser() != streamResp.GetBlurb().GetUser() || reqs[1].GetBlurb().GetText() != streamResp.GetBlurb().GetText() { t.Errorf( "Expected to get created blurb. Want: %+v, got %+v", reqs[1].GetBlurb(), streamResp.GetBlurb()) } // Create a blurb. created, err := s.CreateBlurb( context.Background(), &pb.CreateBlurbRequest{ Parent: "users/rumble/profile", Blurb: &pb.Blurb{ User: "users/musubi", Content: &pb.Blurb_Text{Text: "meow"}, }, }) if err != nil { t.Errorf("Create: unexpected err %+v", err) } // Check that the stream sent the blurb info. m.respMu.Lock() streamResp = m.resps[len(m.resps)-1] m.respMu.Unlock() if streamResp.GetAction() != pb.StreamBlurbsResponse_CREATE { t.Errorf( "StreamBlurbs: want blurb with action %s, got %s", pb.StreamBlurbsResponse_Action_name[int32(pb.StreamBlurbsResponse_CREATE)], pb.StreamBlurbsResponse_Action_name[int32(streamResp.GetAction())]) } if !proto.Equal(streamResp.GetBlurb(), created) { t.Errorf( "StreamBlurbs: want created blurb %+v, got %+v", created, streamResp.GetBlurb()) } // Update the blurb. created.Content = &pb.Blurb_Text{Text: "purrr"} updated, err := s.UpdateBlurb( context.Background(), &pb.UpdateBlurbRequest{Blurb: created, UpdateMask: nil}) if err != nil { t.Errorf("Update: unexpected err %+v", err) } // Check that the stream sent the blurb info. m.respMu.Lock() streamResp = m.resps[len(m.resps)-1] m.respMu.Unlock() if streamResp.GetAction() != pb.StreamBlurbsResponse_UPDATE { t.Errorf( "StreamBlurbs: want blurb with action %s, got %s", pb.StreamBlurbsResponse_Action_name[int32(pb.StreamBlurbsResponse_UPDATE)], pb.StreamBlurbsResponse_Action_name[int32(streamResp.GetAction())]) } if !proto.Equal(streamResp.GetBlurb(), updated) { t.Errorf( "StreamBlurbs: want updated blurb %+v, got %+v", updated, streamResp.GetBlurb()) } // Delete the blurb. _, err = s.DeleteBlurb( context.Background(), &pb.DeleteBlurbRequest{Name: updated.Name}) if err != nil { t.Errorf("Delete: unexpected err %+v", err) } // Check that the stream sent the blurb info. m.respMu.Lock() streamResp = m.resps[len(m.resps)-1] m.respMu.Unlock() if streamResp.GetAction() != pb.StreamBlurbsResponse_DELETE { t.Errorf( "StreamBlurbs: want blurb with action %s, got %s", pb.StreamBlurbsResponse_Action_name[int32(pb.StreamBlurbsResponse_DELETE)], pb.StreamBlurbsResponse_Action_name[int32(streamResp.GetAction())]) } if !proto.Equal(streamResp.GetBlurb(), updated) { t.Errorf( "StreamBlurbs: want deleted blurb %+v, got %+v", updated, streamResp.GetBlurb()) } m.stop = true if err := g.Wait(); err != nil { t.Error(err) } } type errorConnectStream struct { pb.Messaging_ConnectServer } func (m *errorConnectStream) Recv() (*pb.ConnectRequest, error) { return nil, status.Error(codes.Unknown, "Error") } func TestConnect_error(t *testing.T) { m := &errorConnectStream{} s := NewMessagingServer(&mockIdentityServer{}) err := s.Connect(m) status, _ := status.FromError(err) if status.Code() != codes.Unknown { t.Errorf( "Connect: Want error code %d got %d", codes.Unknown, status.Code()) } } func TestConnect_notConfigured(t *testing.T) { reqs := []*pb.ConnectRequest{ { Request: &pb.ConnectRequest_Blurb{ Blurb: &pb.Blurb{ User: "users/rumble", Content: &pb.Blurb_Text{Text: "woof"}, }, }, }, } m := &mockConnectStream{ reqs: reqs, t: t, resps: []*pb.StreamBlurbsResponse{}, } s := NewMessagingServer(&mockIdentityServer{}) err := s.Connect(m) if err == nil { t.Fatalf("Connect: expected err") } status, _ := status.FromError(err) if status.Code() != codes.InvalidArgument { t.Errorf( "Connect: Want error code %d got %d", codes.InvalidArgument, status.Code()) } } func TestConnect_parentNotFound(t *testing.T) { reqs := []*pb.ConnectRequest{ { Request: &pb.ConnectRequest_Config{ Config: &pb.ConnectRequest_ConnectConfig{ Parent: "users/rumble/profile", }, }, }, } m := &mockConnectStream{ reqs: reqs, t: t, resps: []*pb.StreamBlurbsResponse{}, } s := NewMessagingServer(NewIdentityServer()) err := s.Connect(m) if err == nil { t.Fatalf("Connect: expected err") } status, _ := status.FromError(err) if status.Code() != codes.NotFound { t.Errorf( "Connect: Want error code %d got %d", codes.NotFound, status.Code()) } } type sendErrorConnectStream struct { reqs []*pb.ConnectRequest t *testing.T stop bool respMu sync.Mutex resps []*pb.StreamBlurbsResponse nextMu sync.Mutex next int pb.Messaging_ConnectServer } func (m *sendErrorConnectStream) Recv() (*pb.ConnectRequest, error) { if m.next < len(m.reqs) { req := m.reqs[m.next] m.next++ return req, nil } if m.stop { return nil, io.EOF } return nil, nil } func (m *sendErrorConnectStream) Send(r *pb.StreamBlurbsResponse) error { return status.Error(codes.Unknown, "Error") } func TestConnect_sendError(t *testing.T) { reqs := []*pb.ConnectRequest{ { Request: &pb.ConnectRequest_Config{ Config: &pb.ConnectRequest_ConnectConfig{ Parent: "users/rumble/profile", }, }, }, { Request: &pb.ConnectRequest_Blurb{ Blurb: &pb.Blurb{ User: "users/rumble", Content: &pb.Blurb_Text{Text: "woof"}, }, }, }, } m := &sendErrorConnectStream{ reqs: reqs, t: t, resps: []*pb.StreamBlurbsResponse{}, } s := NewMessagingServer(&mockIdentityServer{}) err := s.Connect(m) if err == nil { t.Fatalf("Connect: expected err") } status, _ := status.FromError(err) if status.Code() != codes.Unknown { t.Errorf( "Connect: Want error code %d got %d", codes.Unknown, status.Code()) } } func TestConnect_parentNotFoundLater(t *testing.T) { // Setup Identity server to validate parent against. is := NewIdentityServer() first, err := is.CreateUser( context.Background(), &pb.CreateUserRequest{ User: &pb.User{DisplayName: "rumbledog", Email: "rumble@example.com"}, }) if err != nil { t.Errorf("Create: unexpected err %+v", err) } parent := fmt.Sprintf("%s/profile", first.GetName()) reqs := []*pb.ConnectRequest{ { Request: &pb.ConnectRequest_Config{ Config: &pb.ConnectRequest_ConnectConfig{ Parent: parent, }, }, }, { Request: &pb.ConnectRequest_Blurb{ Blurb: &pb.Blurb{ User: "users/rumble", Content: &pb.Blurb_Text{Text: "woof"}, }, }, }, } m := &mockConnectStream{ reqs: reqs, t: t, resps: []*pb.StreamBlurbsResponse{}, } // We specify the now function so we can control when the stream ends. s := &messagingServerImpl{ identityServer: is, token: server.NewTokenGenerator(), roomKeys: map[string]int{}, blurbKeys: map[string]blurbIndex{}, blurbs: map[string][]blurbEntry{}, parentUids: map[string]*server.UniqID{}, observers: map[string]map[string]blurbObserver{}, nowF: time.Now, } g := new(errgroup.Group) g.Go(func() error { err := s.Connect(m) if err == nil { return fmt.Errorf("Connect: expected err, but did not get one") } status, _ := status.FromError(err) if status.Code() != codes.NotFound { return fmt.Errorf( "Connect: Want error code %d got %d", codes.NotFound, status.Code()) } return nil }) for { if s.hasObservers(parent) { break } } // Delete the user so that the parent is invalid. is.DeleteUser( context.Background(), &pb.DeleteUserRequest{Name: first.GetName()}) if err := g.Wait(); err != nil { t.Error(err) } } func Test_Connect_creationFailure(t *testing.T) { reqs := []*pb.ConnectRequest{ { Request: &pb.ConnectRequest_Config{ Config: &pb.ConnectRequest_ConnectConfig{ Parent: "users/rumble/profile", }, }, }, { Request: &pb.ConnectRequest_Blurb{ Blurb: &pb.Blurb{ Content: &pb.Blurb_Text{Text: "woof"}, }, }, }, } m := &mockConnectStream{ reqs: reqs, t: t, resps: []*pb.StreamBlurbsResponse{}, } s := NewMessagingServer(&mockIdentityServer{}) err := s.Connect(m) if err == nil { t.Fatalf("Connect: expected err") } status, _ := status.FromError(err) if status.Code() != codes.InvalidArgument { t.Errorf( "Connect: Want error code %d got %d", codes.InvalidArgument, status.Code()) } } ================================================ FILE: server/services/operations_service.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package services import ( "context" "encoding/base64" "math/rand" "strconv" "strings" "time" lropb "cloud.google.com/go/longrunning/autogen/longrunningpb" "github.com/golang/protobuf/ptypes" "github.com/golang/protobuf/ptypes/empty" "github.com/googleapis/gapic-showcase/server" pb "github.com/googleapis/gapic-showcase/server/genproto" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" ) // NewOperationsServer returns a new OperationsServer for the Showcase API. func NewOperationsServer(messagingServer MessagingServer) lropb.OperationsServer { return &operationsServerImpl{waiter: server.GetWaiterInstance(), messagingServer: messagingServer} } type operationsServerImpl struct { messagingServer MessagingServer waiter server.Waiter } func (s *operationsServerImpl) GetOperation(ctx context.Context, in *lropb.GetOperationRequest) (*lropb.Operation, error) { if op, err := s.handleWait(in); op != nil || err != nil { return op, err } if op, err := s.handleSearchBlurbs(in); op != nil || err != nil { return op, err } return nil, status.Errorf(codes.NotFound, "Operation %q not found.", in.Name) } func (s *operationsServerImpl) handleWait(in *lropb.GetOperationRequest) (*lropb.Operation, error) { prefix := "operations/google.showcase.v1beta1.Echo/Wait/" if !strings.HasPrefix(in.Name, prefix) { return nil, nil } waitReq := &pb.WaitRequest{} encodedBytes := strings.TrimPrefix(in.Name, prefix) waitReqBytes, err := base64.StdEncoding.DecodeString(encodedBytes) if err != nil { return nil, status.Errorf(codes.NotFound, "Operation %q not found.", in.Name) } err = proto.Unmarshal(waitReqBytes, waitReq) if err != nil { return nil, status.Errorf(codes.NotFound, "Operation %q not found.", in.Name) } return s.waiter.Wait(waitReq), nil } func (s *operationsServerImpl) handleSearchBlurbs(in *lropb.GetOperationRequest) (*lropb.Operation, error) { prefix := "operations/google.showcase.v1beta1.Messaging/SearchBlurbs/" if !strings.HasPrefix(in.GetName(), prefix) { return nil, nil } req := &pb.SearchBlurbsRequest{} encodedBytes := strings.TrimPrefix(in.GetName(), prefix) waitReqBytes, err := base64.StdEncoding.DecodeString(encodedBytes) if err != nil { return nil, status.Errorf(codes.NotFound, "Operation %q not found.", in.Name) } err = proto.Unmarshal(waitReqBytes, req) if err != nil { return nil, status.Errorf(codes.NotFound, "Operation %q not found.", in.Name) } // TODO(landrito): add some randomization here so that the search blurbs // operation could take multiple get calls to complete. listResp, err := s.messagingServer.FilteredListBlurbs( context.Background(), &pb.ListBlurbsRequest{ Parent: req.GetParent(), PageSize: req.GetPageSize(), PageToken: req.GetPageToken(), }, searchFilterFunc(req.GetQuery())) answer := &lropb.Operation{ Name: in.GetName(), Done: true, } resp, _ := ptypes.MarshalAny( &pb.SearchBlurbsResponse{ Blurbs: listResp.GetBlurbs(), NextPageToken: listResp.GetNextPageToken(), }) answer.Result = &lropb.Operation_Response{Response: resp} return answer, nil } func searchFilterFunc(query string) func(b *pb.Blurb) bool { return func(b *pb.Blurb) bool { for _, s := range strings.Fields(query) { if strings.Index(b.GetText(), s) >= 0 { return true } } return false } } // CancelOperation returns a successful response if the resource name is not blank func (s operationsServerImpl) CancelOperation(ctx context.Context, in *lropb.CancelOperationRequest) (*empty.Empty, error) { if in.Name == "" { return nil, status.Error(codes.NotFound, "cannot cancel operation without a name.") } return &empty.Empty{}, nil } // ListOperations returns a fixed response matching the given PageSize if the resource name is not blank func (s operationsServerImpl) ListOperations(ctx context.Context, in *lropb.ListOperationsRequest) (*lropb.ListOperationsResponse, error) { if in.Name == "" { return nil, status.Error(codes.NotFound, "cannot list operation without a name.") } var operations []*lropb.Operation if in.PageSize > 0 { for i := 1; i <= int(in.PageSize); i++ { var result *lropb.Operation_Response if i%2 == 0 { result = &lropb.Operation_Response{} } operations = append(operations, &lropb.Operation{ Name: "the/thing/" + strconv.Itoa(i), Done: result != nil, Result: result, }) } } else { operations = append(operations, &lropb.Operation{ Name: "a/pending/thing", Done: false, }) } return &lropb.ListOperationsResponse{ Operations: operations, }, nil } // DeleteOperation returns a successful response if the resource name is not blank func (s operationsServerImpl) DeleteOperation(ctx context.Context, in *lropb.DeleteOperationRequest) (*empty.Empty, error) { if in.Name == "" { return nil, status.Error(codes.NotFound, "cannot delete operation without a name.") } return &empty.Empty{}, nil } // WaitOperation randomly waits and returns an operation with the same name func (s operationsServerImpl) WaitOperation(ctx context.Context, in *lropb.WaitOperationRequest) (*lropb.Operation, error) { if in.Name == "" { return nil, status.Error(codes.NotFound, "cannot wait on a operation without a name.") } num := rand.Intn(500) time.Sleep(time.Duration(num) * time.Millisecond) var result *lropb.Operation_Response if num%2 == 0 { result = &lropb.Operation_Response{} } return &lropb.Operation{ Name: in.Name, Done: result != nil, Result: result, }, nil } ================================================ FILE: server/services/operations_service_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package services import ( "context" "encoding/base64" "fmt" "testing" "time" lropb "cloud.google.com/go/longrunning/autogen/longrunningpb" "github.com/golang/protobuf/ptypes" "github.com/googleapis/gapic-showcase/server" pb "github.com/googleapis/gapic-showcase/server/genproto" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" ) func TestGetOperation_wait(t *testing.T) { endTime, _ := ptypes.TimestampProto(time.Now()) waitReq := &pb.WaitRequest{End: &pb.WaitRequest_EndTime{EndTime: endTime}} nameBytes, _ := proto.Marshal(waitReq) req := &lropb.GetOperationRequest{ Name: fmt.Sprintf( "operations/google.showcase.v1beta1.Echo/Wait/%s", base64.StdEncoding.EncodeToString(nameBytes)), } waiter := &mockWaiter{} server := &operationsServerImpl{waiter: waiter} server.GetOperation(context.Background(), req) if !proto.Equal(waiter.req, waitReq) { t.Error("Expected echo.Wait to defer to waiter.") } } type messagingServerWrapper struct { listReq *pb.ListBlurbsRequest MessagingServer } func (m *messagingServerWrapper) FilteredListBlurbs(ctx context.Context, r *pb.ListBlurbsRequest, f func(*pb.Blurb) bool) (*pb.ListBlurbsResponse, error) { m.listReq = r return m.MessagingServer.FilteredListBlurbs(ctx, r, f) } func TestGetOperation_searchBlurbs(t *testing.T) { expected := []*pb.Blurb{ { User: "users/rumble", Content: &pb.Blurb_Text{Text: "woof"}, }, { User: "users/ekko", Content: &pb.Blurb_Text{Text: "bark"}, }, } wrapped := &messagingServerWrapper{ MessagingServer: &messagingServerImpl{ identityServer: &mockIdentityServer{}, roomKeys: map[string]int{}, parentUids: map[string]*server.UniqID{}, token: server.NewTokenGenerator(), blurbKeys: map[string]blurbIndex{ "users/rumble/profile/messages/1": { row: "users/rumble/profile", col: 1}, "users/rumble/profile/messages/2": { row: "users/rumble/profile", col: 2}, "users/rumble/profile/messages/3": { row: "users/rumble/profile", col: 3}, "users/rumble/profile/messages/4": { row: "users/rumble/profile", col: 4}, }, blurbs: map[string][]blurbEntry{ "users/rumble/profile": { blurbEntry{blurb: expected[0]}, blurbEntry{ blurb: &pb.Blurb{ User: "users/musubi", Content: &pb.Blurb_Text{Text: "meow"}, }, }, blurbEntry{blurb: expected[1]}, blurbEntry{blurb: expected[1], deleted: true}, blurbEntry{ blurb: &pb.Blurb{ User: "users/musubi", Content: &pb.Blurb_Text{Text: "meow"}, }, }, }, }, }, } server := NewOperationsServer(wrapped) searchReq := &pb.SearchBlurbsRequest{ Query: "woof bark", Parent: "users/rumble/profile", PageSize: 2, } reqBytes, _ := proto.Marshal(searchReq) req := &lropb.GetOperationRequest{ Name: fmt.Sprintf( "operations/google.showcase.v1beta1.Messaging/SearchBlurbs/%s", base64.StdEncoding.EncodeToString(reqBytes)), } op, err := server.GetOperation(context.Background(), req) if err != nil { t.Errorf("GetOperation: unexpected err %+v", err) } listReq := wrapped.listReq if listReq.Parent != searchReq.GetParent() { t.Errorf( "GetOperation searchBlurbs: list request parent expected %s got %s", searchReq.GetParent(), listReq.Parent) } if listReq.PageSize != searchReq.GetPageSize() { t.Errorf( "GetOperation searchBlurbs: list request page size expected %d got %d", searchReq.GetPageSize(), listReq.PageSize) } if listReq.PageToken != searchReq.GetPageToken() { t.Errorf( "GetOperation searchBlurbs: list request page token expected %s got %s", searchReq.GetPageToken(), listReq.PageToken) } if !op.Done { t.Errorf("SearchBlurbs() for %q expected done=true got done=false", req) } if op.Metadata != nil { t.Errorf("SearchBlurbs() for %q expected nil metadata, got %q", req, op.Metadata) } if op.GetError() != nil { t.Errorf("SearchBlurbs() expected op.Error=nil, got %q", op.GetError()) } if op.GetResponse() == nil { t.Error("SearchBlurbs() expected op.Response!=nil") } resp := &pb.SearchBlurbsResponse{} ptypes.UnmarshalAny(op.GetResponse(), resp) if len(resp.GetBlurbs()) != len(expected) { t.Errorf( "SearchBlurbs() expected blurbs size %d, got %d", len(expected), len(resp.GetBlurbs())) } for i, b := range expected { if !proto.Equal(b, resp.GetBlurbs()[i]) { t.Errorf( "SearchBlurbs().blurbs[%d] want %+v, got %+v", i, b, resp.GetBlurbs()[i], ) } } } func TestGetOperation_notFoundOperation(t *testing.T) { req := &lropb.GetOperationRequest{ Name: "BOGUS", } server := NewOperationsServer(nil) _, err := server.GetOperation(context.Background(), req) s, _ := status.FromError(err) if codes.NotFound != s.Code() { t.Errorf("GetOperation with invalid name expected code=%d, got %d", codes.NotFound, s.Code()) } } func TestGetOperation_invalidEncodedName(t *testing.T) { prefixes := []string{ "operations/google.showcase.v1beta1.Echo/Wait", "operations/google.showcase.v1beta1.Messaging/SearchBlurbs", } for _, p := range prefixes { req := &lropb.GetOperationRequest{ Name: fmt.Sprintf("%s/BOGUS", p), } server := NewOperationsServer(nil) _, err := server.GetOperation(context.Background(), req) s, _ := status.FromError(err) if codes.NotFound != s.Code() { t.Errorf("GetOperation with invalid name expected code=%d, got %d", codes.NotFound, s.Code()) } } } func TestGetOperation_invalidMarshalledProto(t *testing.T) { prefixes := []string{ "operations/google.showcase.v1beta1.Echo/Wait", "operations/google.showcase.v1beta1.Messaging/SearchBlurbs", } for _, p := range prefixes { name := fmt.Sprintf( "%s/%s", p, base64.StdEncoding.EncodeToString([]byte("BOGUS"))) req := &lropb.GetOperationRequest{ Name: name, } server := NewOperationsServer(nil) _, err := server.GetOperation(context.Background(), req) s, _ := status.FromError(err) if codes.NotFound != s.Code() { t.Errorf("GetOperation with invalid name expected code=%d, got %d", codes.NotFound, s.Code()) } } } func TestCancelOperation(t *testing.T) { server := NewOperationsServer(nil) _, err := server.CancelOperation(context.Background(), &lropb.CancelOperationRequest{ Name: "a/thing", }) if err != nil { t.Error("CancelOperation should have been successful") } } func TestCancelOperation_notFound(t *testing.T) { server := NewOperationsServer(nil) _, err := server.CancelOperation(context.Background(), &lropb.CancelOperationRequest{}) s, _ := status.FromError(err) if codes.NotFound != s.Code() { t.Errorf("CancelOperation expected code=%d, got %d", codes.NotFound, s.Code()) } } func TestServerListOperation(t *testing.T) { server := NewOperationsServer(nil) res, err := server.ListOperations(context.Background(), &lropb.ListOperationsRequest{ Name: "something", }) if err != nil { t.Error("ListOperations should have been successful") } if len(res.Operations) != 1 { t.Error("ListOperations should have a result") } res, err = server.ListOperations(context.Background(), &lropb.ListOperationsRequest{ Name: "other", PageSize: 8, }) if err != nil { t.Error("ListOperations should have been successful") } if len(res.Operations) != 8 { t.Error("ListOperations should have 8 results") } if len(res.NextPageToken) > 0 { t.Error("ListOperations should not have more than 1 page") } } func TestServerListOperation_notFound(t *testing.T) { server := NewOperationsServer(nil) _, err := server.ListOperations(context.Background(), &lropb.ListOperationsRequest{}) s, _ := status.FromError(err) if codes.NotFound != s.Code() { t.Errorf("ListOperations expected code=%d, got %d", codes.NotFound, s.Code()) } } func TestServerDeleteOperation(t *testing.T) { server := NewOperationsServer(nil) _, err := server.DeleteOperation(context.Background(), &lropb.DeleteOperationRequest{ Name: "/delete/the/thing", }) if err != nil { t.Errorf("DeleteOperations should have been successful") } } func TestServerDeleteOperation_notFound(t *testing.T) { server := NewOperationsServer(nil) _, err := server.DeleteOperation(context.Background(), &lropb.DeleteOperationRequest{}) s, _ := status.FromError(err) if codes.NotFound != s.Code() { t.Errorf("DeleteOperations expected code=%d, got %d", codes.NotFound, s.Code()) } } func TestServerWaitOperation(t *testing.T) { server := NewOperationsServer(nil) done, notDone := false, false for { res, err := server.WaitOperation(context.Background(), &lropb.WaitOperationRequest{ Name: "some/op", }) if err != nil { t.Errorf("DeleteOperations should have been successful") } if res.Done { done = true } else { notDone = true } if done && notDone { break } } } func TestServerWaitOperation_notFound(t *testing.T) { server := NewOperationsServer(nil) _, err := server.WaitOperation(context.Background(), &lropb.WaitOperationRequest{}) s, _ := status.FromError(err) if codes.NotFound != s.Code() { t.Errorf("WaitOperations expected code=%d, got %d", codes.NotFound, s.Code()) } } ================================================ FILE: server/services/sequence_service.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package services import ( "context" "fmt" "strings" "sync" "time" "github.com/golang/protobuf/ptypes" "github.com/golang/protobuf/ptypes/duration" "github.com/golang/protobuf/ptypes/empty" "github.com/googleapis/gapic-showcase/server" pb "github.com/googleapis/gapic-showcase/server/genproto" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) // NewSequenceServer returns a new SequenceServer for the Showcase API. func NewSequenceServer() pb.SequenceServiceServer { return &sequenceServerImpl{ token: server.NewTokenGenerator(), sequences: sync.Map{}, reports: sync.Map{}, streamingSequences: sync.Map{}, streamingReports: sync.Map{}, } } type sequenceServerImpl struct { uid server.UniqID token server.TokenGenerator sequences sync.Map reports sync.Map streamingSequences sync.Map streamingReports sync.Map } func (s *sequenceServerImpl) CreateSequence(ctx context.Context, in *pb.CreateSequenceRequest) (*pb.Sequence, error) { seq := clone(in.GetSequence()) // Assign Name. id := s.uid.Next() seq.Name = fmt.Sprintf("sequences/%d", id) report := &pb.SequenceReport{ Name: report(seq.GetName()), } s.sequences.Store(seq.GetName(), seq) s.reports.Store(report.GetName(), report) return seq, nil } func (s *sequenceServerImpl) AttemptSequence(ctx context.Context, in *pb.AttemptSequenceRequest) (*empty.Empty, error) { received := time.Now() name := in.GetName() if name == "" { return nil, status.Errorf( codes.InvalidArgument, "The field `name` is required.") } // Retrieve Sequence and associated SequenceReport. i, ok := s.sequences.Load(name) if !ok { return nil, status.Errorf( codes.NotFound, "The Sequence with %q does not exist.", name, ) } seq := i.(*pb.Sequence) i, _ = s.reports.Load(report(name)) rep, _ := i.(*pb.SequenceReport) // Retrieve the attempt deadline. deadline, _ := ctx.Deadline() dpb, err := ptypes.TimestampProto(deadline) if err != nil { return nil, status.Errorf( codes.Internal, "%s", err.Error(), ) } // Get the number of attempts, which coincides with this attempt's number. n := len(rep.Attempts) // Prepare the attempt response defined by the Sequence. st := status.New(codes.OK, "Successful attempt") var delay time.Duration responses := seq.GetResponses() if l := len(responses); l > 0 && n < l { resp := responses[n] delay = resp.GetDelay().AsDuration() st = status.FromProto(resp.GetStatus()) } else if n > l { st = status.New(codes.OutOfRange, "Attempt exceeded predefined responses") } // A delay of 0 returns immediately. time.Sleep(delay) // Calculate the perceived delay since the last RPC attempt. attDelay := &duration.Duration{} if n > 0 { prev := rep.GetAttempts()[n-1] respTime := prev.GetResponseTime() d := received.Sub(respTime.AsTime()) attDelay = ptypes.DurationProto(d) } // Clock the time that the server is sending the response responseTime := time.Now() rpb, err := ptypes.TimestampProto(responseTime) if err != nil { return nil, status.Errorf( codes.Internal, "%s", err.Error(), ) } rep.Attempts = append(rep.Attempts, &pb.SequenceReport_Attempt{ AttemptNumber: int32(n), AttemptDeadline: dpb, ResponseTime: rpb, AttemptDelay: attDelay, Status: st.Proto(), }) return &empty.Empty{}, st.Err() } func (s *sequenceServerImpl) GetSequenceReport(ctx context.Context, in *pb.GetSequenceReportRequest) (*pb.SequenceReport, error) { name := in.GetName() if name == "" { return nil, status.Errorf( codes.InvalidArgument, "The field `name` is required.") } report, ok := s.reports.Load(name) if !ok { return nil, status.Errorf( codes.NotFound, "The sequence report with %q does not exist.", name, ) } return report.(*pb.SequenceReport), nil } func report(n string) string { return fmt.Sprintf("%s/sequenceReport", n) } func clone(s *pb.Sequence) *pb.Sequence { r := make([]*pb.Sequence_Response, len(s.GetResponses())) copy(r, s.GetResponses()) return &pb.Sequence{ Name: s.GetName(), Responses: r, } } func (s *sequenceServerImpl) CreateStreamingSequence(ctx context.Context, in *pb.CreateStreamingSequenceRequest) (*pb.StreamingSequence, error) { seq := cloneStreamingSequence(in.GetStreamingSequence()) // Assign Name. id := s.uid.Next() seq.Name = fmt.Sprintf("streamingSequences/%d", id) report := &pb.StreamingSequenceReport{ Name: streamingReport(seq.GetName()), } s.streamingSequences.Store(seq.GetName(), seq) s.streamingReports.Store(report.GetName(), report) return seq, nil } func (s *sequenceServerImpl) AttemptStreamingSequence(in *pb.AttemptStreamingSequenceRequest, stream pb.SequenceService_AttemptStreamingSequenceServer) error { received := time.Now() name := in.GetName() lastFailIndex := in.GetLastFailIndex() if name == "" { return status.Errorf( codes.InvalidArgument, "The field `name` is required.") } // Retrieve Sequence and associated SequenceReport. i, ok := s.streamingSequences.Load(name) if !ok { return status.Errorf( codes.NotFound, "The Sequence with %q does not exist.", name, ) } seq := i.(*pb.StreamingSequence) i, _ = s.streamingReports.Load(streamingReport(name)) rep, _ := i.(*pb.StreamingSequenceReport) // Get the number of attempts, which coincides with this attempt's number. n := len(rep.Attempts) // Prepare the attempt response defined by the Sequence. st := status.New(codes.OK, "Successful attempt") respIndex := 0 var delay time.Duration responses := seq.GetResponses() content := strings.Fields(seq.GetContent()) if l := len(responses); l > 0 && n < l { resp := responses[n] delay = resp.GetDelay().AsDuration() st = status.FromProto(resp.GetStatus()) respIndex = int(resp.ResponseIndex) } else if n > l { st = status.New(codes.OutOfRange, "Attempt exceeded predefined responses") } if lastFailIndex < 0 { lastFailIndex = 0 } for idx, word := range content[lastFailIndex:] { if idx >= respIndex { break } err := stream.Send(&pb.AttemptStreamingSequenceResponse{Content: word}) if err != nil { return err } } echoStreamingHeaders(stream) echoStreamingTrailers(stream) time.Sleep(delay) // Calculate the perceived delay since the last RPC attempt. attDelay := &duration.Duration{} if n > 0 { prev := rep.GetAttempts()[n-1] respTime := prev.GetResponseTime() d := received.Sub(respTime.AsTime()) attDelay = ptypes.DurationProto(d) } // Clock the time that the server is sending the response responseTime := time.Now() rpb, err := ptypes.TimestampProto(responseTime) if err != nil { return status.Errorf( codes.Internal, "%s", err.Error(), ) } rep.Attempts = append(rep.Attempts, &pb.StreamingSequenceReport_Attempt{ AttemptNumber: int32(n), ResponseTime: rpb, AttemptDelay: attDelay, Status: st.Proto(), }) return st.Err() } func (s *sequenceServerImpl) GetStreamingSequenceReport(ctx context.Context, in *pb.GetStreamingSequenceReportRequest) (*pb.StreamingSequenceReport, error) { name := in.GetName() if name == "" { return nil, status.Errorf( codes.InvalidArgument, "The field `name` is required.") } report, ok := s.streamingReports.Load(name) if !ok { return nil, status.Errorf( codes.NotFound, "The sequence report with %q does not exist.", name, ) } return report.(*pb.StreamingSequenceReport), nil } func cloneStreamingSequence(s *pb.StreamingSequence) *pb.StreamingSequence { r := make([]*pb.StreamingSequence_Response, len(s.GetResponses())) copy(r, s.GetResponses()) return &pb.StreamingSequence{ Name: s.GetName(), Content: s.GetContent(), Responses: r, } } func streamingReport(n string) string { return fmt.Sprintf("%s/streamingSequenceReport", n) } ================================================ FILE: server/services/sequence_service_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package services import ( "context" "reflect" "strings" "testing" "time" "github.com/golang/protobuf/ptypes" pb "github.com/googleapis/gapic-showcase/server/genproto" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" ) func TestSequenceEmpty(t *testing.T) { s := NewSequenceServer() seq, err := s.CreateSequence(context.Background(), &pb.CreateSequenceRequest{}) if err != nil { t.Errorf("CreateSequence(empty): unexpected err %+v", err) } timeout := 5 * time.Second ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() e, err := s.AttemptSequence(ctx, &pb.AttemptSequenceRequest{Name: seq.GetName()}) if err != nil { t.Errorf("AttemptSequence(empty): unexpected err %+v", err) } if e == nil { t.Errorf("AttemptSequence(empty): unexpected nil Empty response") } r := report(seq.GetName()) report, err := s.GetSequenceReport(context.Background(), &pb.GetSequenceReportRequest{Name: r}) if err != nil { t.Errorf("GetSequenceReport(empty): unexpected err %+v", err) } attempts := report.GetAttempts() if len(attempts) != 1 { t.Errorf("%s: expected number of attempts to be 1 but was %d", t.Name(), len(attempts)) } a := attempts[0] ad := a.GetAttemptDeadline().AsTime() d, _ := ctx.Deadline() if !ad.Equal(d) { t.Errorf("%s: server deadline = %v client deadline = %v", t.Name(), ad, d) } } func TestSequenceRetry(t *testing.T) { s := NewSequenceServer() responses := []*pb.Sequence_Response{ { Status: status.New(codes.Unavailable, "Unavailable").Proto(), Delay: ptypes.DurationProto(1 * time.Second), }, { Status: status.New(codes.Unavailable, "Unavailable").Proto(), Delay: ptypes.DurationProto(2 * time.Second), }, { Status: status.New(codes.OK, "OK").Proto(), }, } seq, err := s.CreateSequence(context.Background(), &pb.CreateSequenceRequest{ Sequence: &pb.Sequence{Responses: responses}, }) if err != nil { t.Errorf("CreateSequence(retry): unexpected err %+v", err) } timeout := 5 * time.Second ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() delay := 100 * time.Millisecond for n, r := range responses { res := status.FromProto(r.GetStatus()) _, err = s.AttemptSequence(ctx, &pb.AttemptSequenceRequest{Name: seq.GetName()}) if c := status.Code(err); c != res.Code() { t.Errorf("%s: status #%d was %v wanted %v", t.Name(), n, c, res.Code()) } if n != len(responses)-1 { time.Sleep(delay) delay *= 2 } } r := report(seq.GetName()) report, err := s.GetSequenceReport(context.Background(), &pb.GetSequenceReportRequest{Name: r}) if err != nil { t.Errorf("GetSequenceReport(retry): unexpected err %+v", err) } attempts := report.GetAttempts() if len(attempts) != len(responses) { t.Errorf("%s: expected number of attempts to be %d but was %d", t.Name(), len(responses), len(attempts)) } d, _ := ctx.Deadline() for n, a := range attempts { if got, want := a.GetAttemptNumber(), int32(n); got != want { t.Errorf("%s: expected attempt #%d but was #%d", t.Name(), want, got) } if got, want := a.GetAttemptDeadline().AsTime(), d; !got.Equal(want) { t.Errorf("%s: server deadline = %v client deadline = %v", t.Name(), got, want) } if got, want := a.GetStatus().GetCode(), responses[n].GetStatus().GetCode(); got != want { t.Errorf("%s: expected response %v but was %v", t.Name(), want, got) } // Check that perceived delay between attempts was changing as expected. if n > 0 { if cur, prev := a.GetAttemptDelay().AsDuration(), attempts[n-1].GetAttemptDelay().AsDuration(); cur <= prev { t.Errorf("%s: expected attempt delay: %v to be larger than previous: %v", t.Name(), cur, prev) } } } } func TestSequenceOutOfRange(t *testing.T) { s := NewSequenceServer() seq, err := s.CreateSequence(context.Background(), &pb.CreateSequenceRequest{}) if err != nil { t.Errorf("CreateSequence(out_of_range): unexpected err %+v", err) } timeout := 5 * time.Second ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() e, err := s.AttemptSequence(ctx, &pb.AttemptSequenceRequest{Name: seq.GetName()}) if err != nil { t.Errorf("AttemptSequence(out_of_range): unexpected err %+v", err) } if e == nil { t.Errorf("AttemptSequence(out_of_range): unexpected nil Empty response") } _, err = s.AttemptSequence(ctx, &pb.AttemptSequenceRequest{Name: seq.GetName()}) if c := status.Code(err); c != codes.OutOfRange { t.Errorf("%s: status was %v wanted %v", t.Name(), c, codes.OutOfRange) } _, err = s.AttemptSequence(ctx, &pb.AttemptSequenceRequest{Name: seq.GetName()}) if c := status.Code(err); c != codes.OutOfRange { t.Errorf("%s: status was %v wanted %v", t.Name(), c, codes.OutOfRange) } r := report(seq.GetName()) report, err := s.GetSequenceReport(context.Background(), &pb.GetSequenceReportRequest{Name: r}) if err != nil { t.Errorf("GetSequenceReport(out_of_range): unexpected err %+v", err) } attempts := report.GetAttempts() if len(attempts) != 3 { t.Errorf("%s: expected number of attempts to be 3 but was %d", t.Name(), len(attempts)) } a := attempts[0] ad := a.GetAttemptDeadline().AsTime() d, _ := ctx.Deadline() if !ad.Equal(d) { t.Errorf("%s: server deadline = %v client deadline = %v", t.Name(), ad, d) } } func TestGetSequenceReportNotFound(t *testing.T) { s := NewSequenceServer() _, err := s.GetSequenceReport(context.Background(), &pb.GetSequenceReportRequest{Name: "foo/bar/baz"}) if c := status.Code(err); c != codes.NotFound { t.Errorf("%s: expected error to be %s but was %s", t.Name(), codes.NotFound, c) } } func TestGetSequenceReportMissingName(t *testing.T) { s := NewSequenceServer() _, err := s.GetSequenceReport(context.Background(), &pb.GetSequenceReportRequest{Name: ""}) if c := status.Code(err); c != codes.InvalidArgument { t.Errorf("%s: expected error to be %s but was %s", t.Name(), codes.InvalidArgument, c) } } func TestAttemptSequenceNotFound(t *testing.T) { s := NewSequenceServer() _, err := s.AttemptSequence(context.Background(), &pb.AttemptSequenceRequest{Name: "foo/bar/baz"}) if c := status.Code(err); c != codes.NotFound { t.Errorf("%s: expected error to be %s but was %s", t.Name(), codes.NotFound, c) } } func TestAttemptSequenceMissingName(t *testing.T) { s := NewSequenceServer() _, err := s.AttemptSequence(context.Background(), &pb.AttemptSequenceRequest{Name: ""}) if c := status.Code(err); c != codes.InvalidArgument { t.Errorf("%s: expected error to be %s but was %s", t.Name(), codes.InvalidArgument, c) } } type mockStreamSequence struct { exp []string head []string trail []string t *testing.T pb.SequenceService_AttemptStreamingSequenceServer } func (m *mockStreamSequence) Context() context.Context { return appendTestOutgoingMetadata(context.Background(), &mockSTS{stream: m, t: m.t}) } func (m *mockStreamSequence) SetTrailer(md metadata.MD) { m.trail = append(m.trail, md.Get("showcase-trailer")...) } func (m *mockStreamSequence) SetHeader(md metadata.MD) error { m.head = append(m.head, md.Get("x-goog-request-params")...) return nil } func (m *mockStreamSequence) verify(expectHeadersAndTrailers bool) { if len(m.exp) > 0 { m.t.Errorf("Expand did not stream all expected values. %d expected values remaining.", len(m.exp)) } if expectHeadersAndTrailers && (!reflect.DeepEqual([]string{"show", "case"}, m.trail) || !reflect.DeepEqual([]string{"showcaseHeader", "anotherHeader"}, m.head)) { m.t.Errorf("Expand did not get all expected headers and trailers.\nGot these headers: %+v\nGot these trailers: %+v", m.head, m.trail) } } func TestStreamingSequenceEmpty(t *testing.T) { s := NewSequenceServer() seq, err := s.CreateStreamingSequence(context.Background(), &pb.CreateStreamingSequenceRequest{}) if err != nil { t.Errorf("CreateSequence(empty): unexpected err %+v", err) } stream := &mockStreamSequence{} timeout := 5 * time.Second _, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() err = s.AttemptStreamingSequence(&pb.AttemptStreamingSequenceRequest{Name: seq.GetName()}, stream) if err != nil { t.Errorf("AttemptSequence(empty): unexpected err %+v", err) } r := streamingReport(seq.GetName()) report, err := s.GetStreamingSequenceReport(context.Background(), &pb.GetStreamingSequenceReportRequest{Name: r}) if err != nil { t.Errorf("GetSequenceReport(empty): unexpected err %+v", err) } attempts := report.GetAttempts() if len(attempts) != 1 { t.Errorf("%s: expected number of attempts to be 1 but was %d", t.Name(), len(attempts)) } } func TestStreamingSequenceRetry(t *testing.T) { s := NewSequenceServer() responses := []*pb.StreamingSequence_Response{ { Status: status.New(codes.Unavailable, "Unavailable").Proto(), Delay: ptypes.DurationProto(1 * time.Second), }, { Status: status.New(codes.Unavailable, "Unavailable").Proto(), Delay: ptypes.DurationProto(2 * time.Second), }, { Status: status.New(codes.OK, "OK").Proto(), }, } seq, err := s.CreateStreamingSequence(context.Background(), &pb.CreateStreamingSequenceRequest{ StreamingSequence: &pb.StreamingSequence{Responses: responses, Content: "Hello World"}, }) if err != nil { t.Errorf("CreateSequence(retry): unexpected err %+v", err) } timeout := 5 * time.Second _, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() delay := 100 * time.Millisecond stream := &mockStreamSequence{} for n, r := range responses { res := status.FromProto(r.GetStatus()) err = s.AttemptStreamingSequence(&pb.AttemptStreamingSequenceRequest{Name: seq.GetName()}, stream) if c := status.Code(err); c != res.Code() { t.Errorf("%s: status #%d was %v wanted %v", t.Name(), n, c, res.Code()) } if n != len(responses)-1 { time.Sleep(delay) delay *= 2 } } r := streamingReport(seq.GetName()) report, err := s.GetStreamingSequenceReport(context.Background(), &pb.GetStreamingSequenceReportRequest{Name: r}) if err != nil { t.Errorf("GetSequenceReport(retry): unexpected err %+v", err) } attempts := report.GetAttempts() if len(attempts) != len(responses) { t.Errorf("%s: expected number of attempts to be %d but was %d", t.Name(), len(responses), len(attempts)) } for n, a := range attempts { if got, want := a.GetAttemptNumber(), int32(n); got != want { t.Errorf("%s: expected attempt #%d but was #%d", t.Name(), want, got) } if got, want := a.GetStatus().GetCode(), responses[n].GetStatus().GetCode(); got != want { t.Errorf("%s: expected response %v but was %v", t.Name(), want, got) } } } func TestStreamingSequenceWithLastFailIndex(t *testing.T) { s := NewSequenceServer() responses := []*pb.StreamingSequence_Response{ { Status: status.New(codes.Unavailable, "Unavailable").Proto(), Delay: ptypes.DurationProto(1 * time.Second), }, { Status: status.New(codes.Unavailable, "Unavailable").Proto(), Delay: ptypes.DurationProto(2 * time.Second), }, { Status: status.New(codes.OK, "OK").Proto(), }, } seq, err := s.CreateStreamingSequence(context.Background(), &pb.CreateStreamingSequenceRequest{ StreamingSequence: &pb.StreamingSequence{Responses: responses, Content: "Hello World, nice to see you"}, }) if err != nil { t.Errorf("CreateSequence(retry): unexpected err %+v", err) } timeout := 5 * time.Second _, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() delay := 100 * time.Millisecond stream := &mockStreamSequence{} for n, r := range responses { res := status.FromProto(r.GetStatus()) // by passing the LastFailIndex as 3, we force the response to be the 3rd index of content, which is "to" // the number of responses will still be the same though - the length of the sequence err = s.AttemptStreamingSequence(&pb.AttemptStreamingSequenceRequest{Name: seq.GetName(), LastFailIndex: 3}, stream) if c := status.Code(err); c != res.Code() { t.Errorf("%s: status #%d was %v wanted %v", t.Name(), n, c, res.Code()) } if n != len(responses)-1 { time.Sleep(delay) delay *= 2 } } r := streamingReport(seq.GetName()) report, err := s.GetStreamingSequenceReport(context.Background(), &pb.GetStreamingSequenceReportRequest{Name: r}) if err != nil { t.Errorf("GetSequenceReport(retry): unexpected err %+v", err) } attempts := report.GetAttempts() if len(attempts) != len(responses) { t.Errorf("%s: expected number of attempts to be %d but was %d", t.Name(), len(responses), len(attempts)) } for n, a := range attempts { if got, want := a.GetAttemptNumber(), int32(n); got != want { t.Errorf("%s: expected attempt #%d but was #%d", t.Name(), want, got) } if got, want := a.GetStatus().GetCode(), responses[n].GetStatus().GetCode(); got != want { t.Errorf("%s: expected response %v but was %v", t.Name(), want, got) } } } func TestStreamingSequenceOutOfRange(t *testing.T) { s := NewSequenceServer() seq, err := s.CreateStreamingSequence(context.Background(), &pb.CreateStreamingSequenceRequest{}) if err != nil { t.Errorf("CreateSequence(out_of_range): unexpected err %+v", err) } timeout := 5 * time.Second stream := &mockStreamSequence{} _, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() err = s.AttemptStreamingSequence(&pb.AttemptStreamingSequenceRequest{Name: seq.GetName()}, stream) if err != nil { t.Errorf("AttemptSequence(out_of_range): unexpected err %+v", err) } err = s.AttemptStreamingSequence(&pb.AttemptStreamingSequenceRequest{Name: seq.GetName()}, stream) if c := status.Code(err); c != codes.OutOfRange { t.Errorf("%s: status was %v wanted %v", t.Name(), c, codes.OutOfRange) } err = s.AttemptStreamingSequence(&pb.AttemptStreamingSequenceRequest{Name: seq.GetName()}, stream) if c := status.Code(err); c != codes.OutOfRange { t.Errorf("%s: status was %v wanted %v", t.Name(), c, codes.OutOfRange) } r := streamingReport(seq.GetName()) report, err := s.GetStreamingSequenceReport(context.Background(), &pb.GetStreamingSequenceReportRequest{Name: r}) if err != nil { t.Errorf("GetSequenceReport(out_of_range): unexpected err %+v", err) } attempts := report.GetAttempts() if len(attempts) != 3 { t.Errorf("%s: expected number of attempts to be 3 but was %d", t.Name(), len(attempts)) } } func TestAttemptStreamingSequenceNotFound(t *testing.T) { s := NewSequenceServer() stream := &mockStreamSequence{exp: strings.Fields(""), t: t} attemptRequest := &pb.AttemptStreamingSequenceRequest{Name: "sequences/0"} err := s.AttemptStreamingSequence(attemptRequest, stream) if c := status.Code(err); c != codes.NotFound { t.Errorf("%s: expected error to be %s but was %s", t.Name(), codes.NotFound, c) } } func TestAttemptStreamingSequenceMissingName(t *testing.T) { s := NewSequenceServer() stream := &mockStreamSequence{exp: strings.Fields(""), t: t} err := s.AttemptStreamingSequence(&pb.AttemptStreamingSequenceRequest{Name: ""}, stream) if c := status.Code(err); c != codes.InvalidArgument { t.Errorf("%s: expected error to be %s but was %s", t.Name(), codes.InvalidArgument, c) } } func TestGetStreamingSequenceReportMissingName(t *testing.T) { s := NewSequenceServer() _, err := s.GetStreamingSequenceReport(context.Background(), &pb.GetStreamingSequenceReportRequest{Name: ""}) if c := status.Code(err); c != codes.InvalidArgument { t.Errorf("%s: expected error to be %s but was %s", t.Name(), codes.InvalidArgument, c) } } ================================================ FILE: server/services/services.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package services import ( "log" "github.com/googleapis/gapic-showcase/server" pb "github.com/googleapis/gapic-showcase/server/genproto" locpb "google.golang.org/genproto/googleapis/cloud/location" iampb "cloud.google.com/go/iam/apiv1/iampb" lropb "cloud.google.com/go/longrunning/autogen/longrunningpb" ) // Backend contains the various service backends that will be // accessible via one or more transport endpoints. type Backend struct { // Showcase schema EchoServer pb.EchoServer IdentityServer pb.IdentityServer MessagingServer pb.MessagingServer SequenceServiceServer pb.SequenceServiceServer ComplianceServer pb.ComplianceServer TestingServer pb.TestingServer // Supporting protos OperationsServer lropb.OperationsServer LocationsServer locpb.LocationsServer IAMPolicyServer iampb.IAMPolicyServer // Other supporting data structures StdLog, ErrLog *log.Logger ObserverRegistry server.GrpcObserverRegistry } ================================================ FILE: server/services/test_common.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package services import ( lropb "cloud.google.com/go/longrunning/autogen/longrunningpb" pb "github.com/googleapis/gapic-showcase/server/genproto" ) // Mock waiter type used in echo_service_test and operations_service_test to // check that they defer to the waiter. type mockWaiter struct { req *pb.WaitRequest } func (w *mockWaiter) Wait(req *pb.WaitRequest) *lropb.Operation { w.req = req return nil } ================================================ FILE: server/services/testing_service.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package services import ( "context" "fmt" "strings" "sync" "github.com/golang/protobuf/ptypes/empty" "github.com/googleapis/gapic-showcase/server" pb "github.com/googleapis/gapic-showcase/server/genproto" "github.com/googleapis/gapic-showcase/server/spec" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) // NewTestingServer returns a new TestingServer for the Showcase API. func NewTestingServer(observerRegistry server.GrpcObserverRegistry) pb.TestingServer { name := fmt.Sprintf("sessions/-") defaultSession := server.NewSession(name, pb.Session_V1_LATEST, observerRegistry) defaultSession.RegisterTests(spec.ShowcaseTests(name, pb.Session_V1_LATEST)) sessions := []sessionEntry{{session: defaultSession}} keys := map[string]int{name: len(sessions) - 1} s := &testingServerImpl{ token: server.NewTokenGenerator(), observerRegistry: observerRegistry, keys: keys, sessions: sessions, } return s } type sessionEntry struct { session server.Session deleted bool } type testingServerImpl struct { uid server.UniqID token server.TokenGenerator observerRegistry server.GrpcObserverRegistry mu sync.Mutex keys map[string]int sessions []sessionEntry } func (s *testingServerImpl) CreateSession(_ context.Context, req *pb.CreateSessionRequest) (*pb.Session, error) { s.mu.Lock() defer s.mu.Unlock() seshProto := req.GetSession() id := s.uid.Next() name := fmt.Sprintf("sessions/%d", id) sesh := server.NewSession(name, seshProto.GetVersion(), s.observerRegistry) sesh.RegisterTests(spec.ShowcaseTests(name, seshProto.GetVersion())) index := len(s.sessions) s.sessions = append(s.sessions, sessionEntry{session: sesh}) s.keys[name] = index return server.SessionProto(sesh), nil } func (s *testingServerImpl) GetSession(_ context.Context, req *pb.GetSessionRequest) (*pb.Session, error) { s.mu.Lock() defer s.mu.Unlock() name := req.GetName() if i, ok := s.keys[name]; ok && !s.sessions[i].deleted { return server.SessionProto(s.sessions[i].session), nil } return nil, status.Errorf( codes.NotFound, "A session with name %s not found.", name) } func (s *testingServerImpl) ListSessions(_ context.Context, in *pb.ListSessionsRequest) (*pb.ListSessionsResponse, error) { s.mu.Lock() defer s.mu.Unlock() start, err := s.token.GetIndex(in.GetPageToken()) if err != nil { return nil, err } if start >= len(s.sessions) { return nil, server.InvalidTokenErr } offset := 0 sessions := []*pb.Session{} for _, entry := range s.sessions[start:] { offset++ if entry.deleted { continue } sessions = append(sessions, server.SessionProto(entry.session)) if len(sessions) >= int(in.GetPageSize()) { break } } nextToken := "" if next := start + offset; next < len(s.sessions) { nextToken = s.token.ForIndex(next) } return &pb.ListSessionsResponse{Sessions: sessions, NextPageToken: nextToken}, nil } func (s *testingServerImpl) DeleteSession(_ context.Context, req *pb.DeleteSessionRequest) (*empty.Empty, error) { s.mu.Lock() defer s.mu.Unlock() i, ok := s.keys[req.GetName()] if !ok { return nil, status.Errorf( codes.NotFound, "A session with name %s not found.", req.GetName()) } entry := s.sessions[i] s.sessions[i] = sessionEntry{session: entry.session, deleted: true} return &empty.Empty{}, nil } func (s *testingServerImpl) ReportSession(_ context.Context, req *pb.ReportSessionRequest) (*pb.ReportSessionResponse, error) { s.mu.Lock() defer s.mu.Unlock() if i, ok := s.keys[req.GetName()]; ok && !s.sessions[i].deleted { return s.sessions[i].session.GetReport(), nil } return nil, status.Errorf( codes.NotFound, "A session with name %s not found.", req.GetName()) } func (s *testingServerImpl) ListTests(_ context.Context, in *pb.ListTestsRequest) (*pb.ListTestsResponse, error) { s.mu.Lock() defer s.mu.Unlock() name := in.GetParent() if i, ok := s.keys[name]; ok && !s.sessions[i].deleted { return s.sessions[i].session.ListTests(in) } return nil, status.Errorf( codes.NotFound, "A session with name %s not found.", name) } func (s *testingServerImpl) DeleteTest(_ context.Context, req *pb.DeleteTestRequest) (*empty.Empty, error) { s.mu.Lock() defer s.mu.Unlock() for name, i := range s.keys { if strings.HasPrefix(req.GetName(), name) && !s.sessions[i].deleted { return s.sessions[i].session.DeleteTest(req.GetName()) } } return nil, status.Errorf( codes.NotFound, "A test with name %s not found.", req.GetName()) } func (s *testingServerImpl) VerifyTest(context.Context, *pb.VerifyTestRequest) (*pb.VerifyTestResponse, error) { // This should be handled by the test observers. return &pb.VerifyTestResponse{}, nil } ================================================ FILE: server/services/testing_service_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package services import ( "context" "encoding/base64" "testing" "github.com/golang/protobuf/ptypes/empty" "github.com/googleapis/gapic-showcase/server" pb "github.com/googleapis/gapic-showcase/server/genproto" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" ) func Test_Session_lifecycle(t *testing.T) { s := NewTestingServer(server.ShowcaseObserverRegistry()) first, err := s.CreateSession( context.Background(), &pb.CreateSessionRequest{ Session: &pb.Session{Version: pb.Session_V1_0}, }) if err != nil { t.Errorf("Create: unexpected err %+v", err) } delete, err := s.CreateSession( context.Background(), &pb.CreateSessionRequest{ Session: &pb.Session{Version: pb.Session_V1_0}, }) if err != nil { t.Errorf("Create: unexpected err %+v", err) } _, err = s.DeleteSession( context.Background(), &pb.DeleteSessionRequest{Name: delete.Name}) if err != nil { t.Errorf("Delete: unexpected err %+v", err) } created, err := s.CreateSession( context.Background(), &pb.CreateSessionRequest{ Session: &pb.Session{Version: pb.Session_V1_0}, }) if err != nil { t.Errorf("Create: unexpected err %+v", err) } got, err := s.GetSession( context.Background(), &pb.GetSessionRequest{Name: created.GetName()}) if err != nil { t.Errorf("Get: unexpected err %+v", err) } if !proto.Equal(created, got) { t.Error("Expected to get created session.") } r, err := s.ListSessions( context.Background(), &pb.ListSessionsRequest{PageSize: 1, PageToken: ""}) if len(r.GetSessions()) != 1 { t.Errorf("List want: page size %d, got %d", 1, len(r.GetSessions())) } if r.GetSessions()[0].GetName() != "sessions/-" { t.Errorf("List want: first session 'sessions/-', got %+v", r.GetSessions()[0]) } if r.GetNextPageToken() == "" { t.Error("List want: non empty next page token") } r, err = s.ListSessions( context.Background(), &pb.ListSessionsRequest{PageSize: 10, PageToken: r.GetNextPageToken()}) if len(r.GetSessions()) != 2 { t.Errorf("List want: page size %d, got %d", 2, len(r.GetSessions())) } if !proto.Equal(first, r.GetSessions()[0]) { t.Errorf("List want: first session %+v, got %+v", got, r.GetSessions()[0]) } if !proto.Equal(got, r.GetSessions()[1]) { t.Errorf("List want: second session %+v, got %+v", got, r.GetSessions()[1]) } if r.GetNextPageToken() != "" { t.Error("List want: empty next page token") } } func Test_GetSession_deleted(t *testing.T) { s := NewTestingServer(server.ShowcaseObserverRegistry()) created, err := s.CreateSession( context.Background(), &pb.CreateSessionRequest{ Session: &pb.Session{Version: pb.Session_V1_0}, }) if err != nil { t.Errorf("Create: unexpected err %+v", err) } _, err = s.DeleteSession( context.Background(), &pb.DeleteSessionRequest{Name: created.GetName()}) if err != nil { t.Errorf("Delete: unexpected err %+v", err) } _, err = s.GetSession( context.Background(), &pb.GetSessionRequest{Name: created.GetName()}) status, _ := status.FromError(err) if status.Code() != codes.NotFound { t.Errorf( "Get deleted: Want error code %d got %d", codes.NotFound, status.Code()) } } func Test_ListSessions_invalidToken(t *testing.T) { sessions := []sessionEntry{{session: &sessionMock{}}} keys := map[string]int{"name": len(sessions) - 1} s := &testingServerImpl{ token: server.TokenGeneratorWithSalt("salt"), keys: keys, sessions: sessions, } tests := []string{ "0", // Not base64 encoded base64.StdEncoding.EncodeToString([]byte("0")), // No salt base64.StdEncoding.EncodeToString([]byte("saltblah")), // Invalid index base64.StdEncoding.EncodeToString([]byte("salt1000")), // index out of range. } for _, token := range tests { _, err := s.ListSessions( context.Background(), &pb.ListSessionsRequest{ PageSize: 1, PageToken: token}) status, _ := status.FromError(err) if status.Code() != codes.InvalidArgument { t.Errorf( "List: Want error code %d got %d", codes.InvalidArgument, status.Code()) } } } func Test_DeleteSession_notFound(t *testing.T) { s := NewTestingServer(server.ShowcaseObserverRegistry()) _, err := s.DeleteSession( context.Background(), &pb.DeleteSessionRequest{Name: "invalid"}) status, _ := status.FromError(err) if status.Code() != codes.NotFound { t.Errorf( "Delete: Want error code %d got %d", codes.NotFound, status.Code()) } } func Test_ReportSession_notFound(t *testing.T) { s := NewTestingServer(server.ShowcaseObserverRegistry()) _, err := s.ReportSession( context.Background(), &pb.ReportSessionRequest{Name: "not found"}) status, _ := status.FromError(err) if status.Code() != codes.NotFound { t.Errorf( "ReportSession: Want error code %d got %d", codes.NotFound, status.Code()) } } type sessionMock struct { wantReport *pb.ReportSessionResponse wantList *pb.ListTestsResponse deleteCalled bool server.Session } func (s *sessionMock) GetReport() *pb.ReportSessionResponse { return s.wantReport } func (s *sessionMock) ListTests(in *pb.ListTestsRequest) (*pb.ListTestsResponse, error) { return s.wantList, nil } func (s *sessionMock) DeleteTest(name string) (*empty.Empty, error) { s.deleteCalled = true return &empty.Empty{}, nil } func Test_ReportSession(t *testing.T) { want := &pb.ReportSessionResponse{ Result: pb.ReportSessionResponse_PASSED, } sessions := []sessionEntry{{session: &sessionMock{wantReport: want}}} keys := map[string]int{"name": 0} s := &testingServerImpl{ keys: keys, sessions: sessions, } got, err := s.ReportSession( context.Background(), &pb.ReportSessionRequest{Name: "name"}) if err != nil { t.Errorf("Create: unexpected err %+v", err) } if !proto.Equal(got, want) { t.Errorf( "ReportSession: Want %+v got %+v", want, got) } } func Test_ListTests_notFound(t *testing.T) { s := NewTestingServer(server.ShowcaseObserverRegistry()) _, err := s.ListTests( context.Background(), &pb.ListTestsRequest{Parent: "not found"}) status, _ := status.FromError(err) if status.Code() != codes.NotFound { t.Errorf( "ListTests: Want error code %d got %d", codes.NotFound, status.Code()) } } func Test_ListTests(t *testing.T) { want := &pb.ListTestsResponse{ Tests: []*pb.Test{}, } sessions := []sessionEntry{{session: &sessionMock{wantList: want}}} keys := map[string]int{"name": 0} s := &testingServerImpl{ token: server.NewTokenGenerator(), keys: keys, sessions: sessions, } got, err := s.ListTests( context.Background(), &pb.ListTestsRequest{Parent: "name"}) if err != nil { t.Errorf("ListTests: unexpected err %+v", err) } if !proto.Equal(got, want) { t.Errorf( "ListTests: Want %+v got %+v", want, got) } } func Test_DeleteTest_notFound(t *testing.T) { s := NewTestingServer(server.ShowcaseObserverRegistry()) _, err := s.DeleteTest( context.Background(), &pb.DeleteTestRequest{Name: "not found"}) status, _ := status.FromError(err) if status.Code() != codes.NotFound { t.Errorf( "DeleteTest: Want error code %d got %d", codes.NotFound, status.Code()) } } func Test_DeleteTests(t *testing.T) { sesh := &sessionMock{} sessions := []sessionEntry{{session: sesh}} keys := map[string]int{"name": 0} s := &testingServerImpl{ token: server.NewTokenGenerator(), keys: keys, sessions: sessions, } _, err := s.DeleteTest( context.Background(), &pb.DeleteTestRequest{Name: "name"}) if err != nil { t.Errorf("DeleteTest: unexpected err %+v", err) } if !sesh.deleteCalled { t.Error("DeleteTest: expected to delegate call to session.") } } func Test_VerifyTest(t *testing.T) { s := NewTestingServer(server.ShowcaseObserverRegistry()) got, err := s.VerifyTest(context.Background(), &pb.VerifyTestRequest{}) if err != nil { t.Errorf("VerifyTest: unexpected err %+v", err) } if !proto.Equal(got, &pb.VerifyTestResponse{}) { t.Errorf("VerifyTest want %+v got %+v", &pb.VerifyTestResponse{}, got) } } ================================================ FILE: server/services/util.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package services import ( "google.golang.org/protobuf/reflect/protoreflect" ) func strContains(haystack []string, needle string) bool { for _, s := range haystack { if s == needle { return true } } return false } // applyFieldMask applies the values from the src message to the values of the // dst message according to the contents of the given field mask paths. // If paths is empty/nil, or contains *, it is considered a full update. // // TODO: Does not support nested message paths. Currently only used with flat // resource messages. func applyFieldMask(src, dst protoreflect.Message, paths []string) { fullUpdate := len(paths) == 0 || strContains(paths, "*") fields := dst.Descriptor().Fields() for i := 0; i < fields.Len(); i++ { field := fields.Get(i) isOneof := field.ContainingOneof() != nil && !field.ContainingOneof().IsSynthetic() // Set field in dst with value from src, skipping true oneofs, while // handling proto3_optional fields represented as synthetic oneofs. if (fullUpdate || strContains(paths, string(field.Name()))) && !isOneof { dst.Set(field, src.Get(field)) } } oneofs := dst.Descriptor().Oneofs() for i := 0; i < oneofs.Len(); i++ { oneof := oneofs.Get(i) // Skip proto3_optional synthetic oneofs. if oneof.IsSynthetic() { continue } setOneof := src.WhichOneof(oneof) if setOneof == nil && fullUpdate { // Full update with no field set in this oneof of // src means clear all fields for this oneof in dst. fields := oneof.Fields() for j := 0; j < fields.Len(); j++ { dst.Clear(fields.Get(j)) } } else if setOneof != nil && (fullUpdate || strContains(paths, string(setOneof.Name()))) { // Full update or targeted updated with a field set in this oneof of // src means set that field for the same oneof in dst, which implicitly // clears any previously set field for this oneof. dst.Set(setOneof, src.Get(setOneof)) } } } ================================================ FILE: server/session.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package server import ( "strings" "sync" "github.com/golang/protobuf/ptypes/empty" pb "github.com/googleapis/gapic-showcase/server/genproto" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) // Session represents a suite of tests, generally being made in the context // of testing code generation. // // A session defines tests it may expect, based on which version of the // code generation spec is in use. type Session interface { GetName() string GetVersion() pb.Session_Version GetReport() *pb.ReportSessionResponse RegisterTests(tests []Test) ListTests(in *pb.ListTestsRequest) (*pb.ListTestsResponse, error) DeleteTest(name string) (*empty.Empty, error) } // SessionProto returns a proto representation of the Session. func SessionProto(s Session) *pb.Session { return &pb.Session{ Name: s.GetName(), Version: s.GetVersion(), } } // NewSession returns a session for a given name, version and observerRegistry. func NewSession(name string, version pb.Session_Version, observerRegistry GrpcObserverRegistry) Session { session := &sessionImpl{ name: name, version: version, observerRegistry: observerRegistry, token: NewTokenGenerator(), keys: map[string]int{}, tests: []testEntry{}, } return session } type testEntry struct { test Test deleted bool } type sessionImpl struct { name string version pb.Session_Version observerRegistry GrpcObserverRegistry token TokenGenerator mu sync.Mutex keys map[string]int tests []testEntry } func (s *sessionImpl) GetName() string { return s.name } func (s *sessionImpl) GetVersion() pb.Session_Version { return s.version } func (s *sessionImpl) GetReport() *pb.ReportSessionResponse { result := pb.ReportSessionResponse_PASSED for _, entry := range s.tests { if entry.deleted { continue } test := entry.test issue := test.GetIssue() if issue == nil { continue } // TODO: Add severity handling if issue.GetType() == pb.Issue_INCORRECT_CONFIRMATION { result = pb.ReportSessionResponse_FAILED continue } if result != pb.ReportSessionResponse_FAILED { result = pb.ReportSessionResponse_INCOMPLETE } } testRuns := []*pb.TestRun{} for _, entry := range s.tests { if entry.deleted { continue } testRuns = append(testRuns, TestRunProto(entry.test)) } return &pb.ReportSessionResponse{ Result: result, TestRuns: testRuns, } } func (s *sessionImpl) ListTests(in *pb.ListTestsRequest) (*pb.ListTestsResponse, error) { start, err := s.token.GetIndex(in.GetPageToken()) if err != nil { return nil, err } pageSize := in.GetPageSize() if pageSize == 0 { pageSize = 10 } offset := 0 tests := []*pb.Test{} for _, entry := range s.tests[start:] { offset++ if entry.deleted { continue } tests = append(tests, TestProto(entry.test)) if len(tests) >= int(pageSize) { break } } nextToken := "" if start+offset < len(s.tests) { nextToken = s.token.ForIndex(start + offset) } return &pb.ListTestsResponse{Tests: tests, NextPageToken: nextToken}, nil } func (s *sessionImpl) DeleteTest(name string) (*empty.Empty, error) { s.mu.Lock() defer s.mu.Unlock() for n, i := range s.keys { if strings.HasSuffix(name, n) && !s.tests[i].deleted { s.tests[i] = testEntry{test: s.tests[i].test, deleted: true} test := s.tests[i].test if _, ok := test.(UnaryObserver); ok { s.observerRegistry.DeleteUnaryObserver(test.GetName()) } if _, ok := test.(StreamRequestObserver); ok { s.observerRegistry.DeleteStreamRequestObserver(test.GetName()) } if _, ok := test.(StreamResponseObserver); ok { s.observerRegistry.DeleteStreamResponseObserver(test.GetName()) } return &empty.Empty{}, nil } } return nil, status.Errorf( codes.NotFound, "A test with name %s not found.", name) } func (s *sessionImpl) RegisterTests(tests []Test) { for _, test := range tests { i := len(s.tests) s.tests = append(s.tests, testEntry{test: test}) s.keys[test.GetName()] = i if obs, ok := test.(UnaryObserver); ok { s.observerRegistry.RegisterUnaryObserver(obs) } if obs, ok := test.(StreamRequestObserver); ok { s.observerRegistry.RegisterStreamRequestObserver(obs) } if obs, ok := test.(StreamResponseObserver); ok { s.observerRegistry.RegisterStreamResponseObserver(obs) } } } ================================================ FILE: server/session_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package server import ( "context" "testing" pb "github.com/googleapis/gapic-showcase/server/genproto" "google.golang.org/grpc" "google.golang.org/protobuf/proto" ) func TestSessionProto(t *testing.T) { s := NewSession("name", pb.Session_V1_0, ShowcaseObserverRegistry()) if s.GetName() != "name" { t.Errorf("Session.GetName() = %v, want %v", s.GetName(), "name") } if s.GetVersion() != pb.Session_V1_0 { t.Errorf("Session.GetVersion() = %v, want %v", s.GetVersion(), pb.Session_V1_0) } want := &pb.Session{Name: "name", Version: pb.Session_V1_0} got := SessionProto(s) if !proto.Equal(got, want) { t.Errorf("SessionProto() = %v, want %v", got, want) } } type mockTest struct { name string expectation pb.Test_ExpectationLevel blueprints []*pb.Test_Blueprint iType pb.Issue_Type severity pb.Issue_Severity description string Test } func (t *mockTest) GetName() string { return t.name } func (t *mockTest) GetIssue() *pb.Issue { if t.iType == 0 { return nil } return &pb.Issue{ Type: t.iType, Severity: t.severity, Description: t.description, } } func (t *mockTest) GetExpectationLevel() pb.Test_ExpectationLevel { return t.expectation } func (t *mockTest) GetDescription() string { return t.description } func (t *mockTest) GetBlueprints() []*pb.Test_Blueprint { return t.blueprints } // Implements UnaryObserver func (t *mockTest) ObserveUnary( ctx context.Context, req interface{}, resp interface{}, info *grpc.UnaryServerInfo, err error) { } // Implements StreamRequestObserver func (t *mockTest) ObserveStreamRequest( ctx context.Context, req interface{}, info *grpc.StreamServerInfo, err error) { } // Implements StreamResponseObserver func (t *mockTest) ObserveStreamResponse( ctx context.Context, resp interface{}, info *grpc.StreamServerInfo, err error) { } func Test_sessionImpl_TestLifeCycle(t *testing.T) { failed := &mockTest{ name: "failedTest", iType: pb.Issue_INCORRECT_CONFIRMATION, severity: pb.Issue_ERROR, expectation: pb.Test_REQUIRED, description: "This test failed.", } pending := &mockTest{ name: "pendingTest", iType: pb.Issue_PENDING, severity: pb.Issue_ERROR, expectation: pb.Test_RECOMMENDED, description: "This test failed.", } skipped := &mockTest{ name: "skippedTest", expectation: pb.Test_OPTIONAL, iType: pb.Issue_SKIPPED, severity: pb.Issue_ERROR, description: "This test failed.", } passed := &mockTest{ name: "passedTest", expectation: pb.Test_REQUIRED, description: "This test passed.", } // Register tests and ensure they are all listed. session := &sessionImpl{ observerRegistry: ShowcaseObserverRegistry(), token: &tokenGenerator{salt: ""}, keys: map[string]int{}, tests: []testEntry{}, } session.RegisterTests([]Test{failed, pending, skipped, passed}) wantList := &pb.ListTestsResponse{ Tests: []*pb.Test{ TestProto(failed), TestProto(pending), TestProto(skipped), TestProto(passed), }, } got, _ := session.ListTests(&pb.ListTestsRequest{}) if !proto.Equal(got, wantList) { t.Errorf("sessionImpl.ListTests() = %v, want %v", got, wantList) } // Delete tests if _, err := session.DeleteTest("skippedTest"); err != nil { t.Errorf("sessionImpl.DeleteTest() = %v", err) } if _, err := session.DeleteTest("invalidName"); err == nil { t.Error("sessionImpl.DeleteTest() for invalid name wanted err got nil") } // Ensure list of test does not include the deleted tests. wantList = &pb.ListTestsResponse{ Tests: []*pb.Test{ TestProto(failed), TestProto(pending), TestProto(passed), }, } got, _ = session.ListTests(&pb.ListTestsRequest{}) if !proto.Equal(got, wantList) { t.Errorf("sessionImpl.ListTests() = %v, want %v", got, wantList) } // Test pagination wantList = &pb.ListTestsResponse{ Tests: []*pb.Test{ TestProto(failed), TestProto(pending), }, NextPageToken: "Mg==", // Deterministic since we hard coded the page token salt. } got, _ = session.ListTests(&pb.ListTestsRequest{PageSize: 2}) if !proto.Equal(got, wantList) { t.Errorf("sessionImpl.ListTests() = %v, want %v", got, wantList) } // Invalid page token if _, err := session.ListTests(&pb.ListTestsRequest{PageToken: "invalid"}); err == nil { t.Error("sessionImpl.ListTests() with invalid page token got nil.") } } func Test_sessionImpl_GetReport(t *testing.T) { failed := &mockTest{ name: "failedTest", iType: pb.Issue_INCORRECT_CONFIRMATION, severity: pb.Issue_ERROR, description: "This test failed.", } pending := &mockTest{ name: "pendingTest", iType: pb.Issue_PENDING, severity: pb.Issue_ERROR, description: "This test failed.", } skipped := &mockTest{ name: "skippedTest", iType: pb.Issue_SKIPPED, severity: pb.Issue_ERROR, description: "This test failed.", } passed := &mockTest{name: "passedTest"} tests := []struct { name string entries []testEntry want *pb.ReportSessionResponse }{ { "Passes if all tests passed", []testEntry{ testEntry{test: &mockTest{name: "passed 1"}, deleted: false}, testEntry{test: &mockTest{name: "passed 2"}, deleted: false}, testEntry{test: &mockTest{name: "passed 3"}, deleted: false}, }, &pb.ReportSessionResponse{ Result: pb.ReportSessionResponse_PASSED, TestRuns: []*pb.TestRun{ &pb.TestRun{Test: "passed 1"}, &pb.TestRun{Test: "passed 2"}, &pb.TestRun{Test: "passed 3"}, }, }, }, { "Marks as incomplete if there are pending and skipped tests.", []testEntry{ testEntry{test: &mockTest{name: "passed 1"}, deleted: false}, testEntry{test: &mockTest{name: "passed 2"}, deleted: false}, testEntry{test: &mockTest{name: "passed 3"}, deleted: false}, testEntry{test: pending, deleted: false}, testEntry{test: skipped, deleted: false}, }, &pb.ReportSessionResponse{ Result: pb.ReportSessionResponse_INCOMPLETE, TestRuns: []*pb.TestRun{ &pb.TestRun{Test: "passed 1"}, &pb.TestRun{Test: "passed 2"}, &pb.TestRun{Test: "passed 3"}, &pb.TestRun{Test: pending.GetName(), Issue: pending.GetIssue()}, &pb.TestRun{Test: skipped.GetName(), Issue: skipped.GetIssue()}, }, }, }, { "Fails if one tests failed", []testEntry{ testEntry{test: &mockTest{name: "passed 1"}, deleted: false}, testEntry{test: &mockTest{name: "passed 2"}, deleted: false}, testEntry{test: &mockTest{name: "passed 3"}, deleted: false}, testEntry{test: pending, deleted: false}, testEntry{test: skipped, deleted: false}, testEntry{test: failed, deleted: false}, }, &pb.ReportSessionResponse{ Result: pb.ReportSessionResponse_FAILED, TestRuns: []*pb.TestRun{ &pb.TestRun{Test: "passed 1"}, &pb.TestRun{Test: "passed 2"}, &pb.TestRun{Test: "passed 3"}, &pb.TestRun{Test: pending.GetName(), Issue: pending.GetIssue()}, &pb.TestRun{Test: skipped.GetName(), Issue: skipped.GetIssue()}, &pb.TestRun{Test: failed.GetName(), Issue: failed.GetIssue()}, }, }, }, { "Marks as incomplete if there are pending and skipped tests.", []testEntry{ testEntry{test: &mockTest{name: "passed 1"}, deleted: false}, testEntry{test: &mockTest{name: "passed 2"}, deleted: false}, testEntry{test: &mockTest{name: "passed 3"}, deleted: false}, testEntry{test: pending, deleted: false}, testEntry{test: skipped, deleted: false}, }, &pb.ReportSessionResponse{ Result: pb.ReportSessionResponse_INCOMPLETE, TestRuns: []*pb.TestRun{ &pb.TestRun{Test: "passed 1"}, &pb.TestRun{Test: "passed 2"}, &pb.TestRun{Test: "passed 3"}, &pb.TestRun{Test: pending.GetName(), Issue: pending.GetIssue()}, &pb.TestRun{Test: skipped.GetName(), Issue: skipped.GetIssue()}, }, }, }, { "Skips Deleted Tests", []testEntry{ testEntry{test: passed, deleted: false}, testEntry{test: failed, deleted: true}, }, &pb.ReportSessionResponse{ Result: pb.ReportSessionResponse_PASSED, TestRuns: []*pb.TestRun{TestRunProto(passed)}, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { s := &sessionImpl{ tests: tt.entries, } if got := s.GetReport(); !proto.Equal(got, tt.want) { t.Errorf("sessionImpl.GetReport() = %v, want %v", got, tt.want) } }) } } ================================================ FILE: server/spec/showcase_tests.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package spec import ( "github.com/googleapis/gapic-showcase/server" pb "github.com/googleapis/gapic-showcase/server/genproto" v1 "github.com/googleapis/gapic-showcase/server/spec/v1" ) // ShowcaseTests returns the set of tests for a specific version of a session. func ShowcaseTests(sessionName string, version pb.Session_Version) []server.Test { switch version { case pb.Session_V1_0: return v1_0Tests(sessionName) case pb.Session_V1_LATEST: return v1LatestTests(sessionName) default: return []server.Test{} } } func v1_0Tests(sessionName string) []server.Test { return []server.Test{ v1.NewUnaryTest(sessionName), } } func v1LatestTests(sessionName string) []server.Test { return []server.Test{ v1.NewUnaryTest(sessionName), } } ================================================ FILE: server/spec/v1/unary.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package v1 import ( "bytes" "context" "fmt" "sync" "github.com/googleapis/gapic-showcase/server" pb "github.com/googleapis/gapic-showcase/server/genproto" "google.golang.org/grpc" "google.golang.org/protobuf/proto" ) type unaryTest struct { sessionName string mu sync.Mutex responses []interface{} attemptedVerification bool verified bool } func NewUnaryTest(sessionName string) server.Test { return &unaryTest{ sessionName: sessionName, responses: []interface{}{}, } } func (t *unaryTest) GetName() string { return fmt.Sprintf("%s/gapic.v1p0.unary_unary.ok", t.sessionName) } func (t *unaryTest) GetExpectationLevel() pb.Test_ExpectationLevel { return pb.Test_REQUIRED } func (t *unaryTest) GetDescription() string { return "The generator generates a unary-unary RPC, is able to call it," + ", and is able to handle an OK server response." } // TODO: Figure out a good way to represent all unary methods as a bluerprint. func (t *unaryTest) GetBlueprints() []*pb.Test_Blueprint { return []*pb.Test_Blueprint{} } func (t *unaryTest) GetIssue() *pb.Issue { if t.verified { return nil } if t.attemptedVerification { return &pb.Issue{ Type: pb.Issue_INCORRECT_CONFIRMATION, Severity: pb.Issue_ERROR, Description: "An incorrect answer was supplied to verify this test.", } } if len(t.responses) > 0 { return &pb.Issue{ Type: pb.Issue_PENDING, Severity: pb.Issue_ERROR, Description: "This test has not been verified.", } } return &pb.Issue{ Type: pb.Issue_SKIPPED, Severity: pb.Issue_ERROR, Description: "This test has not been started. Make a unary request to start this test.", } } func (t *unaryTest) ObserveUnary( ctx context.Context, req interface{}, resp interface{}, info *grpc.UnaryServerInfo, err error) { t.mu.Lock() defer t.mu.Unlock() if resp != nil { t.responses = append(t.responses, resp) } if info.FullMethod == "/google.showcase.v1beta1.Testing/VerifyTest" { // Only validate for this test. vtReq := req.(*pb.VerifyTestRequest) if vtReq.GetName() != t.GetName() { return } t.attemptedVerification = true for _, r := range t.responses { bs, _ := proto.Marshal(r.(proto.Message)) if bytes.Equal(bs, vtReq.GetAnswer()) { t.verified = true } } } } ================================================ FILE: server/spec/v1/unary_test.go ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package v1 import ( "context" "testing" pb "github.com/googleapis/gapic-showcase/server/genproto" "google.golang.org/grpc" "google.golang.org/protobuf/proto" ) func Test_unaryTest_GetName(t *testing.T) { ut := NewUnaryTest("sessions/-") got := ut.GetName() want := "sessions/-/gapic.v1p0.unary_unary.ok" if got != want { t.Errorf("GetName: got %s, want %s", got, want) } } func Test_unaryTest_GetExpectationLevel(t *testing.T) { ut := NewUnaryTest("sessions/-") got := ut.GetExpectationLevel() want := pb.Test_REQUIRED if got != want { t.Errorf("GetExpectationLevel: got %+v, want %+v", got, want) } } func Test_unaryTest_GetDescription(t *testing.T) { ut := NewUnaryTest("sessions/-") got := ut.GetDescription() if got == "" { t.Errorf("GetDescription: expected non-empty string") } } func Test_unaryTest_GetBlueprints(t *testing.T) { ut := NewUnaryTest("sessions/-") got := ut.GetBlueprints() if len(got) != 0 { t.Errorf("GetBluprints: expected empty list") } } func Test_unaryTest_GetIssue_doesntVerifyForOtherSessions(t *testing.T) { ut := &unaryTest{ sessionName: "sessions/-", responses: []interface{}{}, } other := NewUnaryTest("sessions/1") resp := &pb.EchoResponse{Content: "hello world"} ut.ObserveUnary( context.Background(), nil, resp, serverInfo("/google.showcase.v1beta1.Echo/Echo"), nil) data, _ := proto.Marshal(resp) ut.ObserveUnary( context.Background(), &pb.VerifyTestRequest{ Name: other.GetName(), Answer: data, }, &pb.VerifyTestResponse{}, serverInfo("/google.showcase.v1beta1.Testing/VerifyTest"), nil) got := ut.GetIssue() want := &pb.Issue{ Type: pb.Issue_PENDING, Severity: pb.Issue_ERROR, Description: "This test has not been verified.", } if !proto.Equal(got, want) { t.Errorf("GetIssue: got %+v, want %+v", got, want) } } func Test_unaryTest_GetIssue_verified(t *testing.T) { ut := &unaryTest{ sessionName: "sessions/-", responses: []interface{}{}, } resp := &pb.EchoResponse{Content: "hello world"} ut.ObserveUnary( context.Background(), nil, resp, serverInfo("/google.showcase.v1beta1.Echo/Echo"), nil) data, _ := proto.Marshal(resp) ut.ObserveUnary( context.Background(), &pb.VerifyTestRequest{ Name: ut.GetName(), Answer: data, }, &pb.VerifyTestResponse{}, serverInfo("/google.showcase.v1beta1.Testing/VerifyTest"), nil) got := ut.GetIssue() if got != nil { t.Errorf("GetIssue: got %+v, want nil", got) } } func Test_unaryTest_GetIssue_failedVerification(t *testing.T) { ut := &unaryTest{ sessionName: "sessions/-", responses: []interface{}{}, } ut.ObserveUnary( context.Background(), nil, &pb.EchoResponse{Content: "hello world"}, serverInfo("/google.showcase.v1beta1.Echo/Echo"), nil) data, _ := proto.Marshal(&pb.EchoResponse{Content: "hi world"}) ut.ObserveUnary( context.Background(), &pb.VerifyTestRequest{ Name: ut.GetName(), Answer: data, }, &pb.VerifyTestResponse{}, serverInfo("/google.showcase.v1beta1.Testing/VerifyTest"), nil) got := ut.GetIssue() want := &pb.Issue{ Type: pb.Issue_INCORRECT_CONFIRMATION, Severity: pb.Issue_ERROR, Description: "An incorrect answer was supplied to verify this test.", } if !proto.Equal(got, want) { t.Errorf("GetIssue: got %+v, want %+v", got, want) } } func Test_unaryTest_GetIssue_needsVerification(t *testing.T) { ut := &unaryTest{ sessionName: "sessions/-", responses: []interface{}{}, } ut.ObserveUnary( context.Background(), nil, &pb.EchoResponse{Content: "hello world"}, serverInfo("/google.showcase.v1beta1.Echo/Echo"), nil) got := ut.GetIssue() want := &pb.Issue{ Type: pb.Issue_PENDING, Severity: pb.Issue_ERROR, Description: "This test has not been verified.", } if !proto.Equal(got, want) { t.Errorf("GetIssue: got %+v, want %+v", got, want) } } func Test_unaryTest_GetIssue_skipped(t *testing.T) { ut := &unaryTest{ sessionName: "sessions/-", responses: []interface{}{}, } got := ut.GetIssue() want := &pb.Issue{ Type: pb.Issue_SKIPPED, Severity: pb.Issue_ERROR, Description: "This test has not been started. Make a unary request to start this test.", } if !proto.Equal(got, want) { t.Errorf("GetIssue: got %+v, want %+v", got, want) } } func serverInfo(methodName string) *grpc.UnaryServerInfo { return &grpc.UnaryServerInfo{FullMethod: methodName} } ================================================ FILE: server/test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package server import ( pb "github.com/googleapis/gapic-showcase/server/genproto" ) // Test represents a test case that is run. This interfaces exposes the // properties of the test as well as the observers used to run this test. // // A Test will also implement at least one of UnaryObserver, StreamRequestObserver, // StreamResponseOvserver in order to track requests made to the showcase server. type Test interface { GetName() string GetExpectationLevel() pb.Test_ExpectationLevel GetDescription() string GetBlueprints() []*pb.Test_Blueprint GetIssue() *pb.Issue } // TestProto returns a proto representation of the Test. func TestProto(t Test) *pb.Test { return &pb.Test{ Name: t.GetName(), ExpectationLevel: t.GetExpectationLevel(), Description: t.GetDescription(), Blueprints: t.GetBlueprints(), } } // TestRunProto returns a proto representation of a test run. func TestRunProto(t Test) *pb.TestRun { return &pb.TestRun{ Test: t.GetName(), Issue: t.GetIssue(), } } ================================================ FILE: server/unique_id.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package server import ( "sync/atomic" ) // UniqID provides a numerical id that is guaranteed to be unique. type UniqID struct { i int64 } // Next gets the next unique id. func (u *UniqID) Next() int64 { return atomic.AddInt64(&u.i, 1) - 1 } ================================================ FILE: server/unique_id_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package server import "testing" func TestUniqID_Next(t *testing.T) { u := &UniqID{2} got := u.Next() if got != 2 { t.Errorf("Next: got %d, want %d", got, 2) } } ================================================ FILE: server/waiter.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package server import ( "encoding/base64" "fmt" "time" lropb "cloud.google.com/go/longrunning/autogen/longrunningpb" "github.com/golang/protobuf/ptypes" pb "github.com/googleapis/gapic-showcase/server/genproto" "google.golang.org/protobuf/proto" ) var waiterSingleton Waiter = &waiterImpl{ nowF: time.Now, } // GetWaiterInstance returns the waiter singleton. func GetWaiterInstance() Waiter { return waiterSingleton } // Waiter handles the echo.Wait method for both the LRO service and the echo service. type Waiter interface { Wait(req *pb.WaitRequest) *lropb.Operation } type waiterImpl struct { nowF func() time.Time } func (w *waiterImpl) Wait(req *pb.WaitRequest) *lropb.Operation { endTime := time.Unix(0, 0).UTC() if ttl := req.GetTtl(); ttl != nil { duration, _ := ptypes.Duration(ttl) endTime = w.nowF().Add(duration) } if end := req.GetEndTime(); end != nil { endTime, _ = ptypes.Timestamp(end) } endTimeProto, _ := ptypes.TimestampProto(endTime) req.End = &pb.WaitRequest_EndTime{ EndTime: endTimeProto, } done := w.nowF().After(endTime) reqBytes, _ := proto.Marshal(req) name := fmt.Sprintf( "operations/google.showcase.v1beta1.Echo/Wait/%s", base64.StdEncoding.EncodeToString(reqBytes)) answer := &lropb.Operation{ Name: name, Done: done, } if done && (req.GetError() != nil) { answer.Result = &lropb.Operation_Error{Error: req.GetError()} } if done && (req.GetSuccess() != nil) { resp, _ := ptypes.MarshalAny(req.GetSuccess()) answer.Result = &lropb.Operation_Response{Response: resp} } if !done { meta, _ := ptypes.MarshalAny(&pb.WaitMetadata{EndTime: endTimeProto}) answer.Metadata = meta } return answer } ================================================ FILE: server/waiter_test.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package server import ( "encoding/base64" "strings" "testing" "time" lropb "cloud.google.com/go/longrunning/autogen/longrunningpb" "github.com/golang/protobuf/ptypes" "github.com/golang/protobuf/ptypes/timestamp" pb "github.com/googleapis/gapic-showcase/server/genproto" "google.golang.org/genproto/googleapis/rpc/status" "google.golang.org/protobuf/proto" ) func TestGetWaiterInstance(t *testing.T) { waiter := GetWaiterInstance() if waiter != waiterSingleton { t.Error("GetWaiterInstance: Expected to get waiter singleton.") } } func TestWait_pending(t *testing.T) { now := time.Unix(1, 0) endTime := time.Unix(2, 0) ttl := endTime.Sub(now) nowF := func() time.Time { return time.Unix(1, 0) } endTimeProto := timestampProto(endTime) tests := []*pb.WaitRequest{ &pb.WaitRequest{ End: &pb.WaitRequest_EndTime{ EndTime: endTimeProto, }, }, &pb.WaitRequest{ End: &pb.WaitRequest_Ttl{ Ttl: ptypes.DurationProto(ttl), }, }, } for _, req := range tests { waiter := &waiterImpl{nowF: nowF} op := waiter.Wait(req) if op.Done { t.Errorf("Wait() for %q expectee done=false got done=true", req) } checkName(t, req, op) if op.Metadata == nil { t.Errorf("Wait() for %q expected metadata, got nil", req) } meta := &pb.WaitMetadata{} ptypes.UnmarshalAny(op.Metadata, meta) if !proto.Equal(endTimeProto, meta.EndTime) { t.Errorf( "Wait for %q expected metadata with Endtime=%q, got %q", req, endTimeProto, meta.EndTime) } } } func TestWait_success(t *testing.T) { nowF := func() time.Time { return time.Unix(3, 0) } endTime := timestampProto(time.Unix(2, 0)) success := &pb.WaitResponse{Content: "Hello World!"} req := &pb.WaitRequest{ End: &pb.WaitRequest_EndTime{ EndTime: endTime, }, Response: &pb.WaitRequest_Success{Success: success}, } waiter := &waiterImpl{nowF: nowF} op := waiter.Wait(req) checkName(t, req, op) if !op.Done { t.Errorf("Wait() for %q expected done=true got done=false", req) } if op.Metadata != nil { t.Errorf("Wait() for %q expected nil metadata, got %q", req, op.Metadata) } if op.GetError() != nil { t.Errorf("Wait() expected op.Error=nil, got %q", op.GetError()) } if op.GetResponse() == nil { t.Error("Wait() expected op.Response!=nil") } resp := &pb.WaitResponse{} ptypes.UnmarshalAny(op.GetResponse(), resp) if !proto.Equal(resp, success) { t.Errorf("Wait() expected op.GetResponse()=%q, got %q", success, resp) } } func TestWait_error(t *testing.T) { nowF := func() time.Time { return time.Unix(3, 0) } endTime := timestampProto(time.Unix(2, 0)) expErr := &status.Status{Code: int32(1), Message: "Error!"} req := &pb.WaitRequest{ End: &pb.WaitRequest_EndTime{ EndTime: endTime, }, Response: &pb.WaitRequest_Error{Error: expErr}, } waiter := &waiterImpl{nowF: nowF} op := waiter.Wait(req) checkName(t, req, op) if !op.Done { t.Errorf("Wait() for %q expected done=true got done=false", req) } if op.Metadata != nil { t.Errorf("Wait() for %q expected nil metadata, got %q", req, op.Metadata) } if op.GetResponse() != nil { t.Errorf("Wait() expected op.Response=nil, got %q", op.GetResponse()) } if !proto.Equal(expErr, op.GetError()) { t.Errorf("Wait() expected op.Error=%q, got %q", expErr, op.GetError()) } } func timestampProto(t time.Time) *timestamp.Timestamp { ts, _ := ptypes.TimestampProto(t) return ts } func checkName(t *testing.T, req *pb.WaitRequest, op *lropb.Operation) { if !strings.HasPrefix(op.Name, "operations/google.showcase.v1beta1.Echo/Wait/") { t.Errorf( "Wait() expected op.Name prefex 'operations/google.showcase.v1beta1.Echo/Wait/', got: %s'", op.Name) } nameProto := &pb.WaitRequest{} encodedBytes := strings.TrimPrefix( op.Name, "operations/google.showcase.v1beta1.Echo/Wait/") bytes, _ := base64.StdEncoding.DecodeString(encodedBytes) proto.Unmarshal(bytes, nameProto) if !proto.Equal(nameProto, req) { t.Errorf( "Wait() for %q expected unmarshalled name=%q, got name=%q", req, req, nameProto) } } ================================================ FILE: util/cmd/compile_protos/main.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "github.com/googleapis/gapic-showcase/util" ) // This script regenerates all of the generated source code for the Showcase // API including the generated messages, gRPC services, go gapic clients, // and the generated CLI. This script must be ran from the root directory // of the gapic-showcase repository. // // This script should be used whenever any changes are made to any of // the protos found in schema. // // Usage: go run ./util/cmd/compile_protos/main.go func main() { util.CompileProtos("v1beta1") } ================================================ FILE: util/cmd/protoc-gen-go_rest_server/README.md ================================================ # protoc-gen-go_rest_server This directory contains the `protoc` plugin `go_rest_server` used to generate a Go HTTP server that can translate REST requests and responses to and from protocol buffer messages used by the Showcase gRPC server. ================================================ FILE: util/cmd/protoc-gen-go_rest_server/main.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "google.golang.org/protobuf/compiler/protogen" "github.com/googleapis/gapic-showcase/util/genrest" ) // TODO(vchudnov-g): Continue filling this in. It's a an initial empty // stub at the moment. func main() { // https://pkg.go.dev/google.golang.org/protobuf/compiler/protogen#Options opts := &protogen.Options{} opts.Run(genrest.Generate) } ================================================ FILE: util/cmd/release/main.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "flag" "fmt" "log" "os" "os/exec" "path/filepath" "github.com/googleapis/gapic-showcase/util" ) var version string func init() { flag.StringVar(&version, "version", "", "the version tag [required]") } // This script is run in CI when a new version tag is pushed to main. This script // places the compiled proto descriptor set, a tarball of showcase-protos alongside its // dependencies, and the compiled executables of the gapic-showcase cli tool inside the // directory "dist" // // This script must be run from the root directory of the gapic-showcase repository. // // Usage: go run ./util/cmd/release -version vX.Y.Z func main() { flag.Parse() if version == "" { log.Fatalln("Missing required flag: -version") } if err := os.RemoveAll("tmp"); err != nil { log.Fatalf("Failed to remove the directory 'tmp': %v", err) } tmpProtoPath := filepath.Join("tmp", "protos") if err := os.MkdirAll(tmpProtoPath, 0755); err != nil { log.Fatalf("Failed to make the directory 'tmp': %v", err) } defer os.RemoveAll("tmp") if err := os.RemoveAll("dist"); err != nil { log.Fatalf("Failed to remove the directory 'dist': %v", err) } if err := os.MkdirAll("dist", 0755); err != nil { log.Fatalf("Failed to make the directory 'dist': %v", err) } // Move schema files alongside their dependencies. util.Execute("cp", "-rf", filepath.Join("schema", "google"), tmpProtoPath) apiPath := filepath.Join("schema", "googleapis", "google", "api") tmpAPIPath := filepath.Join(tmpProtoPath, "google", "api") os.MkdirAll(tmpAPIPath, 0755) protoFiles, err := filepath.Glob(filepath.Join(apiPath, "*.proto")) if err != nil { log.Fatal("Failed to find proto files within googleapis/google/api/*") } for _, protoFile := range protoFiles { util.Execute("cp", protoFile, tmpAPIPath) } longrunningPath := filepath.Join("schema", "googleapis", "google", "longrunning") tmpLongrunningPath := filepath.Join(tmpProtoPath, "google", "longrunning") os.MkdirAll(tmpLongrunningPath, 0755) util.Execute("cp", filepath.Join(longrunningPath, "operations.proto"), tmpLongrunningPath) rpcPath := filepath.Join("schema", "googleapis", "google", "rpc") tmpRPCPath := filepath.Join(tmpProtoPath, "google", "rpc") os.MkdirAll(tmpRPCPath, 0755) util.Execute("cp", filepath.Join(rpcPath, "status.proto"), tmpRPCPath) util.Execute("cp", filepath.Join(rpcPath, "error_details.proto"), tmpRPCPath) util.Execute("cp", filepath.Join(rpcPath, "code.proto"), tmpRPCPath) // Copy gRPC ServiceConfig as the source of retry config. retrySrc := filepath.Join("schema", "google", "showcase", "v1beta1", "showcase_grpc_service_config.json") util.Execute("cp", retrySrc, "dist") // Copy compliance suite for easy access by generators. complianceSrc := filepath.Join("schema", "google", "showcase", "v1beta1", "compliance_suite.json") util.Execute("cp", complianceSrc, "dist") // Copy the API Service config for easy access by generators. serviceYamlSrc := filepath.Join("schema", "google", "showcase", "v1beta1", "showcase_v1beta1.yaml") util.Execute("cp", serviceYamlSrc, "dist") // Tar Protos output := filepath.Join("dist", fmt.Sprintf("gapic-showcase-%s-protos.tar.gz", version)) util.Execute("tar", "-zcf", output, "-C", tmpProtoPath, "google") // Check if protoc is installed. if err := exec.Command("protoc", "--version").Run(); err != nil { log.Fatal("Error: 'protoc' is expected to be installed on the path.") } // Compile protos files, err := filepath.Glob(filepath.Join(tmpProtoPath, "google", "showcase", "v1beta1", "*.proto")) if err != nil { log.Fatal("Error: failed to find protos in " + tmpProtoPath) } command := []string{ "protoc", "--experimental_allow_proto3_optional", "--proto_path=" + tmpProtoPath, "--include_imports", "--include_source_info", "-o", filepath.Join("dist", fmt.Sprintf("gapic-showcase-%s.desc", version)), } util.Execute(append(command, files...)...) } ================================================ FILE: util/compile_protos.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package util import ( "fmt" "log" "os" "os/exec" "path/filepath" ) // CompileProtos regenerates all of the generated source code for the Showcase // API including the generated messages, gRPC services, go gapic clients, // and the generated CLI. This must be run from the root directory // of the gapic-showcase repository. func CompileProtos(version string) { // Check if protoc is installed. if err := exec.Command("protoc", "--version").Run(); err != nil { log.Fatal("Error: 'protoc' is expected to be installed on the path.") } // Setup paths pwd, err := os.Getwd() if err != nil { log.Fatalf("Error: unable to get working dir: %+v", err) } outDir, err := os.MkdirTemp(os.TempDir(), "gapic-showcase") if err != nil { log.Fatalf("Error: unable to create a temporary dir: %+v\n", err) } defer os.RemoveAll(outDir) protos := filepath.Join("schema", "google", "showcase", version, "*.proto") files, err := filepath.Glob(protos) if err != nil { log.Fatal("Error: failed to find protos in " + protos) } // Run protoc command := []string{ "protoc", "--experimental_allow_proto3_optional", "--proto_path=schema/googleapis", "--proto_path=schema", "--go_cli_out=" + filepath.Join("cmd", "gapic-showcase"), "--go_cli_opt=root=gapic-showcase", "--go_cli_opt=gapic=github.com/googleapis/gapic-showcase/client", "--go_cli_opt=fmt=false", "--go_gapic_out=" + outDir, "--go_gapic_opt=omit-snippets", "--go_gapic_opt=go-gapic-package=github.com/googleapis/gapic-showcase/client;client", "--go_gapic_opt=grpc-service-config=schema/google/showcase/v1beta1/showcase_grpc_service_config.json", "--go_gapic_opt=api-service-config=schema/google/showcase/v1beta1/showcase_v1beta1.yaml", "--go_gapic_opt=metadata", "--go_gapic_opt=transport=grpc+rest", "--go_rest_server_out=" + filepath.Join("server", "genrest"), "--go_out=plugins=grpc:" + outDir, } Execute(append(command, files...)...) // Copy generated code back into repo. tempClient := filepath.Join(outDir, "github.com", "googleapis", "gapic-showcase", "client") tempServer := filepath.Join(outDir, "github.com", "googleapis", "gapic-showcase", "server") command = []string{ "cp", "-r", tempClient, tempServer, pwd, } Execute(command...) // Fix some generated errors. fixes := []struct { file string fix string }{ { "cmd/gapic-showcase/verify-test.go", "/ByteSliceVar/d", }, { "cmd/gapic-showcase/wait.go", "s/EndEnd_time/EndEndTime/g", }, { "cmd/gapic-showcase/search-blurbs.go", "/if err == iterator.Done {/,/}/d", }, } command = []string{ "sed", "-i.bak", } for _, f := range fixes { Execute(append(command, f.fix, f.file)...) // Remove the backup file. Execute("rm", fmt.Sprintf("%s.bak", f.file)) } // TODO: Remove this once the CLI generator supports mapped pagination responses. Execute("rm", "-f", "cmd/gapic-showcase/paged-expand-legacy.go") // Format generated output Execute("go", "fmt", "./...") } ================================================ FILE: util/execute.go ================================================ // Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package util import ( "log" "os/exec" ) // Execute runs the given strings as a command. func Execute(args ...string) { if output, err := exec.Command(args[0], args[1:]...).CombinedOutput(); err != nil { log.Fatalf("%s", output) } } ================================================ FILE: util/genrest/README.md ================================================ # util/genrest This directory contains the core functionality for the `protoc` plugin `go_rest_server`, which implements a REST endpoint for Showcase services. ================================================ FILE: util/genrest/errorhandling/accumulator.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package errorhandling import ( "fmt" "strings" ) // Accumulator allows storing a series of errors and then concatenating their string representations // into one big error. type Accumulator struct { errors []error } // AccumulateError stores an error to be reported later. func (ea *Accumulator) AccumulateError(err error) { if err == nil { return } ea.errors = append(ea.errors, err) } // Error concatenates the string representations of all stored errors and returns it as a single // error. func (ea *Accumulator) Error() error { if len(ea.errors) == 0 { return nil } errorStrings := make([]string, len(ea.errors)) for idx, err := range ea.errors { errorStrings[idx] = err.Error() } return fmt.Errorf("%s", strings.Join(errorStrings, "\n")) } ================================================ FILE: util/genrest/genserver.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package genrest import ( "path/filepath" "strings" "google.golang.org/protobuf/compiler/protogen" "google.golang.org/protobuf/types/pluginpb" ) func Generate(plugin *protogen.Plugin) error { info := plugin.NewGeneratedFile("showcase-rest-sample-response.txt", "github.com/googleapis/gapic-showcase/server/genrest") // The typecasting below appears to be idiomatic as per // https://github.com/protocolbuffers/protobuf-go/blob/master/cmd/protoc-gen-go/internal_gengo/main.go#L31 plugin.SupportedFeatures = uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL) info.P("Generated via \"google.golang.org/protobuf/compiler/protogen\" via ProtoModel!") info.P("Files:\n", strings.Join(plugin.Request.GetFileToGenerate(), "\n")) protoModel, err := NewProtoModel(plugin) if err != nil { return err } info.P("\nProto Model:") info.P(protoModel.String()) info.P("\n\n") goModel, err := NewGoModel(protoModel) if err != nil { return err } info.P(goModel.String()) view, err := NewView(goModel) if err != nil { return err } for _, source := range view.Files { file := plugin.NewGeneratedFile(source.Name, protogen.GoImportPath(filepath.Join("github.com/googleapis/gapic-showcase/server/genrest", source.Directory))) file.P(source.Contents()) } return nil } ================================================ FILE: util/genrest/gomodel/gomodel.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package gomodel import ( "fmt" "regexp" "sort" "strings" "github.com/googleapis/gapic-showcase/util/genrest/errorhandling" "github.com/googleapis/gapic-showcase/util/genrest/internal/pbinfo" "github.com/googleapis/gapic-showcase/util/genrest/resttools" ) //////////////////////////////////////// // Model // Model is a data model intended to be capture all the information needed for generating Go source // files that provide shims between REST messages on the wire and protocol buffer messages in the // back end, for multiple services. type Model struct { errorhandling.Accumulator Service []*ServiceModel } // Add adds `service` to this Model. func (gm *Model) Add(service *ServiceModel) { gm.Service = append(gm.Service, service) } // String returns a string representation of this Model. func (gm *Model) String() string { shimStrings := make([]string, len(gm.Service)) for idx, shim := range gm.Service { shimStrings[idx] = shim.String() } sep := "----------------------------------------" return fmt.Sprintf("GoModel\n%s\n%s", sep, strings.Join(shimStrings, "\n"+sep+"\n")) } // CheckConsistency checks this Model for consistency, accumulating // any errors found. This means checking that all the HTTP annotations // across all services resolve to distinct paths. func (gm *Model) CheckConsistency() { reBodyField := regexp.MustCompile(resttools.RegexField) allHandlers := []*RESTHandler{} for _, service := range gm.Service { allHandlers = append(allHandlers, service.Handlers...) } for first, firstHandler := range allHandlers { if len(firstHandler.RequestBodyFieldProtoName) > 0 && firstHandler.RequestBodyFieldProtoName != "*" { // The body field name refers to a top-level field. if reBodyField.FindStringIndex(firstHandler.RequestBodyFieldProtoName) == nil { gm.AccumulateError(fmt.Errorf("bad syntax in body field spec %q", firstHandler.RequestBodyFieldProtoName)) } } if _, nestedVariables := firstHandler.PathTemplate.HasVariables(); nestedVariables { gm.AccumulateError(fmt.Errorf("pattern %q specifies nested variables, which are not allowed as per https://cloud.google.com/endpoints/docs/grpc-service-config/reference/rpc/google.api#path-template-syntax", firstHandler.URIPattern)) } for _, secondHandler := range allHandlers[first+1:] { if firstHandler.HTTPMethod != secondHandler.HTTPMethod { continue } fullMatch, ambiguousPattern, err := FindValuesMatching(firstHandler.PathTemplate, secondHandler.PathTemplate) if err != nil { gm.AccumulateError(fmt.Errorf("matching patterns %q and %q (constructed %q): %s", firstHandler, secondHandler, ambiguousPattern, err)) continue } if !fullMatch { continue } gm.AccumulateError(fmt.Errorf("pattern %q matches both\n %s and\n %s\n\n", ambiguousPattern, firstHandler, secondHandler)) } } } //////////////////////////////////////// // ServiceModel // ServiceModel is a data model for generating a REST/proto shim for // a single protocol buffer service. type ServiceModel struct { // the fully qualified protocol buffer type name of this service ProtoPath string // the non-qualified name of this service ShortName string // a map of import paths to import info for each of the service-related Go imports that will // be needed to implement all of the Handlers Imports map[string]*pbinfo.ImportSpec // a list of all the HTTP handlers that will need to be generated, one for each HTTP // annotation for each service RPC Handlers []*RESTHandler } // FullName pretty-prints the short name and proto path. func (service *ServiceModel) FullName() string { return fmt.Sprintf("%q (%s)", service.ShortName, service.ProtoPath) } // String returns a string representation of this ServiceModel. func (service *ServiceModel) String() string { importStrings := make([]string, 0, len(service.Imports)) for path, spec := range service.Imports { importStrings = append(importStrings, fmt.Sprintf("%s: %q %q", spec.Name, spec.Path, path)) } sort.Strings(importStrings) handlerStrings := make([]string, len(service.Handlers)) for idx, handler := range service.Handlers { handlerStrings[idx] = handler.String() } sort.Strings(handlerStrings) return fmt.Sprintf("Shim %s\n Imports:\n %s\n Handlers (%d):\n %s", service.FullName(), strings.Join(importStrings, "\n "), len(handlerStrings), strings.Join(handlerStrings, "\n ")) } // AddHandler adds handler to this ServiceModel. func (service *ServiceModel) AddHandler(handler *RESTHandler) { if service.Handlers == nil { service.Handlers = []*RESTHandler{} } service.Handlers = append(service.Handlers, handler) } // AddImports adds each element of imports to the imports in this ServiceModel. func (service *ServiceModel) AddImports(imports ...*pbinfo.ImportSpec) { if service.Imports == nil { service.Imports = make(map[string]*pbinfo.ImportSpec, len(imports)) } for _, importSpec := range imports { service.Imports[importSpec.Path] = importSpec } } //////////////////////////////////////// // RESTHandler // RESTHandler contains the information needed to generate a single HTTP handler. type RESTHandler struct { //// Transcoding information HTTPMethod string URIPattern string // as it appears in the HTTP annotation PathTemplate PathTemplate // parsed version of URIPattern StreamingServer bool // whether this method uses server-side streaming StreamingClient bool // whether this method uses client-side streaming //// Go types GoMethod string RequestType string RequestTypePackage string RequestTypeImport string RequestVariable string RequestBodyFieldSpec BodyFieldSpec RequestBodyFieldProtoName string RequestBodyFieldName string RequestBodyFieldType string RequestBodyFieldVariable string RequestBodyFieldPackage string ResponseType string ResponseTypePackage string ResponseVariable string } // String returns a string representation of this RESTHandler. func (rh *RESTHandler) String() string { return fmt.Sprintf("%8s %50s func %s(%s %s.%s) (%s %s.%s) {}\n%s\n", rh.HTTPMethod, rh.URIPattern, rh.GoMethod, rh.RequestVariable, rh.RequestTypePackage, rh.RequestType, rh.ResponseVariable, rh.ResponseTypePackage, rh.ResponseType, rh.PathTemplate) } // BodyFieldSpec encodes what request field was annotated as the REST request body. type BodyFieldSpec int const ( BodyFieldNone BodyFieldSpec = iota // no RPC field specified in the REST body BodyFieldSingle // a single top-level RPC request field was specified in the REST body BodyFieldAll // the whole RPC request message is encoded in the REST body ) ================================================ FILE: util/genrest/gomodel/pathtemplate.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package gomodel import ( "fmt" "strings" ) //////////////////////////////////////// // PathTemplate // PathTemplate contains a sequence of parsed Segment to represent an HTTP binding. type PathTemplate []*Segment // NewPathTemplate parses `pattern` to return the corresponding PathTemplate. func NewPathTemplate(pattern string) (PathTemplate, error) { return ParseTemplate(pattern) } // Flatten returns a flattened PathTemplate, which contains no recursively nested // PathTemplate. Effectively, this removes any Segment with `Kind==Variable`. func (pt PathTemplate) Flatten() PathTemplate { flat := PathTemplate{} for _, seg := range pt { flat = append(flat, seg.Flatten()...) } return flat } // HasVariables returns two booleans depending on whether `pt` has top-level and nested // (lower-level) variables. func (pt PathTemplate) HasVariables() (topVar, nestedVar bool) { for _, segment := range pt { if segment.Kind == Variable { segTopVar, segNestedVar := segment.Subsegments.HasVariables() nestedVar = nestedVar || segTopVar || segNestedVar topVar = true } } return topVar, nestedVar } // ListVariables returns a list of all the variables (proto field names) found in `pt`, func (pt PathTemplate) ListVariables() []string { varNames := []string{} for _, segment := range pt { if segment.Kind == Variable { varNames = append(varNames, segment.Value) varNames = append(varNames, segment.Subsegments.ListVariables()...) } } return varNames } // asGoLiteral returns a Go-syntax representation of this PathTemplate. This is useful for // constructing and debugging tests. func (pt PathTemplate) asGoLiteral() string { parts := make([]string, len(pt)) for idx, segment := range pt { parts[idx] = "&" + segment.asGoLiteral() } return fmt.Sprintf("PathTemplate{ %s }", strings.Join(parts, ", ")) } //////////////////////////////////////// // Segment // Segment is a single structural element in an HTTP binding type Segment struct { Kind SegmentKind // the semantics of Value depend on Kind: // Kind==Variable: field path // Kind==Literal: literal value // Kind==SingleValue: "*" // Kind== MultipleValue: "**" Value string Subsegments PathTemplate } // String returns a string representation of this Segment. func (seg *Segment) String() string { switch seg.Kind { case Literal: return fmt.Sprintf("%q", seg.Value) case SingleValue, MultipleValue: return seg.Value case Variable: subsegments := "!!ERROR: no subsegments" if len(seg.Subsegments) > 0 { subsegments = fmt.Sprintf("%s", seg.Subsegments) } return fmt.Sprintf("{%s = %s}", seg.Value, subsegments) } // Out of range: print as much info as possible return fmt.Sprintf("{%s(%d) %q %s}", seg.Kind, seg.Kind, seg.Value, seg.Subsegments) } // Flatten returns a flattened PathTemplate containing either this Segment or its flattened // sub-segments. Effectively, this removes any Segment with `Kind==Variable`. func (seg *Segment) Flatten() PathTemplate { switch seg.Kind { case Variable: return seg.Subsegments.Flatten() default: return PathTemplate{seg} } } // asGoLiteral returns a Go-syntax representation of this Segment. This is useful for // constructing and debugging tests. func (seg *Segment) asGoLiteral() string { subsegments := "nil" if seg.Subsegments != nil { subsegments = seg.Subsegments.asGoLiteral() } return fmt.Sprintf("Segment{ %s, %q, %s }", seg.Kind.asGoLiteral(), seg.Value, subsegments) } //////////////////////////////////////// // SegmentKind // SegmentKind describes a type of Segment. type SegmentKind int const ( KindUndefined SegmentKind = iota Literal Variable SingleValue MultipleValue KindEnd ) // Valid returns true iff this SegmentKind value is valid. func (sk SegmentKind) Valid() bool { return sk > KindUndefined && sk < KindEnd } // String returns a string representation of this SegmentKind. func (sk SegmentKind) String() string { var names = []string{"(UNDEFINED)", "LITERAL", "VARIABLE", "SINGLEVAL", "MULTIVAL", "(END)"} if !sk.Valid() { return "INVALID" } return names[sk] } // asGoLiteral returns a Go-syntax representation of this SegmentKind. This is useful for // constructing and debugging tests. func (sk SegmentKind) asGoLiteral() string { var names = []string{"KindUndefined", "Literal", "Variable", "SingleValue", "MultipleValue", "KindEnd"} return names[sk] } ================================================ FILE: util/genrest/gomodel/pathtemplate_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package gomodel import ( "testing" ) func TestHasVariables(t *testing.T) { for idx, testCase := range []struct { stringTemplate string expectVars bool expectNestedVars bool }{ { stringTemplate: "/aa/cc/ee/*/gg/ii/jj/*/kk/**:ll", expectVars: false, expectNestedVars: false, }, { stringTemplate: "/aa/{bb}/cc/{dd=ee/*/gg}/{hh=ii/jj/*/kk/**}:ll", expectVars: true, expectNestedVars: false, }, { stringTemplate: "/aa/{bb}/cc/{dd=ee/*/gg/{hh=ii/jj/*/kk}/**}:ll", expectVars: true, expectNestedVars: true, }, } { parsed, err := ParseTemplate(testCase.stringTemplate) if err != nil { t.Errorf("testCase = %d: ParseTemplate failed: %s \n Test case input: %v", idx, err, testCase) } hasVars, hasNestedVars := parsed.HasVariables() if got, want := hasVars, testCase.expectVars; got != want { t.Errorf("testCase = %d: HasVars() failed checking variables: got %v, want %v", idx, got, want) } if got, want := hasNestedVars, testCase.expectNestedVars; got != want { t.Errorf("testCase = %d: HasVars() failed checking nested variables: got %v, want %v", idx, got, want) } } } func TestListVariables(t *testing.T) { for idx, testCase := range []struct { stringTemplate string expectVars []string }{ { stringTemplate: "/aa/cc/ee/*/gg/ii/jj/*/kk/**:ll", expectVars: nil, }, { stringTemplate: "/aa/{bb}/cc/{dd=ee/*/gg}/{hh=ii/jj/*/kk/**}:ll", expectVars: []string{"bb", "dd", "hh"}, }, { stringTemplate: "/aa/{bb}/cc/{dd=ee/*/gg/{hh=ii/jj/*/kk}/**}:ll", expectVars: []string{"bb", "dd", "hh"}, }, } { parsed, err := ParseTemplate(testCase.stringTemplate) if err != nil { t.Errorf("testCase = %d: ParseTemplate failed: %s \n Test case input: %v", idx, err, testCase) } varList := parsed.ListVariables() if got, want := len(varList), len(testCase.expectVars); got != want { t.Errorf("testCase = %d: ListVars() unexpected number of variables returned: got %v, want %v: returned elements: %v", idx, got, want, varList) continue } for varIdx, got := range varList { if want := testCase.expectVars[varIdx]; got != want { t.Errorf("testCase = %d: ListVars() variable %d unexpected: got %v, want %v", idx, varIdx, got, want) } } } } ================================================ FILE: util/genrest/gomodel/pathtemplatematch.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package gomodel import ( "fmt" "strings" ) // FindValuesMatching returns the the longest string prefix that matches the templates `first` and // `second`, and a bool indicating whether this prefix if a full match for both expressions. func FindValuesMatching(first, second PathTemplate) (fullMatch bool, longestMatch string, err error) { one := &traverser{template: first.Flatten()} two := &traverser{template: second.Flatten()} values := make([]string, max(one.Len(), two.Len())) defer func() { longestMatch = strings.Join(values, "") }() for !(one.Done() || two.Done()) { matches, matching := segmentsMatch(one, two) if !matches { return false, "", nil } values = append(values, matching) } // A Segment of kind MultipleValue can match many other segments, so it doesn't auto-advance // in all scenarios. one.ConsumeIfKind(MultipleValue) two.ConsumeIfKind(MultipleValue) if one.ConsumedAll() && two.ConsumedAll() { return true, "", nil } if !(one.ConsumedAll() || two.ConsumedAll()) { return false, "", fmt.Errorf("did not traverse either full pattern one: %v two: %v", *one, *two) } return false, "", nil } // segmentsMatch is the main work function for FindValuesMatching. It returns true iff one and two // can be matched, as well as the matching string between `one` and `two`, which can be a literal, a // wildcard "*", or be empty (for some matches in progress). This typically advanced the indices of // `one` and/or `two`. func segmentsMatch(one, two *traverser) (bool, string) { seg1 := one.Segment() seg2 := two.Segment() if seg1.Kind != Literal && seg2.Kind == Literal { return segmentsMatch(two, one) } // If at least one of the arguments is a Literal, the first one is. if seg1.Kind == Literal { switch seg2.Kind { case Literal: if seg1.Value != seg2.Value { return false, "" } one.Inc() two.Inc() return true, seg1.Value case SingleValue: one.Inc() two.Inc() return true, seg1.Value case MultipleValue: // special case for the verb, which is the only thing that can come after a // multiple value. Advance past the multiple value and reprocess. if seg1.Value == ":" { two.Inc() return true, "" } one.Inc() // no increment for two return true, seg1.Value default: one.SetDone() two.SetDone() return false, "[ERROR]" } } // If we reach here, neither argument was a Literal if seg1.Kind != SingleValue && seg2.Kind == SingleValue { return segmentsMatch(two, one) } // If at least one of the arguments is a SingleValue, the first one is. if seg1.Kind == SingleValue { switch seg2.Kind { case SingleValue: one.Inc() two.Inc() return true, "*" case MultipleValue: one.Inc() // no increment for two return true, "*" default: one.SetDone() two.SetDone() return false, "[ERROR]" } } // If we reach here, neither argument was a Literal or SingleValue if seg1.Kind == MultipleValue { if seg2.Kind != MultipleValue { one.SetDone() two.SetDone() return false, fmt.Sprintf("[ERROR: unknown SegmentKind %d]", seg2.Kind) } // The following should mark both as done, since there shouldn't be any subsequent segments for either one.Inc() two.Inc() return true, "**" } // We should never reach here (note that flattened PathTemplates contain no segments with Kind==Variable) one.SetDone() two.SetDone() return false, fmt.Sprintf("[ERROR: unknown SegmentKind %d]", seg1.Kind) } func max(x, y int) int { if x > y { return x } return y } //////////////////////////////////////// // traverser // traverser is a helper struct for FindValuesMatching. It keeps track of which segment of a // PathTemplate we're current processing, and whether the traversal has been determined to be // finished. type traverser struct { // template being traversed template PathTemplate // index into the segment of template being examined idx int // whether we're done traversing this template done bool } // Segment returns the current Segment in the traversal. func (tr *traverser) Segment() *Segment { return tr.template[tr.idx] } // Len returns the length of the template. func (tr *traverser) Len() int { return len(tr.template) } // Inc advances to the next Segment in the template. func (tr *traverser) Inc() { tr.idx++ if tr.ConsumedAll() { tr.SetDone() } } // ConsumeIfKind calls Inc() iff the current Segment's `Kind` equals `kind`. func (tr *traverser) ConsumeIfKind(kind SegmentKind) { if !tr.Done() && tr.template[tr.idx].Kind == kind { tr.Inc() } } // ConsumedAll returns true iff we have traversed all the segments of the template. func (tr *traverser) ConsumedAll() bool { return tr.idx >= len(tr.template) } // Done returns true iff this traversal has been marked finished. func (tr *traverser) Done() bool { return tr.done } // SetDone returns marks this traversal finished. func (tr *traverser) SetDone() { tr.done = true } ================================================ FILE: util/genrest/gomodel/pathtemplatematch_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package gomodel import ( "testing" ) func TestFindValuesMatching(t *testing.T) { for idx, testCase := range []struct { pattern1, pattern2, longestMatch string fullMatch bool }{ // Literal, Literal {"/zz/yy", "/zz/yy", "/zz/yy", true}, {"/zz", "/zz/yy", "/zz", false}, {"/zz/yy:xx", "/zz/yy:xx", "/zz/yy:xx", true}, {"/zz:xx", "/zz/yy:xx", "/zz", false}, {"/zz/yy:xx", "/zz/yy", "/zz/yy", false}, {"/zz", "/zz/yy:xx", "/zz", false}, // Literal, SingleValue {"/zz/yy/{ww}/vv", "/zz/yy/xx/vv", "/zz/yy/xx/vv", true}, {"/zz/yy/xx/vv", "/zz/yy/{ww}/vv", "/zz/yy/xx/vv", true}, {"/zz/yy/{ww}/vv:uu", "/zz/yy/xx/vv:uu", "/zz/yy/xx/vv:uu", true}, {"/zz/yy/{ww}:uu", "/zz/yy/xx:uu", "/zz/yy/xx:uu", true}, {"/zz/yy/{xx=ww/*}/vv:uu", "/zz/yy/ww/tt/vv:uu", "/zz/yy/ww/tt/vv:uu", true}, {"/zz/yy/{xx=ww/*}:uu", "/zz/yy/ww/tt:uu", "/zz/yy/ww/tt:uu", true}, // Literal, MultipleValue {"/zz/yy/xx/ww/vv", "/zz/{pp=yy/xx/**}", "/zz/yy/xx/ww/vv", true}, {"/zz/{pp=yy/xx/**}", "/zz/yy/xx/ww/vv", "/zz/yy/xx/ww/vv", true}, {"/zz/{pp=yy/xx/**}:rr", "/zz/yy/xx/ww/vv:rr", "/zz/yy/xx/ww/vv:rr", true}, {"/zz/{pp=yy/xx/**}:rr", "/zz/yy/xx/ww/vv", "/zz/yy/xx/ww/vv", false}, {"/zz/{pp=yy/xx/**}", "/zz/yy/xx/ww/vv:rr", "/zz/yy/xx/ww/vv", false}, {"/zz/{pp=yy/xx/**}:rr", "/zz/yy/xx/ww/vv:ss", "/zz/yy/xx/ww/vv:", false}, // SingleValue, SingleValue {"/zz/yy/{xx=ww/*}/vv", "/zz/yy/{tt=ww/*}/vv", "/zz/yy/ww/*/vv", true}, {"/zz/yy/{xx=ww/*}:uu", "/zz/yy/{tt=ww/*}:uu", "/zz/yy/ww/*:uu", true}, {"/zz/yy/{xx=ww/*}/vv/{ss=rr/*/pp}", "/zz/yy/ww/{xx}/vv/{oo=rr/*/pp}", "/zz/yy/ww/*/vv/rr/*/pp", true}, // SingleValue, MultipleValue {"/zz/yy/{xx=ww/**}", "/zz/yy/ww/{vv}/uu", "/zz/yy/ww/*/uu", true}, {"/zz/yy/{xx=ww/**}:tt", "/zz/yy/ww/{vv}/uu:tt", "/zz/yy/ww/*/uu:tt", true}, {"/zz/yy/{xx=ww/**}", "/zz/yy/{vv=ww/*}/uu", "/zz/yy/ww/*/uu", true}, {"/zz/yy/{xx=ww/**}:tt", "/zz/yy/{vv=ww/*}/uu:tt", "/zz/yy/ww/*/uu:tt", true}, {"/zz/yy/{xx=ww/**}:tt", "/zz/yy/ww/{vv}/uu", "/zz/yy/ww/*/uu", false}, {"/zz/yy/{xx=ww/**}", "/zz/yy/ww/{vv}/uu:tt", "/zz/yy/ww/*/uu", false}, // MultipleValue, MultipleValue {"/zz/yy/{xx=ww/**}", "/zz/yy/{vv=ww/**}", "/zz/yy/ww/**", true}, {"/zz/yy/{xx=ww/**}:ss", "/zz/yy/{vv=ww/**}:ss", "/zz/yy/ww/**:ss", true}, {"/zz/yy/{xx=ww/**}", "/zz/yy/{vv=ww/**}:ss", "/zz/yy/ww/**", false}, {"/zz/yy/{xx=ww/**}:ss", "/zz/yy/{vv=ww/**}", "/zz/yy/ww/**", false}, // Mix } { template1, err := NewPathTemplate(testCase.pattern1) if err != nil { t.Errorf("testCase %2d: unexpected error constructing template1: %s:\n Test case input: %v", idx, err, testCase) } template2, err := NewPathTemplate(testCase.pattern2) if err != nil { t.Errorf("testCase %2d: unexpected error constructing template2: %s:\n Test case input: %v", idx, err, testCase) } fullMatch, longestMatch, err := FindValuesMatching(template1, template2) if got, want := longestMatch, testCase.longestMatch; got != want { t.Errorf("testCase %2d: longestMatch failed: got %q want %q:\n Test case input: %v\n err = %v", idx, got, want, testCase, err) } if got, want := fullMatch, testCase.fullMatch; got != want { t.Errorf("testCase %2d: fullMatch failed: got %v want %v:\n Test case input: %v\n err = %v", idx, got, want, testCase, err) } _ = err } } ================================================ FILE: util/genrest/gomodel/pathtemplateparser.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package gomodel import ( "fmt" "regexp" "strings" "github.com/googleapis/gapic-showcase/util/genrest/resttools" ) // ParseTemplate parses a path template string according to // https://cloud.google.com/endpoints/docs/grpc-service-config/reference/rpc/google.api#path-template-syntax // // Grammar: // // Template = "/" Segments [ Verb ] ; // Segments = Segment { "/" Segment } ; // Segment = "*" | "**" | LITERAL | Variable ; // Variable = "{" FieldPath [ "=" Segments ] "}" ; // FieldPath = IDENT { "." IDENT } ; // Verb = ":" LITERAL ; // // with "**" matching the last part of the path template string except for the Verb. func ParseTemplate(template string) (parsed PathTemplate, err error) { return NewParser(template).parse() } //////////////////////////////////////// // Parser // Parser contains the context for parsing a path template string. type Parser struct { source *Source // whether we've encountered the last "**" segment haveLastSegment bool // regexes regex map[string]*regexp.Regexp } // NewParser returns a Parser ready to process template. func NewParser(template string) *Parser { return &Parser{ source: &Source{ str: template, }, regex: make(map[string]*regexp.Regexp), } } // parse returns the parsed PathTemplate. func (parser *Parser) parse() (pt PathTemplate, err error) { defer func() { if err != nil { indent := strings.Repeat(" ", parser.source.idx) err = fmt.Errorf("parsing template, position %d: %s haveLastSegment: %v\n %q\n %s^\n -> %s", parser.source.idx, err, parser.haveLastSegment, parser.source.str, indent, pt) } }() if !parser.source.ConsumeIf('/') { return nil, fmt.Errorf("template does not start with slash") } pt, err = parser.parseSegments() pt = append(PathTemplate{slashSegment}, pt...) if err != nil { return pt, err } if parser.source.ConsumeIf(':') { verb, err := parser.parseLiteral() if err != nil { return pt, fmt.Errorf("could not parse verb") } pt = append(pt, &Segment{Kind: Literal, Value: ":"}, verb) } if parser.source.InRange() { return pt, fmt.Errorf("unexpected character") } return pt, nil } // parseSegments parses a sequence of slash-delimited segments. func (parser *Parser) parseSegments() (PathTemplate, error) { pt := PathTemplate{} proceed := true for proceed { if parser.haveLastSegment { return pt, fmt.Errorf("already encountered last segment") } segment, err := parser.parseOneSegment() pt = append(pt, segment) if err != nil { return pt, err } if proceed = parser.source.ConsumeIf('/'); proceed { pt = append(pt, slashSegment) } } return pt, nil } // segmentParser is a function type that parses a specific type of segment. It returns both nil // error and nil Segment if the parser does not apply to the next stream of characters in the // source. It returns a non-nil Segment if the characters from the point at which called matched the // segment type. type segmentParser func() (*Segment, error) // parseOneSegment parses exactly one segment of the recognized types. func (parser *Parser) parseOneSegment() (*Segment, error) { orderedParsers := []segmentParser{parser.parseVariable, parser.parseLiteral, parser.parseMultipleValue, parser.parseSingleValue} for _, parse := range orderedParsers { seg, err := parse() if err != nil || seg != nil { return seg, err } } return nil, fmt.Errorf("could not parse path segment") } // parseSingleValue parses a segment with `Kind==SingleValue` (i.e. a single-segment placeholder), returning nil if not possible. func (parser *Parser) parseSingleValue() (*Segment, error) { re := parser.GetRegexp(`^\*`) return parser.parseToSegment(re, SingleValue), nil } // parseMultipleValue parses a segment with `Kind==MultipleValue` (i.e. a multiple-segment placeholder), returning nil if not possible. func (parser *Parser) parseMultipleValue() (*Segment, error) { re := parser.GetRegexp(`^\*\*`) seg := parser.parseToSegment(re, MultipleValue) if seg != nil { parser.haveLastSegment = true } return seg, nil } // parseLiteral parses a segment with `Kind==Literal`, returning nil if not possible. func (parser *Parser) parseLiteral() (*Segment, error) { re := parser.GetRegexp(resttools.RegexLiteral) return parser.parseToSegment(re, Literal), nil } // parseToSegment is a helper function that creates a Segment of the specified kind if the next // characters in the parse stream match the expression re. func (parser *Parser) parseToSegment(re *regexp.Regexp, kind SegmentKind) *Segment { match := parser.source.ConsumeRegex(re) if len(match) == 0 { return nil } return &Segment{Kind: kind, Value: match} } // parseFieldPath parses a field path, which is the "field" in a "{field=segments}" declaration. func (parser *Parser) parseFieldPath() string { re := parser.GetRegexp(resttools.RegexField) return parser.source.ConsumeRegex(re) } // parseVariable parses a variable spec, which is a sequence of field names, segments, and/or // placeholders, all enclosed by matching braces "{}". func (parser *Parser) parseVariable() (*Segment, error) { if !parser.source.ConsumeIf('{') { return nil, nil } fieldPath := parser.parseFieldPath() if len(fieldPath) == 0 { return nil, fmt.Errorf("no field path specified") } segment := &Segment{ Kind: Variable, Value: fieldPath, } if parser.source.ConsumeIf('=') { var err error segment.Subsegments, err = parser.parseSegments() if err != nil { return segment, err } if len(segment.Subsegments) == 0 { return segment, fmt.Errorf("no path segments specified for field path %q", fieldPath) } } else { segment.Subsegments = PathTemplate{&Segment{Kind: SingleValue}} } if !parser.source.ConsumeIf('}') { return segment, fmt.Errorf("expected end-of-variable '}', got %q", parser.source.Str()) } return segment, nil } // GetRegexp returns the memoized compiled regex corresponding to expr. This allows defining regexes // where they're used while still compiling them only once. func (parser *Parser) GetRegexp(expr string) *regexp.Regexp { compiled := parser.regex[expr] if compiled == nil { compiled = regexp.MustCompile(expr) parser.regex[expr] = compiled } return compiled } var slashSegment = &Segment{Kind: Literal, Value: "/"} //////////////////////////////////////// // Source // Source contains the context for the source string being parsed. Note that Source and its methods // are NOT rune-safe and operate on each individual character, not each rune. type Source struct { str string idx int } // Consume advances source by num characters. func (src *Source) Consume(num int) { src.idx += num } // Str returns the unparsed part of the original source string. func (src *Source) Str() string { if !src.InRange() { return "" } return src.str[src.idx:] } // InRange returns true iff there are more characters that can be read from the source string. func (src *Source) InRange() bool { return len(src.str) > src.idx } // IsNextByte returns true iff the next character to be read is `query`. func (src *Source) IsNextByte(query byte) bool { return src.InRange() && src.str[src.idx] == query } // ConsumeIf advances the source and returns true iff the next character matches `query`. func (src *Source) ConsumeIf(query byte) bool { matches := src.IsNextByte(query) if matches { src.Consume(1) } return matches } // ConsumeMatch consumes and returns characters matching re, and returns them. func (src *Source) ConsumeRegex(re *regexp.Regexp) string { match := re.FindString(src.Str()) src.Consume(len(match)) return match } ================================================ FILE: util/genrest/gomodel/pathtemplateparser_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package gomodel import ( "reflect" "testing" ) func TestParseTemplate(t *testing.T) { for idx, testCase := range []struct { stringTemplate string expectSuccess bool expectParsedTemplate PathTemplate }{ // general segment parsing errors {"/aa/", false, nil}, {"//bb", false, nil}, {"/@aa/bb", false, nil}, {"/a@/", false, nil}, {"/aa/:bb", false, nil}, {"/aa/:bb:cc", false, nil}, {"/aa/:bb/cc/dd:ee", false, nil}, // parse() errors {"aa/bb", false, nil}, {"/aa/bb:@dd", false, nil}, {"/aa/bb:cc@", false, nil}, {"/aa/bb:d/d", false, nil}, // parseVariable() errors {"/aa/{}", false, nil}, {"/aa/{bb=}", false, nil}, {"/aa/{bb=/cc}", false, nil}, {"/aa/{bb=cc/}", false, nil}, {"/aa/{bb=cc/@}", false, nil}, {"/aa/{@bb=cc}", false, nil}, // successful cases { stringTemplate: "/aa/{bb}/cc/{dd=ee/*/gg/{hh=ii/jj/*/kk}/**}:ll", expectSuccess: true, expectParsedTemplate: PathTemplate{ &Segment{Literal, "/", nil}, &Segment{Literal, "aa", nil}, &Segment{Literal, "/", nil}, &Segment{Variable, "bb", PathTemplate{ &Segment{SingleValue, "", nil}, }}, &Segment{Literal, "/", nil}, &Segment{Literal, "cc", nil}, &Segment{Literal, "/", nil}, &Segment{Variable, "dd", PathTemplate{ &Segment{Literal, "ee", nil}, &Segment{Literal, "/", nil}, &Segment{SingleValue, "*", nil}, &Segment{Literal, "/", nil}, &Segment{Literal, "gg", nil}, &Segment{Literal, "/", nil}, &Segment{Variable, "hh", PathTemplate{ &Segment{Literal, "ii", nil}, &Segment{Literal, "/", nil}, &Segment{Literal, "jj", nil}, &Segment{Literal, "/", nil}, &Segment{SingleValue, "*", nil}, &Segment{Literal, "/", nil}, &Segment{Literal, "kk", nil}}, }, &Segment{Literal, "/", nil}, &Segment{MultipleValue, "**", nil}}}, &Segment{Literal, ":", nil}, &Segment{Literal, "ll", nil}}, }, { stringTemplate: "/aa/{bb}/cc/{dd=ee/*/gg/{hh=ii/jj/*/kk}/**}", expectSuccess: true, expectParsedTemplate: PathTemplate{ &Segment{Literal, "/", nil}, &Segment{Literal, "aa", nil}, &Segment{Literal, "/", nil}, &Segment{Variable, "bb", PathTemplate{ &Segment{SingleValue, "", nil}}, }, &Segment{Literal, "/", nil}, &Segment{Literal, "cc", nil}, &Segment{Literal, "/", nil}, &Segment{Variable, "dd", PathTemplate{ &Segment{Literal, "ee", nil}, &Segment{Literal, "/", nil}, &Segment{SingleValue, "*", nil}, &Segment{Literal, "/", nil}, &Segment{Literal, "gg", nil}, &Segment{Literal, "/", nil}, &Segment{Variable, "hh", PathTemplate{ &Segment{Literal, "ii", nil}, &Segment{Literal, "/", nil}, &Segment{Literal, "jj", nil}, &Segment{Literal, "/", nil}, &Segment{SingleValue, "*", nil}, &Segment{Literal, "/", nil}, &Segment{Literal, "kk", nil}}, }, &Segment{Literal, "/", nil}, &Segment{MultipleValue, "**", nil}, }}, }, }, } { parsed, err := ParseTemplate(testCase.stringTemplate) if got, want := err == nil, testCase.expectSuccess; got != want { t.Errorf("testCase = %d: ParseTemplate failed: want success: %v; got error: %s \n Test case input: %v", idx, want, err, testCase) } if !testCase.expectSuccess { continue } if got, want := parsed, testCase.expectParsedTemplate; !reflect.DeepEqual(got, want) { t.Errorf("parsed template incorrect:\n got: %s\n want: %s", got.asGoLiteral(), want.asGoLiteral()) } _ = parsed } } ================================================ FILE: util/genrest/gomodelcreator.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package genrest import ( "fmt" "github.com/golang/protobuf/protoc-gen-go/descriptor" "github.com/googleapis/gapic-showcase/util/genrest/gomodel" "github.com/googleapis/gapic-showcase/util/genrest/internal/pbinfo" "github.com/googleapis/gapic-showcase/util/genrest/protomodel" "github.com/iancoleman/strcase" "google.golang.org/protobuf/types/descriptorpb" ) // NewGoModel creates a new goModel.Model from the given protomodel.Model. It essentially extracts // and organizes the data needed to later generate Go source files. func NewGoModel(protoModel *protomodel.Model) (*gomodel.Model, error) { goModel := &gomodel.Model{ Service: make([]*gomodel.ServiceModel, 0, len(protoModel.Services)), } protoInfo := protoModel.ProtoInfo for _, service := range protoModel.Services { serviceModel := &gomodel.ServiceModel{ProtoPath: service.TypeName, ShortName: service.Name} goModel.Add(serviceModel) for _, binding := range service.RESTBindings { protoMethodType := binding.ProtoMethod protoMethodDesc, ok := protoInfo.Type[protoMethodType].(*descriptorpb.MethodDescriptorProto) if !ok { goModel.AccumulateError(fmt.Errorf("could not get descriptor for %q: %#x", protoMethodType, protoInfo.Type[protoMethodType])) continue } inProtoType := protoInfo.Type[*protoMethodDesc.InputType] inGoType, inImports, err := protoInfo.NameSpec(inProtoType) goModel.AccumulateError(err) var ( requestBodyFieldType string requestBodyFieldName string bodyFieldImports pbinfo.ImportSpec bodyFieldSpec gomodel.BodyFieldSpec ) if binding.BodyField == "*" { bodyFieldSpec = gomodel.BodyFieldAll } else if len(binding.BodyField) > 0 { bodyFieldSpec = gomodel.BodyFieldSingle var bodyFieldDesc *descriptorpb.FieldDescriptorProto inProtoTypeDescriptor, ok := inProtoType.(*descriptor.DescriptorProto) if !ok { goModel.AccumulateError(fmt.Errorf("could not type assert inProtoType %v to *descriptor.DescriptorProto", inProtoType)) } // Intentional: the following indirectly enforces that the field // specified is top-level (is not a dotted path), as periods are not // allowed in field names. for _, fd := range inProtoTypeDescriptor.GetField() { if fd.GetName() == binding.BodyField { bodyFieldDesc = fd break } } if bodyFieldDesc == nil { goModel.AccumulateError(fmt.Errorf("could not find body field %q in %q", binding.BodyField, inProtoType.GetName())) } bodyFieldTypeDesc, ok := protoInfo.Type[bodyFieldDesc.GetTypeName()] if !ok { goModel.AccumulateError(fmt.Errorf("could not read protoInfo[%q]", inProtoType)) } requestBodyFieldType, bodyFieldImports, err = protoInfo.NameSpec(bodyFieldTypeDesc) // TODO: test for HTTP body encoding a single field whose names is different than its type // TODO: Test for HTTP body encoding a single field that is a scalar, not a message requestBodyFieldName = strcase.ToCamel(bodyFieldDesc.GetName()) goModel.AccumulateError(err) } outProtoType := protoInfo.Type[*protoMethodDesc.OutputType] outGoType, outImports, err := protoInfo.NameSpec(outProtoType) goModel.AccumulateError(err) pathTemplate, err := gomodel.NewPathTemplate(binding.RESTPattern.Pattern) goModel.AccumulateError(err) // TODO: Check that each field path in the handler path template refers to // an actual field in the request. We can use the functionality in // resttools.PopulateOneField() (after some refactoring) to do this, // starting from FieldDescriptor.ProtoReflect(). This will allow us to error // at build time rather than at server run time. restHandler := &gomodel.RESTHandler{ HTTPMethod: binding.RESTPattern.HTTPMethod, URIPattern: binding.RESTPattern.Pattern, PathTemplate: pathTemplate, StreamingServer: protoMethodDesc.GetServerStreaming(), StreamingClient: protoMethodDesc.GetClientStreaming(), GoMethod: protoMethodDesc.GetName(), RequestType: inGoType, RequestTypePackage: inImports.Name, RequestTypeImport: inImports.Path, RequestVariable: "request", RequestBodyFieldSpec: bodyFieldSpec, RequestBodyFieldProtoName: binding.BodyField, RequestBodyFieldName: requestBodyFieldName, RequestBodyFieldType: requestBodyFieldType, RequestBodyFieldVariable: "bodyField", RequestBodyFieldPackage: bodyFieldImports.Name, ResponseType: outGoType, ResponseTypePackage: outImports.Name, ResponseVariable: "response", } serviceModel.AddImports(&inImports, &outImports) serviceModel.AddHandler(restHandler) } } goModel.CheckConsistency() return goModel, goModel.Error() } ================================================ FILE: util/genrest/goview/goview.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package goview import ( "fmt" "strings" ) // View contains a list of files to be output. type View struct { Files []*SourceFile } // New returns a new, empty View. func New(capacity int) *View { return &View{Files: make([]*SourceFile, 0, capacity)} } // Append appends file to this View. func (view *View) Append(file *SourceFile) *SourceFile { view.Files = append(view.Files, file) return file } // SourceFile contains a single file to be output, including both its content and location. type SourceFile struct { Directory string Name string // without any directory components source *Source } // NewFile creates an empty SourceFile with the specified Directory and Name. func NewFile(directory, name string) *SourceFile { return &SourceFile{ Directory: directory, Name: name, source: NewSource(), } } // Contents returns the stringified contents this SourceFile. func (sf *SourceFile) Contents() string { return sf.source.Contents() } // Append appends the lines in Source to the lines in SourceFile. func (sf *SourceFile) Append(source *Source) { sf.source.lines = append(sf.source.lines, source.lines...) } // P appends a printf-formatted line to SourcerFile. func (sf *SourceFile) P(format string, args ...interface{}) { sf.source.P(format, args...) } // Source stores a list of lines, typically a continuous section of source code that forms a part of // (or the entirety of) a whole source file. type Source struct { lines []string // a list of lines } // NewSource returns a new Source func NewSource() *Source { return &Source{lines: []string{}} } // Contents returns the stringified contents this SourceFile. func (source *Source) Contents() string { return strings.Join(source.lines, "\n") + "\n" } // P writes a new line of content to this SourceFile. The arguments are treated exactly as in // fmt.Printf. Note that there is an implicit in the SourceFile contents "\n" after each call to // P(). func (source *Source) P(format string, args ...interface{}) { source.lines = append(source.lines, fmt.Sprintf(format, args...)) } ================================================ FILE: util/genrest/goviewcreator.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package genrest import ( "fmt" "sort" "strings" "time" "github.com/googleapis/gapic-showcase/util/genrest/gomodel" "github.com/googleapis/gapic-showcase/util/genrest/goview" "github.com/googleapis/gapic-showcase/util/genrest/resttools" ) // NewView creates a a new goview.View (a series of files to be output) from a gomodel.Model. The // current approach is to generate one file per service, with that file containing all the service's // RPCs. An additional file `genrest.go` is also created to register all these handlers with a // gorilla/mux dispatcher. func NewView(model *gomodel.Model) (*goview.View, error) { // TODO: Assert that all services live in the same proto package, which is currently the case and we currently assume. namer := NewNamer() numServices := len(model.Service) view := goview.New(numServices) registered := []*registeredHandler{} for idxService, service := range model.Service { file := view.Append(goview.NewFile("", strings.ToLower(service.ShortName)+".go")) file.P("%s", license) file.P("// DO NOT EDIT. This is an auto-generated file containing the REST handlers") file.P("// for service #%d: %s.\n", idxService, service.FullName()) file.P("") file.P("package genrest") file.P("") fileImports := map[string]string{ "context": "", "net/http": "", "github.com/googleapis/gapic-showcase/util/genrest/resttools": "", "github.com/gorilla/mux": "gmux", } // TODO: Properly deal with import strings. They may need to be taken out of the gomodel // Accumulate source code for each method corresponding to an RPC, as well as the imports the code requires. methodSources := []*goview.Source{} // Accumulate helper methods required by RPC methods, taking care to not duplicate them. helperSources := sourceMap{} for _, handler := range service.Handlers { source := goview.NewSource() methodSources = append(methodSources, source) excludedQueryParams := []string{} handlerName := namer.Get("Handle" + handler.GoMethod) pathMatch, allURLVariables, err := matchingPath(handler.PathTemplate) if err != nil { return nil, fmt.Errorf("processing %q: %s", handler.PathTemplate, err) } registered = append(registered, ®isteredHandler{pathMatch, handlerName, handler.HTTPMethod}) source.P("") source.P("// %s translates REST requests/responses on the wire to internal proto messages for %s", handlerName, handler.GoMethod) source.P("// Generated for HTTP binding pattern: %s %q", handler.HTTPMethod, handler.URIPattern) source.P("func (backend *RESTBackend) %s(w http.ResponseWriter, r *http.Request) {", handlerName) if handler.StreamingClient { source.P(` backend.Error(w, http.StatusNotImplemented, "client-streaming methods not implemented yet (request matched '%s': %%q)", r.URL)`, handler.URIPattern) source.P("}") continue } source.P(` urlPathParams := gmux.Vars(r)`) source.P(" numUrlPathParams := len(urlPathParams)") source.P("") // TODO: Consider factoring out code shared among handlers into a single // place, so that handlers only provide the relevant values (e.g. expected // number of path variables, etc.) source.P(` backend.StdLog.Printf("Received %%s request matching '%s': %%q", r.Method, r.URL)`, handler.URIPattern) source.P(` backend.StdLog.Printf(" urlPathParams (expect %d, have %%d): %%q", numUrlPathParams, urlPathParams)`, len(allURLVariables)) source.P(` backend.StdLog.Printf(" urlRequestHeaders:\n%%s", resttools.PrettyPrintHeaders(r, " "))`) source.P("") source.P(" resttools.IncludeRequestHeadersInResponse(w, r)") source.P("") source.P(" if numUrlPathParams!=%d {", len(allURLVariables)) source.P(` backend.Error(w, http.StatusBadRequest, "found unexpected number of URL variables: expected %d, have %%d: %%#v", numUrlPathParams, urlPathParams)`, len(allURLVariables)) source.P(" return") source.P(" }") source.P("") source.P(" systemParameters, queryParams, err := resttools.GetSystemParameters(r)") source.P(" if err != nil {") source.P(` backend.Error(w, http.StatusBadRequest, "error in query string: %%s", err)`) source.P(" return") source.P(" }") // TODO: Fail with an error if numeric enums are not set, as GAPICs should // always request numeric enums. Make this change once we know that it won't // break existing usages of Showcase for generators not yet implementing the // feature. source.P("") source.P(" %s := &%s.%s{}", handler.RequestVariable, handler.RequestTypePackage, handler.RequestType) fileImports[handler.RequestTypeImport] = handler.RequestTypePackage switch handler.RequestBodyFieldSpec { case gomodel.BodyFieldAll: fileImports["bytes"] = "" fileImports["io"] = "" source.P(" // Intentional: Field values in the URL path override those set in the body.") source.P(" var jsonReader bytes.Buffer") source.P(" bodyReader := io.TeeReader(r.Body, &jsonReader)") source.P(" rBytes, err := io.ReadAll(bodyReader)") source.P(" if err != nil {") source.P(` backend.Error(w, http.StatusBadRequest, "error reading body content: %%s", err)`) source.P(" return") source.P(" }") source.P("") source.P(" if err := resttools.FromJSON().Unmarshal(rBytes, %s); err != nil {", handler.RequestVariable) source.P(` backend.Error(w, http.StatusBadRequest, "error reading body params '*': %%s", err)`) source.P(" return") source.P(" }") source.P("") source.P(" if err := resttools.CheckRequestFormat(&jsonReader, r, %s.ProtoReflect()); err != nil {", handler.RequestVariable) source.P(` backend.Error(w, http.StatusBadRequest, "REST request failed format check: %%s", err)`) source.P(" return") source.P(" }") source.P("") source.P(" if len(queryParams) > 0 {") source.P(` backend.Error(w, http.StatusBadRequest, "encountered unexpected query params: %%v", queryParams)`) source.P(" return") source.P(" }") case gomodel.BodyFieldSingle: fileImports["bytes"] = "" fileImports["io"] = "" // TODO: Ensure this works when the specified field is a scalar. We // may need to use PopulateFields from the generated code in that // case. source.P(" // Intentional: Field values in the URL path override those set in the body.") source.P(" var %s %s.%s", handler.RequestBodyFieldVariable, handler.RequestBodyFieldPackage, handler.RequestBodyFieldType) source.P(" var jsonReader bytes.Buffer") source.P(" bodyReader := io.TeeReader(r.Body, &jsonReader)") source.P(" rBytes, err := io.ReadAll(bodyReader)") source.P(" if err != nil {") source.P(` backend.Error(w, http.StatusBadRequest, "error reading body content: %%s", err)`) source.P(" return") source.P(" }") source.P("") source.P(" if err := resttools.FromJSON().Unmarshal(rBytes, &%s); err != nil {", handler.RequestBodyFieldVariable) source.P(` backend.Error(w, http.StatusBadRequest, "error reading body into request field '%s': %%s", err)`, handler.RequestBodyFieldProtoName) source.P(" return") source.P(" }") source.P("") source.P(" if err := resttools.CheckRequestFormat(&jsonReader, r, %s.ProtoReflect()); err != nil {", handler.RequestVariable) source.P(` backend.Error(w, http.StatusBadRequest, "REST request failed format check: %%s", err)`) source.P(" return") source.P(" }") source.P(" %s.%s = &%s", handler.RequestVariable, handler.RequestBodyFieldName, handler.RequestBodyFieldVariable) source.P("") excludedQueryParams = append(excludedQueryParams, handler.RequestBodyFieldProtoName) default: source.P(" if err := resttools.CheckRequestFormat(nil, r, %s.ProtoReflect()); err != nil {", handler.RequestVariable) source.P(` backend.Error(w, http.StatusBadRequest, "REST request failed format check: %%s", err)`) source.P(" return") source.P(" }") } source.P(" if err := resttools.PopulateSingularFields(%s, urlPathParams); err != nil {", handler.RequestVariable) source.P(` backend.Error(w, http.StatusBadRequest, "error reading URL path params: %%s", err)`) source.P(" return") source.P(" }") source.P("") excludedQueryParams = append(excludedQueryParams, handler.PathTemplate.ListVariables()...) if handler.RequestBodyFieldSpec != gomodel.BodyFieldAll { source.P(" // TODO: Decide whether query-param value or URL-path value takes precedence when a field appears in both") if len(excludedQueryParams) > 0 { source.P(" excludedQueryParams := %#v", excludedQueryParams) source.P(" if duplicates := resttools.KeysMatchPath(queryParams, excludedQueryParams); len(duplicates) > 0 {") source.P(` backend.Error(w, http.StatusBadRequest, "(QueryParamsInvalidFieldError) found keys that should not appear in query params: %%v", duplicates)`) source.P(" return") source.P(" }") } source.P(" if err := resttools.PopulateFields(%s, queryParams); err != nil {", handler.RequestVariable) source.P(` backend.Error(w, http.StatusBadRequest, "error reading query params: %%s", err)`) source.P(" return") source.P(" }") source.P("") } source.P("") source.P(" marshaler := resttools.ToJSON()") source.P(" marshaler.UseEnumNumbers = systemParameters.EnumEncodingAsInt") source.P(" requestJSON, _ := marshaler.Marshal(%s)", handler.RequestVariable) source.P(` backend.StdLog.Printf(" request: %%s", requestJSON)`) source.P("") if handler.StreamingServer { streamerType := constructServerStreamer(service, handler, fileImports, helperSources) source.P(` serverStreamer, err := resttools.NewServerStreamer(w, resttools.ServerStreamingChunkSize)`) source.P(` if err != nil {`) source.P(` backend.Error(w,http.StatusInternalServerError, "server error: could not construct server streamer: %%s", err.Error())`) source.P(` return`) source.P(` }`) source.P(` defer serverStreamer.End()`) source.P(` streamer := &%s{serverStreamer}`, streamerType) source.P(" if err := backend.%sServer.%s(%s, streamer); err != nil {", service.ShortName, handler.GoMethod, handler.RequestVariable) source.P(" backend.ReportGRPCError(w, err)") source.P(" }") } else { // regular unary call // TODO: In the future, we may want to redirect all REST-endpoint requests to the gRPC endpoint so that the gRPC-registered observers get invoked. source.P(" ctx := context.WithValue(r.Context(), resttools.BindingURIKey, \"%s\")", handler.URIPattern) source.P(" %s, err := backend.%sServer.%s(ctx, %s)", handler.ResponseVariable, service.ShortName, handler.GoMethod, handler.RequestVariable) source.P(" if err != nil {") source.P(" backend.ReportGRPCError(w, err)") source.P(" return") source.P(" }") source.P("") source.P(" json, err := marshaler.Marshal(%s)", handler.ResponseVariable) source.P(" if err != nil {") source.P(` backend.Error(w, http.StatusInternalServerError, "error json-encoding response: %%s", err.Error())`) source.P(" return") source.P(" }") source.P("") source.P(" w.Write(json)") } source.P("}\n") } // Use the accumulated method source code and import data to write out the actual file. file.P("import (") for path, name := range fileImports { file.P(" %s %q", name, path) } file.P(")") file.P("") for _, method := range methodSources { file.Append(method) } for _, k := range helperSources.sortedKeys() { file.Append(helperSources[k]) } } file := view.Append(goview.NewFile("", "genrest.go")) file.P("%s", license) file.P("// DO NOT EDIT. This is an auto-generated file registering the REST handlers.") file.P("// for the various Showcase services.") file.P("") file.P("package genrest") file.P("") file.P("import (") file.P(` "fmt"`) file.P(` "net/http"`) file.P("") file.P(` "github.com/googleapis/gapic-showcase/server/services"`) file.P(` "github.com/googleapis/gapic-showcase/util/genrest/resttools"`) file.P("") file.P(` gmux "github.com/gorilla/mux"`) file.P(` "google.golang.org/grpc/status"`) file.P(")") file.P("") file.P("") file.P("type RESTBackend services.Backend") file.P("") file.P("") file.P(`func RegisterHandlers(router *gmux.Router, backend *services.Backend) {`) file.P(" rest := (*RESTBackend)(backend)") // TODO: Support path-encoded '\n' in strings (%0A), which currently don't work. Probably the way to do this is to add // file.P(" router.UseEncodedPath()") // here, and to explicitly path decode in resttools.PopulateSingularFields. We should also // add '\n' to the "ExtremeValues" ComplianceGroup in compliance_suite.json. for _, handler := range registered { file.P(` router.HandleFunc(%q, rest.%s).Methods(%q)`, handler.pattern, handler.function, handler.verb) // Java's PATCH requests are sent as POST requests with a `X-HTTP-Method-Override` header if handler.verb == "PATCH" { // HeadersRegexp is used to match for both POST Http Verb and the Header value file.P(` router.HandleFunc(%q, rest.%s).HeadersRegexp("X-HTTP-Method-Override", "^PATCH$").Methods("POST")`, handler.pattern, handler.function) } } file.P(` router.PathPrefix("/").HandlerFunc(rest.catchAllHandler)`) file.P(`}`) file.P("") file.P("func (backend *RESTBackend) catchAllHandler(w http.ResponseWriter, r *http.Request) {") file.P(` backend.Error(w, http.StatusBadRequest, "unrecognized request: %%s %%q", r.Method, r.URL)`) file.P("}") file.P("") file.P("func (backend *RESTBackend) Error(w http.ResponseWriter, httpStatus int, format string, args ...interface{}) {") file.P(" message := fmt.Sprintf(format, args...)") file.P(" backend.ErrLog.Print(message)") file.P(" resttools.ErrorResponse(w, httpStatus, resttools.NoCodeGRPC, message)") file.P("}") file.P("func (backend *RESTBackend) ReportGRPCError(w http.ResponseWriter, err error) {") file.P(" st, ok := status.FromError(err)") file.P(" if !ok {") file.P(` backend.Error(w, http.StatusInternalServerError, "server error: %%s", err.Error())`) // TODO(https://github.com/googleapis/gapic-showcase/issues/1575): Report internal errors as standard gRPC errors file.P(" return") file.P(" }") file.P("") file.P(" backend.ErrLog.Print(st.Message())") file.P(" resttools.ErrorResponse(w, resttools.NoCodeHTTP, st.Code(), st.Message(), st.Details()...)") file.P("}") return view, nil } func constructServerStreamer(service *gomodel.ServiceModel, handler *gomodel.RESTHandler, fileImports map[string]string, helperSources sourceMap) (streamerType string) { streamerType = fmt.Sprintf("%s_%sServer", service.ShortName, handler.GoMethod) streamerInterface := fmt.Sprintf("%s.%s_%sServer", handler.RequestTypePackage, service.ShortName, handler.GoMethod) streamerElement := fmt.Sprintf("*%s.%s", handler.ResponseTypePackage, handler.ResponseType) helper := goview.NewSource() helperSources[streamerType] = helper helper.P(`// %s implements %s to provide server-side streaming over REST, returning all the`, streamerType, streamerInterface) helper.P(`// individual responses as part of a long JSON list.`) helper.P(`type %s struct{`, streamerType) helper.P(` *resttools.ServerStreamer`) helper.P(`}`) helper.P(``) helper.P(` // Send accumulates a response to be fetched later as part of response list returned over REST.`) helper.P(`func (streamer *%s) Send(response %s) error {`, streamerType, streamerElement) helper.P(` return streamer.ServerStreamer.Send(response)`) helper.P(`}`) return streamerType } // registeredHandler pairs a URL path pattern with the name of the associated handler type registeredHandler struct { pattern string // URL pattern function string // handler function verb string // HTTP verb } // matchingPath returns the URL path for a gorilla/mux HTTP handler corresponding to the given // `template`, as well as a list of all the template variables (identified by their proto field // path, which are also their key values in the variable map that will be returned by gorilla/mux.Vars()). func matchingPath(template gomodel.PathTemplate) (string, []string, error) { return extractPath(template, false) } // extractPath is a one-level recursive helper function that does the actual work of // matchingPath(). `insideVariable` denotes whether we're processing segments already inside a // top-level handler path variable, since nested variables are not allowed. The list of variable // keys (which will be provided by gorilla/mux, and which also match their proto field path in the // request object) is returned together with the actual gorilla/mux matching path. func extractPath(template gomodel.PathTemplate, insideVariable bool) (string, []string, error) { var allVariables []string parts := make([]string, len(template)) for idx, seg := range template { var part string switch seg.Kind { case gomodel.Literal: part = seg.Value case gomodel.SingleValue: part = resttools.RegexURLPathSingleSegmentValue case gomodel.MultipleValue: part = resttools.RegexURLPathMultipleSegmentValue case gomodel.Variable: if insideVariable { return "", nil, fmt.Errorf("nested variables are disallowed: https://cloud.google.com/endpoints/docs/grpc-service-config/reference/rpc/google.api#path-template-syntax") } subParts, _, err := extractPath(seg.Subsegments, true) if err != nil { return "", nil, err } // Here we convert the proto-cased (snake-cased) field path to be JSON-cased // (lower-camel-cased) so that we can keep the resttools.Populate*Field*() // functions simple, only dealing with JSON-cased field names, part = fmt.Sprintf("{%s:%s}", resttools.ToDottedLowerCamel(seg.Value), subParts) allVariables = append(allVariables, seg.Value) } parts[idx] = part } return strings.Join(parts, ""), allVariables, nil } //////////////////////////////////////// // Namer // Namer keeps track of a series of symbol names being used in order to disambiguate new names. type Namer struct { registered map[string]int } // NewNamer returns a new Namer. func NewNamer() *Namer { return &Namer{registered: make(map[string]int)} } // Get registers and returns a non-previously registered name that is as close to newName as // possible. Disambiguation, if needed, is accomplished by adding a numeric suffix. func (namer *Namer) Get(newName string) string { for { numSeen := namer.registered[newName] namer.registered[newName] = numSeen + 1 if numSeen == 0 { return newName } newName = fmt.Sprintf("%s_%d", newName, numSeen) // run through the loop again to ensure the new name hasn't been previously registered either. } } // sourceMap implements a method to return the keys in sorted order. type sourceMap map[string]*goview.Source // sortedKeys returns a slice containing all the keys in sm, sorted. func (sm sourceMap) sortedKeys() []string { keys := []string{} for k := range sm { keys = append(keys, k) } sort.Strings(keys) return keys } var license string func init() { license = fmt.Sprintf(`// Copyright %d Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. `, time.Now().Year()) } ================================================ FILE: util/genrest/goviewcreator_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package genrest import ( "os" "reflect" "testing" "github.com/google/go-cmp/cmp" "github.com/googleapis/gapic-showcase/util/genrest/gomodel" ) func TestMatchingPath(t *testing.T) { for idx, testCase := range []struct { template string expectError bool expectMatch string expectVars []string }{ { template: "/aa/{bb}/cc/{dd=ee/*/gg/{hh=ii/jj/*/kk}/**}:ll", expectError: true, }, { template: "/aa/{bb}/cc/{dd=ee/*/gg}/{hh=ii/jj/*/kk/**}", expectMatch: "/aa/{bb:[^:]+}/cc/{dd:ee/[^:]+/gg}/{hh:ii/jj/[^:]+/kk/[^:]+}", expectVars: []string{"bb", "dd", "hh"}, }, } { pathTemplate, err := gomodel.ParseTemplate(testCase.template) if err != nil { t.Errorf("testCase %2d: unexpected error constructing template: %s:\n Test case input: %v", idx, err, testCase) continue } path, allVars, err := matchingPath(pathTemplate) if got, want := (err != nil), testCase.expectError; got != want { t.Errorf("testCase %2d: matchingPath error:\n got: %q\n want: %v", idx, err, want) } if err != nil { continue } if got, want := path, testCase.expectMatch; got != want { t.Errorf("testCase %2d: matchingPath path:\n got: %q\n want: %q", idx, got, want) } if got, want := allVars, testCase.expectVars; !reflect.DeepEqual(got, want) { t.Errorf("testCase %2d: matchingPath path:\n got: %#v\n want: %#v", idx, got, want) } } } func TestNamer(t *testing.T) { namer := NewNamer() for idx, testCase := range []struct { requested string expected string }{ // Order matters, since we're testing disambiguation with previously seen items. {"rainbow", "rainbow"}, {"rainbow", "rainbow_1"}, {"rainbow", "rainbow_2"}, {"rainbow_1", "rainbow_1_1"}, {"rainbow_1", "rainbow_1_2"}, {"rainbow_1", "rainbow_1_3"}, {"rainbow_2", "rainbow_2_1"}, {"sun_1", "sun_1"}, {"sun_1", "sun_1_1"}, } { if got, want := namer.Get(testCase.requested), testCase.expected; got != want { t.Errorf("testCase %2d: got %q, want %q", idx, got, want) } } } func TestConstructStreamingServer(t *testing.T) { fileImports := map[string]string{} helperSources := sourceMap{} constructServerStreamer(&gomodel.ServiceModel{ShortName: "Catalog"}, &gomodel.RESTHandler{ RequestTypePackage: "catalogpb", ResponseTypePackage: "responsepb", GoMethod: "StreamAuthors", ResponseType: "AuthorEntry", }, fileImports, helperSources) if got, want := len(helperSources), 1; got != want { t.Errorf("unexpected length of helperSources: got %d, want %d", got, want) } constructServerStreamer(&gomodel.ServiceModel{ShortName: "Catalog"}, &gomodel.RESTHandler{ RequestTypePackage: "catalogpb", ResponseTypePackage: "responsepb", GoMethod: "StreamTitles", ResponseType: "TitleEntry", }, fileImports, helperSources) if got, want := len(helperSources), 2; got != want { t.Errorf("unexpected length of helperSources: got %d, want %d", got, want) } constructServerStreamer(&gomodel.ServiceModel{ShortName: "Media"}, &gomodel.RESTHandler{ RequestTypePackage: "mediapb", ResponseTypePackage: "responsepb", GoMethod: "StreamAudio", ResponseType: "AudioEntry", }, fileImports, helperSources) if got, want := len(helperSources), 3; got != want { t.Errorf("unexpected length of helperSources: got %d, want %d", got, want) } constructServerStreamer(&gomodel.ServiceModel{ShortName: "Media"}, &gomodel.RESTHandler{ RequestTypePackage: "mediapb", ResponseTypePackage: "responsepb", GoMethod: "StreamVideo", ResponseType: "VideoEntry", }, fileImports, helperSources) if got, want := len(helperSources), 4; got != want { t.Errorf("unexpected length of helperSources: got %d, want %d", got, want) } actualSources := "" for _, key := range helperSources.sortedKeys() { actualSources += helperSources[key].Contents() + "\n" } expectedSources, err := os.ReadFile("testdata/TestConstructServerStreamer.go.baseline") if err != nil { t.Fatalf("could not load file: %s", err) } if got, want := actualSources, string(expectedSources); got != want { t.Errorf("unexpected helper sources:\n = got: ===\n%s\n= want: ===\n%s\n= diff ===\n%s", got, want, cmp.Diff(got, want)) } } ================================================ FILE: util/genrest/internal/pbinfo/pbinfo.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package pbinfo provides convenience types for looking up protobuf elements. package pbinfo // This file was copied and adapted from gapic-generator-go:internal/pbinfo/pbinfo.go // // TODO: Consider making that file non-internal, back-porting the few modifications here, and then // depending on that, to prevent code duplication. import ( "fmt" "strings" "unicode" "github.com/golang/protobuf/protoc-gen-go/descriptor" "google.golang.org/protobuf/proto" ) // ProtoType represents a type in protobuf descriptors. // It is an interface implemented by DescriptorProto and EnumDescriptorProto. type ProtoType interface { proto.Message GetName() string } // Info provides lookup tables for various protobuf properties. // For example, we can look up a type by name without iterating the entire // descriptor. type Info struct { // Maps services and messages to the file containing them, // so we can figure out the import. ParentFile map[proto.Message]*descriptor.FileDescriptorProto // NOTE(pongad): ParentElement and sub-types are only used in samples. // They are added in the shared package because they share a lot of similarities // with things that are already here. Maybe revisit this in the future? // Maps a protobuf element to the enclosing scope. // If enum E is defined in message M which is in file F, // ParentElement[E]=M, ParentElement[M]=nil, and ParentFile[M]=F ParentElement map[ProtoType]ProtoType // Maps type names to their messages. Type map[string]ProtoType // Maps service names to their descriptors. Serv map[string]*descriptor.ServiceDescriptorProto } // Of creates Info from given protobuf files. func Of(files []*descriptor.FileDescriptorProto) Info { info := Info{ ParentFile: map[proto.Message]*descriptor.FileDescriptorProto{}, ParentElement: map[ProtoType]ProtoType{}, Type: map[string]ProtoType{}, Serv: map[string]*descriptor.ServiceDescriptorProto{}, } for _, f := range files { // ParentFile for _, m := range f.MessageType { info.ParentFile[m] = f } for _, e := range f.EnumType { info.ParentFile[e] = f } for _, s := range f.Service { info.ParentFile[s] = f for _, m := range s.Method { info.ParentFile[m] = f info.ParentElement[m] = s } } // Type for _, m := range f.MessageType { // In descriptors, putting the dot in front means the name is fully-qualified. addMessage(info.Type, info.ParentElement, "."+f.GetPackage(), m, nil) } for _, e := range f.EnumType { info.Type["."+f.GetPackage()+"."+e.GetName()] = e } // Serv for _, s := range f.Service { fullyQualifiedName := fmt.Sprintf(".%s.%s", f.GetPackage(), s.GetName()) info.Serv[fullyQualifiedName] = s // The following was not in the original file in gapic-generator-go. for _, m := range s.Method { info.Type[fmt.Sprintf("%s.%s", fullyQualifiedName, m.GetName())] = m } } } return info } func addMessage(typMap map[string]ProtoType, parentMap map[ProtoType]ProtoType, prefix string, msg, parentMsg *descriptor.DescriptorProto) { fullName := prefix + "." + msg.GetName() typMap[fullName] = msg if parentMsg != nil { parentMap[msg] = parentMsg } for _, subMsg := range msg.NestedType { addMessage(typMap, parentMap, fullName, subMsg, msg) } for _, subEnum := range msg.EnumType { typMap[fullName+"."+subEnum.GetName()] = subEnum parentMap[subEnum] = msg } for _, field := range msg.GetField() { parentMap[field] = msg } } type ImportSpec struct { Name, Path string } // NameSpec reports the name and ImportSpec of e. // // The reported name is the same with how protoc-gen-go refers to e. // E.g. if type B is nested under A, then the name of type B is "A_B". func (in *Info) NameSpec(e ProtoType) (string, ImportSpec, error) { topLvl := e var nameParts []string for e2 := e; e2 != nil; e2 = in.ParentElement[e2] { topLvl = e2 nameParts = append(nameParts, e2.GetName()) } for i, l := 0, len(nameParts); i < l/2; i++ { nameParts[i], nameParts[l-i-1] = nameParts[l-i-1], nameParts[i] } name := strings.Join(nameParts, "_") var eTxt interface{} = e if et, ok := eTxt.(interface{ GetName() string }); ok { eTxt = et.GetName() } fdesc := in.ParentFile[topLvl] if fdesc == nil { return "", ImportSpec{}, fmt.Errorf("can't determine import path for %v; can't find parent file", eTxt) } pkg := fdesc.GetOptions().GetGoPackage() if pkg == "" { return "", ImportSpec{}, fmt.Errorf("can't determine import path for %v, file %q missing `option go_package`", eTxt, fdesc.GetName()) } if p := strings.IndexByte(pkg, ';'); p >= 0 { return name, ImportSpec{Path: pkg[:p], Name: pkg[p+1:] + "pb"}, nil } for { p := strings.LastIndexByte(pkg, '/') if p < 0 { return name, ImportSpec{Path: pkg, Name: pkg + "pb"}, nil } elem := pkg[p+1:] if len(elem) >= 2 && elem[0] == 'v' && elem[1] >= '0' && elem[1] <= '9' { // It's a version number; skip so we get a more meaningful name pkg = pkg[:p] continue } return name, ImportSpec{Path: pkg, Name: elem + "pb"}, nil } } // ImportSpec reports the ImportSpec for package containing protobuf element e. // Deprecated: Use NameSpec instead. func (in *Info) ImportSpec(e ProtoType) (ImportSpec, error) { _, imp, err := in.NameSpec(e) return imp, err } // ReduceServName removes redundant components from the service name. // For example, FooServiceV2 -> Foo. // The returned name is used as part of longer names, like FooClient. // If the package name and the service name is the same, // ReduceServName returns empty string, so we get foo.Client instead of foo.FooClient. func ReduceServName(svc, pkg string) string { // remove trailing version if p := strings.LastIndexByte(svc, 'V'); p >= 0 { isVer := true for _, r := range svc[p+1:] { if !unicode.IsDigit(r) { isVer = false break } } if isVer { svc = svc[:p] } } svc = strings.TrimSuffix(svc, "Service") if strings.EqualFold(svc, pkg) { svc = "" } // This is a special case for IAM and should not be // extended to support any new API name containing // an acronym. // // In order to avoid a breaking change for IAM // clients, we must keep consistent identifier casing. if strings.Contains(svc, "IAM") { svc = strings.ReplaceAll(svc, "IAM", "Iam") } return svc } ////////// // The following was not in the original file in gapic-generator-go. // fullyQualifiedType constructs a fully-qualified type name suitable for use with pbinfo.Info. func FullyQualifiedType(segments ...string) string { // In descriptors, putting the dot in front means the name is fully-qualified. const dot = "." typeName := strings.Join(segments, dot) if !strings.HasPrefix(typeName, dot) { typeName = dot + typeName } return typeName } ================================================ FILE: util/genrest/protomodel/protomodel.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package protomodel import ( "fmt" "strings" "github.com/googleapis/gapic-showcase/util/genrest/errorhandling" "github.com/googleapis/gapic-showcase/util/genrest/internal/pbinfo" "google.golang.org/protobuf/types/descriptorpb" ) //////////////////////////////////////// // ProtoModel // Model is a data model encapsulating the relevant information for a REST-proto transcoding for // various services defined via annotated protocol buffers. type Model struct { errorhandling.Accumulator ProtoInfo pbinfo.Info Services []*Service } // String returns a string representation of this Model. func (model *Model) String() string { services := make([]string, len(model.Services)) for idx, svc := range model.Services { if svc == nil { continue } services[idx] = svc.String() } return strings.Join(services, "\n\n") } // AddService adds `service` to this Service. func (model *Model) AddService(service *Service) *Service { model.Services = append(model.Services, service) return service } //////////////////////////////////////// // Service // Service is a data model encapsulating the information relevant to REST-proto transcoding about a // proto-defined service. type Service struct { Descriptor *descriptorpb.ServiceDescriptorProto // maybe not needed Name string TypeName string RESTBindings []*RESTBinding } // String returns a string representation of this Service. func (service *Service) String() string { handlers := make([]string, len(service.RESTBindings)) for idx, h := range service.RESTBindings { handlers[idx] = h.String() } indent := " " return fmt.Sprintf("%s (%s):\n%s%s", service.Name, service.TypeName, indent, strings.Join(handlers, "\n"+indent)) } // AddBinding adds a RESTBinding to this Service. func (service *Service) AddBinding(binding *RESTBinding) { service.RESTBindings = append(service.RESTBindings, binding) } //////////////////////////////////////// // RESTBinding // RESTBinding encapsulates the information contained in a protocol buffer HTTP annotation. type RESTBinding struct { // Index of the binding for this method. Since methods could contain multiple bindings, we // will need a way to identify each binding uniquely. Index int // The name of the method for which this is a binding. ProtoMethod string // The URL pattern of the binding. RESTPattern *RESTRequestPattern // The fields in the request body: either none (empty string), a single field (top-level // request field, non-dotted), or all not captured in the URL ("*"). BodyField string } // String returns a string representation of this RESTBinding. func (binding *RESTBinding) String() string { return fmt.Sprintf("%s[%d] : %s", binding.ProtoMethod, binding.Index, binding.RESTPattern) } //////////////////////////////////////// // RESTRequestPattern // RESTRequestPattern encapsulates the information in an individual REST binding within an HTTP annotation. type RESTRequestPattern struct { HTTPMethod string // HTTP verb Pattern string // the URL pattern } // String returns a string representation of this RESTRequestPattern. func (binding *RESTRequestPattern) String() string { return fmt.Sprintf("%s: %q", binding.HTTPMethod, binding.Pattern) } ================================================ FILE: util/genrest/protomodelcreator.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package genrest import ( "fmt" "os" "cloud.google.com/go/iam/apiv1/iampb" "cloud.google.com/go/longrunning/autogen/longrunningpb" "github.com/ghodss/yaml" "github.com/golang/protobuf/protoc-gen-go/descriptor" "github.com/googleapis/gapic-showcase/util/genrest/internal/pbinfo" "github.com/googleapis/gapic-showcase/util/genrest/protomodel" "google.golang.org/genproto/googleapis/api/annotations" "google.golang.org/genproto/googleapis/api/serviceconfig" "google.golang.org/genproto/googleapis/cloud/location" "google.golang.org/protobuf/compiler/protogen" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protodesc" "google.golang.org/protobuf/types/descriptorpb" ) //////////////////////////////////////// // ProtoModel // NewProtoModel uses the information in `plugin` to create a new protomodel.Model. func NewProtoModel(plugin *protogen.Plugin) (*protomodel.Model, error) { protoFiles := append(plugin.Request.GetProtoFile(), getMixinFiles()...) protoModel := &protomodel.Model{ ProtoInfo: pbinfo.Of(protoFiles), Services: make([]*protomodel.Service, 0, len(protoFiles)), } generateFile := map[string]bool{} for _, fileName := range plugin.Request.GetFileToGenerate() { generateFile[fileName] = true } for _, protoFile := range protoFiles { if !generateFile[*protoFile.Name] { continue } protoPackage := *protoFile.Package for _, svc := range protoFile.GetService() { serviceModel := protoModel.AddService(NewService(protoPackage, svc)) for _, method := range svc.GetMethod() { addBindingsForMethod(protoModel, serviceModel, method) } } } serviceConfig, err := GetServiceConfig() if err != nil { return nil, err } mixins := collectMixins(serviceConfig) for _, mixinFile := range mixins { protoPackage := *mixinFile.file.Package for _, mixinService := range mixinFile.services { svc := mixinService.service serviceModel := protoModel.AddService(NewService(protoPackage, svc)) for _, method := range mixinService.methods { addBindingsForMethod(protoModel, serviceModel, method) } } } return protoModel, protoModel.Error() } func addBindingsForMethod(protoModel *protomodel.Model, serviceModel *protomodel.Service, method *descriptor.MethodDescriptorProto) { options := method.GetOptions() if options == nil { return } eHTTP /*, err*/ := proto.GetExtension(method.GetOptions(), annotations.E_Http) http := eHTTP.(*annotations.HttpRule) rules := []*annotations.HttpRule{http} rules = append(rules, http.GetAdditionalBindings()...) for idxRule, oneRule := range rules { protoModel.AccumulateError(NewServiceBinding(serviceModel, method, oneRule, idxRule)) } } //////////////////////////////////////// // Service // NewService creates a protomodel.Service from the given descriptor. func NewService(protoPackage string, descriptor *descriptorpb.ServiceDescriptorProto) *protomodel.Service { // might need *descriptor.ProtoReflect().Type() to instantiate Go type and then reflect to get the name? service := &protomodel.Service{ Descriptor: descriptor, Name: *descriptor.Name, TypeName: pbinfo.FullyQualifiedType(protoPackage, descriptor.GetName()), RESTBindings: make([]*protomodel.RESTBinding, 0), } return service } // NewServiceBinding adds `rule` (as the `index`th binding for `method`) to the specified `service`. func NewServiceBinding(service *protomodel.Service, method *descriptor.MethodDescriptorProto, rule *annotations.HttpRule, index int) error { binding, err := NewRESTBinding(pbinfo.FullyQualifiedType(service.TypeName, method.GetName()), rule, index) if err != nil { return fmt.Errorf("service %q: %s", service.Name, err) } service.AddBinding(binding) return nil } //////////////////////////////////////// // RESTBinding // NewRESTBinding creates a new protomodel.RESTBinding using the given methodName, rule, and index. func NewRESTBinding(methodName string, rule *annotations.HttpRule, index int) (*protomodel.RESTBinding, error) { restPattern, err := NewRESTRequestPattern(rule) if err != nil { return nil, fmt.Errorf("method %q, binding %d: %s", methodName, index, err) } binding := &protomodel.RESTBinding{ Index: index, ProtoMethod: methodName, RESTPattern: restPattern, BodyField: rule.GetBody(), } return binding, nil } //////////////////////////////////////// // RESTRequestPattern // NewRESTRequestPattern creates a new protomodel.RESTRequestPattern by analyzing the rule provided. func NewRESTRequestPattern(rule *annotations.HttpRule) (*protomodel.RESTRequestPattern, error) { binding := &protomodel.RESTRequestPattern{} pattern := rule.GetPattern() switch pattern.(type) { case *annotations.HttpRule_Get: binding.HTTPMethod = "GET" binding.Pattern = rule.GetGet() case *annotations.HttpRule_Post: binding.HTTPMethod = "POST" binding.Pattern = rule.GetPost() case *annotations.HttpRule_Patch: binding.HTTPMethod = "PATCH" binding.Pattern = rule.GetPatch() case *annotations.HttpRule_Put: binding.HTTPMethod = "PUT" binding.Pattern = rule.GetPut() case *annotations.HttpRule_Delete: binding.HTTPMethod = "DELETE" binding.Pattern = rule.GetDelete() default: return nil, fmt.Errorf("unhandled pattern: %#x", pattern) } return binding, nil } //////////////////////////////////////// // Mixins // Note: much of the code below is a modified copy of the mixin code in gapic-generator-go. // GetServiceConfig reads and returns the Showcase service config file. func GetServiceConfig() (*serviceconfig.Service, error) { // TODO: Consider getting this from the plugin options. On the // other hand, there's only one copy of this file, so maybe // hard-coding this location isn't terrible. serviceConfigPath := "schema/google/showcase/v1beta1/showcase_v1beta1.yaml" y, err := os.ReadFile(serviceConfigPath) if err != nil { cwd, _ := os.Getwd() return nil, fmt.Errorf("error reading service config %q (cwd==%q): %v", serviceConfigPath, cwd, err) } j, err := yaml.YAMLToJSON(y) if err != nil { return nil, fmt.Errorf("error converting YAML to JSON: %v", err) } serviceConfig := &serviceconfig.Service{} if err := (protojson.UnmarshalOptions{DiscardUnknown: true}).Unmarshal(j, serviceConfig); err != nil { return nil, fmt.Errorf("error unmarshaling service config: %v", err) } // An API Service Config will always have a `name` so if it is not populated, // it's an invalid config. if serviceConfig.GetName() == "" { return nil, fmt.Errorf("invalid API service config file %q", serviceConfigPath) } return serviceConfig, nil } // Mixins is the collection of files containing methods to be mixed in. type Mixins []*MixinFile // MixinFile describes a single file containins methods to be mixed in. type MixinFile struct { file *descriptor.FileDescriptorProto services []*MixinService } // MixinService describes a single service containing methods to be filled in type MixinService struct { service *descriptor.ServiceDescriptorProto methods []*descriptor.MethodDescriptorProto } // indexedRules keys HTTP rules by their selectors type indexedRules map[string]*annotations.HttpRule // collectMixins collects the configured mixin APIs from the service config and // returns the appropriately configured mixin `MethodDescriptorProto`s to generate for each. func collectMixins(serviceConfig *serviceconfig.Service) Mixins { mixinRules := indexedRules{} for _, rule := range serviceConfig.GetHttp().GetRules() { mixinRules[rule.GetSelector()] = rule } mixins := Mixins{} for _, api := range serviceConfig.GetApis() { mixins = append(mixins, getMixinsForAPI(mixinRules, api.GetName())...) } return mixins } // getMixinsForAPI returns the appropriately configured mixin `MethodDescriptorProto`s // corresponding to the `mixinRules` that refer to `api`. The method descriptors are taken from the // package-global `mixinDescriptors`. func getMixinsForAPI(mixinRules indexedRules, api string) Mixins { files := Mixins{} for _, file := range mixinDescriptors[api] { fileToAdd := &MixinFile{ file: file, } files = append(files, fileToAdd) for _, service := range file.GetService() { serviceToAdd := &MixinService{ service: service, } fileToAdd.services = append(fileToAdd.services, serviceToAdd) for _, method := range service.GetMethod() { fqn := fmt.Sprintf("%s.%s.%s", file.GetPackage(), service.GetName(), method.GetName()) if rule := mixinRules[fqn]; rule != nil { proto.SetExtension(method.Options, annotations.E_Http, rule) serviceToAdd.methods = append(serviceToAdd.methods, method) } } } } return files } func getMixinFiles() (files []*descriptor.FileDescriptorProto) { for _, descriptors := range mixinDescriptors { files = append(files, descriptors...) } return } // mixinDescriptors maps fully qualified proto service names of mixins implemented by Showcase to a // list of FileDescriptors containing the definitions needed for that service. var mixinDescriptors map[string][]*descriptor.FileDescriptorProto func init() { mixinDescriptors = map[string][]*descriptor.FileDescriptorProto{ "google.longrunning.Operations": { protodesc.ToFileDescriptorProto(longrunningpb.File_google_longrunning_operations_proto), }, "google.cloud.location.Locations": { protodesc.ToFileDescriptorProto(location.File_google_cloud_location_locations_proto), }, "google.iam.v1.IAMPolicy": { protodesc.ToFileDescriptorProto(iampb.File_google_iam_v1_iam_policy_proto), protodesc.ToFileDescriptorProto(iampb.File_google_iam_v1_policy_proto), protodesc.ToFileDescriptorProto(iampb.File_google_iam_v1_options_proto), }, } } ================================================ FILE: util/genrest/resttools/checkrequestformat.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resttools import ( "encoding/json" "fmt" "io" "net/http" "strconv" "strings" "unicode" "unicode/utf8" "github.com/iancoleman/strcase" "google.golang.org/protobuf/reflect/protoreflect" ) // CheckRequestFormat verifies that the incoming request has the correct format in its body (via jsonReader) and in its HTTP headers. func CheckRequestFormat(jsonReader io.Reader, request *http.Request, message protoreflect.Message) error { header := request.Header if err := CheckAPIClientHeader(header); err != nil { return err } if jsonReader == nil { return nil } if err := CheckContentType(header); err != nil { return err } jsonBytes, err := io.ReadAll(jsonReader) if err != nil { return err } if (request.Method == http.MethodGet || request.Method == http.MethodDelete) && request.Body != nil { return fmt.Errorf("(UnexpectedRequestBodyError) non-zero body for HTTP %q", request.Method) } var payload jsonPayload json.Unmarshal(jsonBytes, &payload) if err := CheckFieldNames(payload); err != nil { return err } enumFields := GetEnumFields(message) return CheckJSONEnumFields(payload, enumFields) } // CheckFieldNames checks that the field names in the JSON request body are properly formatted // (lower-camel-cased). func CheckFieldNames(payload jsonPayload) error { for fieldName, value := range payload { rune, _ := utf8.DecodeRuneInString(fieldName) if strings.ContainsAny(fieldName, "_- ") || !unicode.IsLower(rune) { return fmt.Errorf("%s field name is not lower-camel-cased; probably want be %q (BodyFieldNameIncorrectlyCasedError)", fieldName, strcase.ToLowerCamel(fieldName)) } if nested, ok := value.(map[string]interface{}); ok { if err := CheckFieldNames(nested); err != nil { return fmt.Errorf("%s.%s", fieldName, err) } } } return nil } // CheckJSONEnumFields verifies that each of the fields listed in fieldsToCheck, presumably all // referring to enum fields, are encoded correctly in the parsed JSON payload, meaning that the // field is absent or its value is a string. Each element of fieldsToCheck is a qualified proto // field name represented as a sequence of simple protoreflect.Name. func CheckJSONEnumFields(payload jsonPayload, fieldsToCheck [][]protoreflect.Name) error { badFields := []string{} for _, fieldPath := range fieldsToCheck { if field, ok := CheckEnum(payload, fieldPath); !ok { badFields = append(badFields, field) } } if len(badFields) > 0 { return fmt.Errorf("(EnumEncodingError) badly transcoded enum values in fields: %v", badFields) } return nil } // CheckEnum verifies whether the field whose qualified name is captured in the elements of // fieldPath has a string value, if it exists, in the JSON representation captured by payload. This // returns the qualified field name (as present as it is in payload) as a single string, and a // boolean that is true only if either fieldPath is not present or if its value is a string. This // means that if fieldPath is a path to an enum field, the boolean will be false if the enum is // encoded in the payload using a non-string representation. func CheckEnum(payload jsonPayload, fieldPath []protoreflect.Name) (fieldName string, ok bool) { nameParts := []string{} last := len(fieldPath) - 1 var value string var found, isString bool for idx, pathSegment := range fieldPath { segment := strcase.ToLowerCamel(string(pathSegment)) nameParts = append(nameParts, segment) // TODO: For repeated fields, will need to recurse. Consider denoting repeated fields by appending a "*" to the pathSegment if idx < last { payload, found = payload[segment].(jsonPayload) if !found { // Some elements of the field path are not populated break } continue } if _, found = payload[segment]; found { // We found the field specified by fieldPath. value, isString = payload[segment].(string) } } fieldName = strings.Join(nameParts, ".") if !found { // We did not find the field denoted by fieldPath, so there is no error. return fieldName, true } if !isString { // We found the enum field denoted by fieldPath, but its value is not a string. This // is an error: we require all enum values to be REST-encoded via their string // representations for REST transport. return fieldName, false } if _, err := strconv.Atoi(value); err == nil { // We found the enum field denoted by fieldPath, and its JSON value is of string // type, but the value of the string merely represents a number. This is an error: a // string representation of an enum value should not be parseable as an int, as it // must contain letters, typically forming words. return fieldName, false } return fieldName, true } // GetEnumFields returns a list of any arbitrarily nested fields in message that are enums. Each // member of the returned list is a qualified field name, itself represented as a list of // simple protoreflect.Name. func GetEnumFields(message protoreflect.Message) [][]protoreflect.Name { messageName := message.Descriptor().FullName() if fields, ok := protoEnumFields[messageName]; ok { return fields } fields := ComputeEnumFields(message) protoEnumFields[messageName] = fields return fields } // ComputeEnumFields determines which fields in message or its submessages are enums, and returns a // list of those qualified field names (each one of those being a list of simple // protoreflect.Name). func ComputeEnumFields(message protoreflect.Message) [][]protoreflect.Name { return computeEnumFields(message.Descriptor(), []protoreflect.Name{}) } // computeEnumFields determines which fields in message or its submessages are enums, and returns a // list of those qualified field names (each one of those being a list of simple // protoreflect.Name). currentPath must be the fully qualified name for message. func computeEnumFields(message protoreflect.MessageDescriptor, currentPath []protoreflect.Name) [][]protoreflect.Name { results := [][]protoreflect.Name{} allFields := message.Fields() for idx := 0; idx < allFields.Len(); idx++ { field := allFields.Get(idx) switch field.Kind() { case protoreflect.EnumKind: results = append(results, append(currentPath, field.Name())) case protoreflect.MessageKind: results = append(results, computeEnumFields(field.Message(), append(currentPath, field.Name()))...) default: continue } } return results } // jsonPayload is used for unmarshaling arbitrary JSON. type jsonPayload map[string]interface{} // protoEnumFields is a list of fields paths (themselves represented as a list of nested field // names) which represent enum fields. This is used to memoize calls to GetEnumFields. var protoEnumFields map[protoreflect.FullName][][]protoreflect.Name func init() { protoEnumFields = map[protoreflect.FullName][][]protoreflect.Name{} } ================================================ FILE: util/genrest/resttools/checkrequestformat_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resttools import ( "net/http" "reflect" "strings" "testing" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "google.golang.org/protobuf/reflect/protoreflect" ) func TestComputeEnumFields(t *testing.T) { complianceData := &genprotopb.ComplianceData{} want := [][]protoreflect.Name{ {"f_kingdom"}, {"f_child", "f_continent"}, {"f_child", "p_continent"}, {"p_kingdom"}, {"p_child", "f_continent"}, {"p_child", "p_continent"}, } got := ComputeEnumFields(complianceData.ProtoReflect()) if !reflect.DeepEqual(got, want) { t.Errorf("enum fields: got %v, want %v", got, want) } } func TestCheckRequestFormat(t *testing.T) { for idx, testCase := range []struct { label string json string header http.Header // nil means standard headers method string // empty means POST wantError string }{ { label: "normal case", json: `{"fString": "hi", "fKingdom": "FUNGI"}`, }, { label: "normal case using PUT", json: `{"fString": "hi", "fKingdom": "FUNGI"}`, method: "PUT", }, { label: "normal case using PATCH", json: `{"fString": "hi", "fKingdom": "FUNGI"}`, method: "PATCH", }, { label: "normal case, optional field", json: `{"fString": "hi", "pKingdom": "FUNGI"}`, }, { label: "normal case, nested message, optional field", json: `{"fString": "hi", "fChild": {"pContinent": "AFRICA"}}`, }, { label: "normal case, nested optional message", json: `{"fString": "hi", "pChild": {"fContinent": "AFRICA"}}`, }, { label: "normal case, no enum", json: `{"fString": "hi"}`, }, { label: "normal case, correct headers", json: `{"fString": "hi"}`, header: http.Header{ headerNameContentType: []string{headerValueContentTypeJSON}, headerNameAPIClient: []string{"foo/1 rest/foo gapic/2 blah"}, }, }, { label: "GET with a body", json: `{"fString": "hi", "fKingdom": "FUNGI"}`, method: "GET", wantError: "(UnexpectedRequestBodyError)", }, { label: "DELETE with a body", json: `{"fString": "hi", "fKingdom": "FUNGI"}`, method: "DELETE", wantError: "(UnexpectedRequestBodyError)", }, { label: "no api client header", json: `{"fString": "hi"}`, header: http.Header{headerNameContentType: []string{headerValueContentTypeJSON}}, wantError: "(HeaderAPIClientError)", }, { label: "no header rest token", json: `{"fString": "hi"}`, header: http.Header{ headerNameContentType: []string{headerValueContentTypeJSON}, headerNameAPIClient: []string{"foo/1 gapic/2 blah"}, }, wantError: "(HeaderTransportRESTError)", }, { label: "no header gapic token", json: `{"fString": "hi"}`, header: http.Header{ headerNameContentType: []string{headerValueContentTypeJSON}, headerNameAPIClient: []string{"foo/1 rest/foo blah"}, }, wantError: "(HeaderClientGAPICError)", }, { label: "no content-type header", json: `{"fString": "hi"}`, header: http.Header{ headerNameAPIClient: []string{"foo/1 rest/foo gapic/2 blah"}, }, wantError: "(HeaderContentTypeError)", }, { label: "bad content-type header", json: `{"fString": "hi"}`, header: http.Header{ headerNameContentType: []string{"something " + headerValueContentTypeJSON}, headerNameAPIClient: []string{"foo/1 rest/foo gapic/2 blah"}, }, wantError: "(HeaderContentTypeError)", }, { label: "random string does not fail", json: `{"fString": "hi", "fKingdom": "MONACO"}`, }, { label: "numeric enum", json: `{"fString": "hi", "fKingdom": 56}`, wantError: "(EnumEncodingError)", }, { label: "numeric optional enum", json: `{"fString": "hi", "pKingdom": 57}`, wantError: "(EnumEncodingError)", }, { label: "stringy numeric enum", json: `{"fString": "hi", "fKingdom": "56"}`, wantError: "(EnumEncodingError)", }, { label: "stringy optional numeric enum", json: `{"fString": "hi", "fKingdom": "57"}`, wantError: "(EnumEncodingError)", }, { label: "stringy number+letter enum", json: `{"fString": "hi", "fKingdom": "56Abacus"}`, }, } { complianceData := &genprotopb.ComplianceData{} method := testCase.method if len(method) == 0 { method = "POST" } request, err := http.NewRequest(method, "showcase.foo.com", strings.NewReader(testCase.json)) if err != nil { t.Fatalf("test case %d[%q] could not create request: %s", idx, testCase.label, err) } request.Header = testCase.header if request.Header == nil { PopulateRequestHeaders(request) } err = CheckRequestFormat(request.Body, request, complianceData.ProtoReflect()) if (err != nil) != (testCase.wantError != "") { t.Errorf("test case %d[%q] CheckRequestFormat(): expected error==%v, got: %v", idx, testCase.label, testCase.wantError, err) continue } if err == nil { continue } if got, want := err.Error(), testCase.wantError; !strings.Contains(got, want) { t.Errorf("test case %d[%q] CheckRequestFormat(): incorrect error: want: %q, got %q", idx, testCase.label, want, got) } } } ================================================ FILE: util/genrest/resttools/constants.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resttools import "fmt" const ( // CharsField contains the characters allowed in a field name (URL path or body) CharsField = `-_.0-9a-zA-Z` // CharsLiteral contains the the characters allowed in a URL path literal segment. CharsLiteral = `-_.~0-9a-zA-Z%` // RegexURLPathSingleSegmentValue contains the regex expression for matching a single URL // path segment (i.e. `/` is not allowed). Since gorilla/mux hands uses the decoded paths to // match, we can just accept any characters. RegexURLPathSingleSegmentValue = "[^:]+" // RegexURLPathSingleSegmentValue contains the regex expression for matching multiple URL // path segments (i.e. `/` is allowed). Since gorilla/mux hands uses the decoded paths to // match, we can just accept any characters. RegexURLPathMultipleSegmentValue = "[^:]+" ) var ( // CharsFieldPath contains the characters allowed in a dotted field path. CharsFieldPath string // RegexField contains the regex expression for matching a single (not nested) field name. RegexField string // RegexField contains the regex expression for matching a dotted field path. RegexFieldPath string // RegexLiteral contains the regex expression for matching a URL path literal segment. RegexLiteral string ) func init() { RegexField = fmt.Sprintf(`[%s]+`, CharsField) CharsFieldPath = CharsField + `.` RegexFieldPath = fmt.Sprintf(`^[%s]+`, CharsFieldPath) RegexLiteral = fmt.Sprintf(`^[%s]+`, CharsLiteral) } // A key-type for storing binding URI value in the Context type BindingURIKeyType string const BindingURIKey BindingURIKeyType = BindingURIKeyType("BindingURIKey") ================================================ FILE: util/genrest/resttools/error_response.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resttools import ( "fmt" "net/http" pb "github.com/googleapis/gapic-showcase/server/genproto" code "google.golang.org/genproto/googleapis/rpc/code" "google.golang.org/grpc/codes" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" anypb "google.golang.org/protobuf/types/known/anypb" ) // gRPCToHTTP is the status code mapping derived from the internal source go/http-canonical-mapping. var gRPCToHTTP map[codes.Code]int = map[codes.Code]int{ codes.OK: http.StatusOK, codes.Canceled: 499, // There isn't a Go constant ClientClosedConnection codes.Unknown: http.StatusInternalServerError, codes.InvalidArgument: http.StatusBadRequest, codes.DeadlineExceeded: http.StatusGatewayTimeout, codes.NotFound: http.StatusNotFound, codes.AlreadyExists: http.StatusConflict, codes.PermissionDenied: http.StatusForbidden, codes.Unauthenticated: http.StatusUnauthorized, codes.ResourceExhausted: http.StatusTooManyRequests, codes.FailedPrecondition: http.StatusBadRequest, codes.Aborted: http.StatusConflict, codes.OutOfRange: http.StatusBadRequest, codes.Unimplemented: http.StatusNotImplemented, codes.Internal: http.StatusInternalServerError, codes.Unavailable: http.StatusServiceUnavailable, codes.DataLoss: http.StatusInternalServerError, } // httpToGRPC is the status code mapping derived from the internal source go/http-canonical-mapping. // This is not merely the inverse of gRPCToHTTP (which, at any rate, is not injective). The // canonical mapping also specifies codes for some HTTP status ranges, so it is imperative to use // HTTPToGRPC(). var httpToGRPC = map[int]codes.Code{ http.StatusBadRequest: codes.InvalidArgument, http.StatusUnauthorized: codes.Unauthenticated, http.StatusForbidden: codes.PermissionDenied, http.StatusNotFound: codes.NotFound, http.StatusConflict: codes.Aborted, http.StatusRequestedRangeNotSatisfiable: codes.OutOfRange, http.StatusTooManyRequests: codes.ResourceExhausted, 499: codes.Canceled, // There isn't a Go constant ClientClosedConnection http.StatusNotImplemented: codes.Unimplemented, http.StatusServiceUnavailable: codes.Unavailable, http.StatusGatewayTimeout: codes.DeadlineExceeded, } // GRPCToHTTP maps the given gRPC Code to the canonical HTTP Status code as // defined by the internal source go/http-canonical-mapping. func GRPCToHTTP(c codes.Code) int { httpStatus, ok := gRPCToHTTP[c] if !ok { httpStatus = http.StatusInternalServerError } return httpStatus } // HTTPToGRPC maps the given HTTP status code to the canonical gRPC // Code as defined by the internal source go/http-canonical-mapping. func HTTPToGRPC(httpStatus int) codes.Code { var gRPCCode codes.Code switch { case httpStatus >= 200 && httpStatus < 300: gRPCCode = codes.OK case httpStatus >= 300 && httpStatus < 400: gRPCCode = codes.Unknown case httpStatus >= 400 && httpStatus < 500: gRPCCode = codes.FailedPrecondition case httpStatus >= 500 && httpStatus < 600: gRPCCode = codes.Internal default: gRPCCode = codes.Unknown } if codeOverride, ok := httpToGRPC[httpStatus]; ok { gRPCCode = codeOverride } return gRPCCode } // Constants to make it obvious when we're not supplying either a gRPC or HTTP status code to // ErrorResponse(). The code we're not supplying will be obtained from the one we do supply. const ( // NoCodeGRPC is an explicit indication when calling ErrorResponse() that we don't know the // gRPC status code and it must be derived from the HTTP response code. NoCodeGRPC codes.Code = 9999 // NoCodeHTTP is an explicit indication when calling ErrorResponse() that we don't know the // HTTP response code and it must be derived from the gRPC status code. NoCodeHTTP int = -1 ) // ErrorResponse is a helper that formats the given response information, including the HTTP or gRPC // status code, a message, and any error detail types, into a RestError proto message and writes the // response as JSON. func ErrorResponse(w http.ResponseWriter, httpResponseCode int, grpcStatus codes.Code, message string, details ...interface{}) { if httpResponseCode == NoCodeHTTP && grpcStatus == NoCodeGRPC { WriteShowcaseRESTImplementationError(w, "neither HTTP code or gRPC status are provided for ErrorResponse. Exactly one must be provided.") return } if httpResponseCode != NoCodeHTTP && grpcStatus != NoCodeGRPC { WriteShowcaseRESTImplementationError(w, "both HTTP code and gRPC status are provided for ErrorResponse. Exactly one must be provided.") return } if httpResponseCode == NoCodeHTTP { httpResponseCode = GRPCToHTTP(grpcStatus) } else { grpcStatus = HTTPToGRPC(httpResponseCode) } jsonError := &pb.RestError{ Error: &pb.RestError_Status{ Code: int32(httpResponseCode), Message: message, Status: code.Code(grpcStatus), }, } for _, oneDetail := range details { detailAsAny, err := anypb.New(oneDetail.(proto.Message)) if err != nil { WriteShowcaseRESTImplementationError(w, fmt.Sprintf("could not interpret error detail as a protobuf Any: %+v", oneDetail)) return } jsonError.Error.Details = append(jsonError.Error.Details, detailAsAny) } w.WriteHeader(httpResponseCode) data, _ := protojson.Marshal(jsonError) w.Write(data) } func WriteShowcaseRESTImplementationError(w http.ResponseWriter, message string) { ErrorResponse(w, 500, NoCodeGRPC, fmt.Sprintf("Showcase consistency error: %s", message)) } ================================================ FILE: util/genrest/resttools/error_response_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resttools import ( "encoding/json" "io" "net/http" "net/http/httptest" "testing" "github.com/google/go-cmp/cmp" "google.golang.org/genproto/googleapis/rpc/errdetails" "google.golang.org/grpc/codes" ) func TestErrorResponse(t *testing.T) { for _, tst := range []struct { details []interface{} message, name string inputHTTPStatus int inputGRPCCode codes.Code wantHTTPStatus int wantResponse string }{ // HTTP → gRPC codes { name: "internal_server", message: "Had an issue", inputGRPCCode: NoCodeGRPC, inputHTTPStatus: http.StatusInternalServerError, wantHTTPStatus: http.StatusInternalServerError, details: []interface{}{&errdetails.ErrorInfo{Reason: "foo"}}, wantResponse: `{"error":{"code":500, "message":"Had an issue", "status":"INTERNAL", "details":[{"@type":"type.googleapis.com/google.rpc.ErrorInfo", "reason":"foo"}]}}`, }, { name: "bad_request", message: "The request was bad", inputGRPCCode: NoCodeGRPC, inputHTTPStatus: http.StatusBadRequest, wantHTTPStatus: http.StatusBadRequest, wantResponse: `{"error":{"code":400, "message":"The request was bad", "status":"INVALID_ARGUMENT"}}`, }, { name: "multiple_issues", message: "Had multiple issues", inputGRPCCode: NoCodeGRPC, inputHTTPStatus: http.StatusInternalServerError, wantHTTPStatus: http.StatusInternalServerError, details: []interface{}{ &errdetails.ErrorInfo{Reason: "foo"}, &errdetails.BadRequest{ FieldViolations: []*errdetails.BadRequest_FieldViolation{ { Field: "an offending field", Description: "a description", Reason: "a reason", }, }, }, }, wantResponse: `{"error":{"code":500, "message":"Had multiple issues", "status":"INTERNAL", "details":[{"@type":"type.googleapis.com/google.rpc.ErrorInfo", "reason":"foo"}, {"@type":"type.googleapis.com/google.rpc.BadRequest", "fieldViolations":[{"field":"an offending field", "description":"a description", "reason":"a reason"}]}]}}`, }, // gRPC → HTTP codes { name: "internal_server", message: "Had an issue", inputGRPCCode: codes.Internal, inputHTTPStatus: NoCodeHTTP, wantHTTPStatus: http.StatusInternalServerError, details: []interface{}{&errdetails.ErrorInfo{Reason: "foo"}}, wantResponse: `{"error":{"code":500, "message":"Had an issue", "status":"INTERNAL", "details":[{"@type":"type.googleapis.com/google.rpc.ErrorInfo", "reason":"foo"}]}}`, }, { name: "bad_request", message: "The request was bad", inputGRPCCode: codes.InvalidArgument, inputHTTPStatus: NoCodeHTTP, wantHTTPStatus: http.StatusBadRequest, wantResponse: `{"error":{"code":400, "message":"The request was bad", "status":"INVALID_ARGUMENT"}}`, }, { name: "multiple_issues", message: "Had multiple issues", inputGRPCCode: codes.Internal, inputHTTPStatus: NoCodeHTTP, wantHTTPStatus: http.StatusInternalServerError, details: []interface{}{ &errdetails.ErrorInfo{Reason: "foo"}, &errdetails.BadRequest{ FieldViolations: []*errdetails.BadRequest_FieldViolation{ { Field: "an offending field", Description: "a description", Reason: "a reason", }, }, }, }, wantResponse: `{"error":{"code":500, "message":"Had multiple issues", "status":"INTERNAL", "details":[{"@type":"type.googleapis.com/google.rpc.ErrorInfo", "reason":"foo"}, {"@type":"type.googleapis.com/google.rpc.BadRequest", "fieldViolations":[{"field":"an offending field", "description":"a description", "reason":"a reason"}]}]}}`, }, // error inputs { name: "test when neither gRPC nor HTTP code is specified", message: "Had an issue", inputGRPCCode: NoCodeGRPC, inputHTTPStatus: NoCodeHTTP, wantHTTPStatus: http.StatusInternalServerError, details: []interface{}{&errdetails.ErrorInfo{Reason: "foo"}}, wantResponse: `{"error":{"code":500, "message":"Showcase consistency error: neither HTTP code or gRPC status are provided for ErrorResponse. Exactly one must be provided.", "status":"INTERNAL"}}`, }, { name: "test when both gRPC and HTTP codes are specified", message: "Had an issue", inputGRPCCode: codes.Internal, inputHTTPStatus: http.StatusBadRequest, wantHTTPStatus: http.StatusInternalServerError, details: []interface{}{&errdetails.ErrorInfo{Reason: "foo"}}, wantResponse: `{"error":{"code":500, "message":"Showcase consistency error: both HTTP code and gRPC status are provided for ErrorResponse. Exactly one must be provided.", "status":"INTERNAL"}}`, }, } { got := httptest.NewRecorder() ErrorResponse(got, tst.inputHTTPStatus, tst.inputGRPCCode, tst.message, tst.details...) if got.Code != tst.wantHTTPStatus { t.Errorf("%s: Expected code %d, but got %d", tst.name, tst.wantHTTPStatus, got.Code) } gotResponse, err := io.ReadAll(got.Result().Body) if err != nil { t.Fatalf("%s: Error reading response body: %+v", tst.name, err) } var gotJSON interface{} err = json.Unmarshal([]byte(gotResponse), &gotJSON) if err != nil { t.Fatalf("%s: Error parsing actual response body as JSON: %+v", tst.name, err) } var wantJSON interface{} err = json.Unmarshal([]byte(tst.wantResponse), &wantJSON) if err != nil { t.Fatalf("%s: Error parsing expected response body as JSON: %+v", tst.name, err) } if diff := cmp.Diff(gotJSON, wantJSON); diff != "" { t.Errorf("%s: error body: got(-),want(+):%s\n\n---------- Raw JSON: got\n%s\n---------- Raw JSON: want\n%s", tst.name, diff, gotResponse, tst.wantResponse) } } } func TestGRPCToHTTP(t *testing.T) { for _, tst := range []struct { code codes.Code want int }{ { codes.Aborted, http.StatusConflict, }, { 100, http.StatusInternalServerError, }, } { if got := GRPCToHTTP(tst.code); got != tst.want { t.Errorf("converting %s: got %d, but expected %d", tst.code, got, tst.want) } } } func TestHTTPToGRPC(t *testing.T) { // This test focuses on the ranges of HTTP codes that map to a single gRPC status, as per go/http-canonical-mapping. for _, tst := range []struct { code int want codes.Code }{ {200, codes.OK}, {299, codes.OK}, {350, codes.Unknown}, {403, codes.PermissionDenied}, {499, codes.Canceled}, {498, codes.FailedPrecondition}, {503, codes.Unavailable}, {599, codes.Internal}, {149, codes.Unknown}, } { if got := HTTPToGRPC(tst.code); got != tst.want { t.Errorf("converting %d: got %d, but expected %d", tst.code, got, tst.want) } } } ================================================ FILE: util/genrest/resttools/headers.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resttools import ( "fmt" "net/http" "strings" ) const ( headerNameContentType = "Content-Type" headerValueContentTypeJSON = "application/json" headerNameAPIClient = "X-Goog-Api-Client" headerValueTransportRESTPrefix = "rest/" headerValueClientGAPICPrefix = "gapic/" ) // PopulateRequestHeaders inspects request and adds the correct headers. This // is useful for tests where we're not trying to send incorrect // headers. func PopulateRequestHeaders(request *http.Request) { header := http.Header{} header.Set(headerNameAPIClient, fmt.Sprintf("%s0.0.0 %s0.0.0", headerValueTransportRESTPrefix, headerValueClientGAPICPrefix)) if request.Body != nil { header.Set(headerNameContentType, headerValueContentTypeJSON) } request.Header = header } // CheckContentType checks header to ensure the expected JSON content type is specified. func CheckContentType(header http.Header) error { if content, ok := header[headerNameContentType]; !ok || len(content) != 1 || !strings.HasPrefix(strings.ToLower(strings.TrimSpace(content[0])), headerValueContentTypeJSON) { return fmt.Errorf("(HeaderContentTypeError) did not find expected HTTP header %q: %q", headerNameContentType, headerValueContentTypeJSON) } return nil } // CheckAPIClientHeader verifies that the "x-goog-api-client" header contains the expected tokens // ("rest/..." and "gapic/..."). func CheckAPIClientHeader(header http.Header) error { content, ok := header[headerNameAPIClient] if !ok || len(content) != 1 { return fmt.Errorf("(HeaderAPIClientError) did not find expected HTTP header %q: %q\n found: %q", headerNameAPIClient, headerValueTransportRESTPrefix, header) } var haveREST, haveGAPIC bool for _, token := range strings.Split(content[0], " ") { trimmed := strings.TrimSpace(token) if !haveREST && strings.HasPrefix(trimmed, headerValueTransportRESTPrefix) { haveREST = true } else if !haveGAPIC && strings.HasPrefix(trimmed, headerValueClientGAPICPrefix) { haveGAPIC = true } else { // nothing changed continue } if haveREST && haveGAPIC { return nil } } if !haveREST { return fmt.Errorf("(HeaderTransportRESTError) did not find expected HTTP header token %q: %q", headerNameAPIClient, headerValueTransportRESTPrefix) } if !haveGAPIC { return fmt.Errorf("(HeaderClientGAPICError) did not find expected HTTP header token %q: %q", headerNameAPIClient, headerValueClientGAPICPrefix) } return fmt.Errorf("internal inconsistency") } // PrettyPrintHeaders prints all the HTTP headers in `request` in // lines preceded by `indentation`. Each line has one header key and a // quoted list of all values for that key. func PrettyPrintHeaders(request *http.Request, indentation string) string { lines := []string{} for key, values := range request.Header { newLine := fmt.Sprintf("%s%s:", indentation, key) for _, oneValue := range values { newLine += fmt.Sprintf(" %q", oneValue) } lines = append(lines, newLine) } return strings.Join(lines, "\n") } // IncludeRequestHeadersInResponse includes all headers in the request `r` and includes them in the response `w`, // prefixing each of these header keys with a constant to reflect they came from the request. func IncludeRequestHeadersInResponse(w http.ResponseWriter, r *http.Request) { const prefix = "x-showcase-request-" responseHeaders := w.Header() for requestKey, valueList := range r.Header { for _, value := range valueList { responseHeaders.Add(prefix+requestKey, value) } } } ================================================ FILE: util/genrest/resttools/json.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resttools import ( "strings" "sync" "github.com/iancoleman/strcase" "google.golang.org/protobuf/encoding/protojson" ) // ToJSON returns a copy of the current global JSON marshaling options in // JSONMarshaler. Modifications to this copy do not change the values of these options returned in // subsequent calls to this function. This is the function Showcase REST endpoints should use to // handle JSON marshaling. func ToJSON() *protojson.MarshalOptions { copy := *JSONMarshaler.current return © } // FromJSON returns a copy of the current global JSON unmarshaling options. Modifications to this copy // do not change the values of these options returned in subsequent calls to this function. This is // the function Showcase REST endpoints should use to handle JSON unmarshaling. func FromJSON() *protojson.UnmarshalOptions { return &protojson.UnmarshalOptions{} } // JSONMarshaler captures the JSON marshaling options. It is intended only for tests of Showcase // functionality (not for normal Showcase use or tests of generators against Showcase). var JSONMarshaler JSONMarshalOptions // JSONMarshalOptions contains the current JSON marshaling options used by REST endpoints, and // allows for temporarily replacing these global options and then restoring them. This functionality // is useful for some tests. type JSONMarshalOptions struct { current, saved *protojson.MarshalOptions mu sync.Mutex } // Replace replaces the current JSON marshaling options with those provided by opt. Call Restore() // to restore the production options. Only one replacement can be active at a time; subsequent calls // hang waiting for the first call's mutex to be released. // // As a special case, if opt==nil, the replacement is with the production options themselves; this // is useful for tests that need to lock the production options to protect from other tests which // may need to change them. func (jm *JSONMarshalOptions) Replace(opt *protojson.MarshalOptions) { jm.mu.Lock() if opt == nil { opt = jm.current } jm.saved = jm.current jm.current = opt } // Restore restores the production JSON marshaling options. There must be an active Replace() called // previously. func (jm *JSONMarshalOptions) Restore() { jm.current = jm.saved jm.saved = nil jm.mu.Unlock() } // ToDottedLowerCamel converts each segment of a dot-delimited fieldPath to be individually lower-camel-cased; the dots are preserved. func ToDottedLowerCamel(fieldPath string) string { parts := strings.Split(fieldPath, ".") for idx, segment := range parts { parts[idx] = strcase.ToLowerCamel(segment) } return strings.Join(parts, ".") } func init() { JSONMarshaler.current = &protojson.MarshalOptions{ Multiline: true, AllowPartial: false, UseEnumNumbers: false, EmitUnpopulated: true, UseProtoNames: false, // we want lower-camel-cased field names } } ================================================ FILE: util/genrest/resttools/keysmatching.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resttools import "strings" // KeysMatchPath returns the keys in `examine` that match any of the elements in `lookFor`, // interpreting the latter as dotted-field paths. This means a match occurs when (a) the two are // identical, or (b) when any element of `lookFor` is a prefix of the `examine` key and is followed // by a period. For example: // KeysMatchPath(map[string][]string{"loc": nil, "loc.lat": nil, "location":nil}, // // []string{"loc"}) // == []string{"loc","loc.lat"} func KeysMatchPath(examine map[string][]string, lookFor []string) []string { matchingKeys := []string{} for key, _ := range examine { for _, target := range lookFor { if matchesSelfOrParent(key, target) { matchingKeys = append(matchingKeys, key) break } } } return matchingKeys } // matchesSelfOrParent returns whether any element of `lookFor` is or contains a full or partial // path (in the dotted-field sense) to `examine`. In other words, this returns true when (a) the two // are identical, or (b) when `examine` starts with `lookFor` and is followed by a period. func matchesSelfOrParent(examine, lookFor string) bool { if !strings.HasPrefix(examine, lookFor) { return false } return len(examine) == len(lookFor) || examine[len(lookFor)] == '.' } ================================================ FILE: util/genrest/resttools/keysmatching_test.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resttools import ( "testing" ) func TestKeysMatchPath(t *testing.T) { for idx, testCase := range []struct { examine map[string][]string lookFor []string wantMatches map[string]bool }{ { examine: map[string][]string{ "loc": nil, "location": nil, "loc.lat": nil, "extra.loc.lat": nil, "location.lat": nil, }, lookFor: []string{"loc"}, wantMatches: map[string]bool{"loc": true, "loc.lat": true}, }, { examine: map[string][]string{ "loc": nil, "location": nil, "loc.lat": nil, "extra.loc.lat": nil, "location.lat": nil, }, lookFor: []string{"location", "loc"}, wantMatches: map[string]bool{"loc": true, "location": true, "loc.lat": true, "location.lat": true}, }, } { matches := KeysMatchPath(testCase.examine, testCase.lookFor) if got, want := len(matches), len(testCase.wantMatches); got != want { t.Errorf("testCase = %d: unexpected number of variables returned: got %v, want %v: returned elements: %v", idx, got, want, matches) continue } for matchIdx, got := range matches { if !testCase.wantMatches[got] { t.Errorf("testCase = %d: got unexpected match #%d %q; expected matches: %v", idx, matchIdx, got, matches) } } } } ================================================ FILE: util/genrest/resttools/populatefield.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resttools import ( "fmt" "strconv" "strings" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" ) // wellKnownTypes has a key for every well-known type message which JSON-encodes to an atomic symbol // (like a number or a string) as opposed to a structured object. The value for each key is true iff // the JSON encoding for the type is a string. We need both these data for well-known types so that // we can properly decode them in URL paths and query strings. var wellKnownTypes = map[string]bool{ // == The following are the only three common types used in this API == "google.protobuf.FieldMask": true, "google.protobuf.Timestamp": true, "google.protobuf.Duration": true, // == End utilized types == // TODO: When the following start being used in the Showcase API, add tests for each of // these. These types are defined in // https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/wrappers.proto "google.protobuf.DoubleValue": false, "google.protobuf.FloatValue": false, "google.protobuf.Int64Value": true, "google.protobuf.UInt64Value": true, "google.protobuf.Int32Value": false, "google.protobuf.UInt32Value": false, "google.protobuf.BoolValue": false, "google.protobuf.StringValue": true, "google.protobuf.BytesValue": true, // TODO: Determine if the following are even viable as query params. "google.protobuf.Value": false, "google.protobuf.ListValue": false, } // PopulateSingularFields sets the fields within protoMessage to the values provided in // fieldValues. The fields and values are provided as a map of field paths to the string // representation of their values. The field paths can refer to fields nested arbitrarily deep // within protoMessage; each path element must be lower-camel-cased. This returns an error if any // field path is not valid or if any value can't be parsed into the correct data type for the field. func PopulateSingularFields(protoMessage proto.Message, fieldValues map[string]string) error { for name, value := range fieldValues { if err := PopulateOneField(protoMessage, name, []string{value}); err != nil { // TODO: accumulate errors so we report them all at once return err } } return nil } // PopulateFields sets the fields within protoMessage to the values provided in fieldValues. The // fields and values are provided as a map of field paths to lists of string representations of // their values. The field paths can refer to fields nested arbitrarily deep within protoMessage; // each path element must be lower-camel-cased. `fieldValues` contains the list of values applicable // to the field: a single value of singular fields, or ordered values for a repeated field. This // returns an error if any field path is not valid or if any value can't be parsed into the correct // data type for the field. func PopulateFields(protoMessage proto.Message, fieldValues map[string][]string) error { for name, value := range fieldValues { if err := PopulateOneField(protoMessage, name, value); err != nil { // TODO: accumulate errors so we report them all at once return err } } return nil } // PopulateOneField finds in protoMessage the field identified by fieldPath (which could refer to an // arbitrarily nested field using dotted notation; each path element must be lower-camel-cased) and // sets it to `value`. It returns an error if the fieldPath does not properly reference a field, or // if `fieldValues` could not be parsed into a list of the data type expected for the // field. `fieldValues` is a slice to allow passing a series of repeated field entries. func PopulateOneField(protoMessage proto.Message, fieldPath string, fieldValues []string) error { message := protoMessage.ProtoReflect() // TODO: Support repeated fields. if len(fieldValues) > 1 { return fmt.Errorf("repeated field values are not supported yet (culprit: %q: %v)", fieldPath, fieldValues) } value := fieldValues[0] levels := strings.Split(fieldPath, ".") lastLevel := len(levels) - 1 for idx, fieldName := range levels { messageDescriptor := message.Descriptor() messageFullName := messageDescriptor.FullName() if messageDescriptor.Syntax() != protoreflect.Proto3 { return fmt.Errorf("cannot process %q as it does not use proto3 syntax", messageFullName) } if len(fieldName) == 0 { return fmt.Errorf("segment %d of path field %q is empty", idx, fieldPath) } // find field subFields := messageDescriptor.Fields() fieldDescriptor, err := findProtoFieldByJSONName(fieldName, subFields) if err != nil { return err } if fieldDescriptor == nil { return fmt.Errorf("could not find %dth field (%q) in field path %q in message %q", idx, fieldName, fieldPath, messageFullName) } if idx != lastLevel { // non-terminal field: go to the next level if kind := fieldDescriptor.Kind(); kind != protoreflect.MessageKind { return fmt.Errorf("%dth field (%q) in field path %q in message %q is not itself a message but a %q", idx, fieldName, fieldPath, messageFullName, kind) } message = message.Mutable(fieldDescriptor).Message() continue } // terminal field var ( protoValue protoreflect.Value parseError error ) kind := fieldDescriptor.Kind() switch kind { case protoreflect.MessageKind: // The only `MessageKind`s we accept in URL paths and query params are // well-known types where the message as a whole encodes into a format // similar to a regular terminal field. Normal messages conveyed via URL // paths or query params must be non-repeated and are represented by listing // their terminal primitive fields, which will trigger the other cases // below instead of this one. if pval, err := parseWellKnownType(message, fieldDescriptor, value); err != nil { parseError = err } else if pval != nil { protoValue = *pval } else { parseError = fmt.Errorf("terminal field %q of field path %q in message %q is a message type", fieldName, fieldPath, messageFullName) } // reference for proto scalar types: // https://developers.google.com/protocol-buffers/docs/proto3#scalar // TODO: see https://pkg.go.dev/google.golang.org/protobuf@v1.25.0/reflect/protoreflect#Kind case protoreflect.StringKind: protoValue = protoreflect.ValueOfString(value) case protoreflect.BytesKind: protoValue = protoreflect.ValueOfBytes([]byte(value)) case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: parsedValue, err := strconv.ParseInt(value, 10, 32) parseError, protoValue = err, protoreflect.ValueOfInt32(int32(parsedValue)) case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: parsedValue, err := strconv.ParseUint(value, 10, 32) parseError, protoValue = err, protoreflect.ValueOfUint32(uint32(parsedValue)) case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: parsedValue, err := strconv.ParseInt(value, 10, 64) parseError, protoValue = err, protoreflect.ValueOfInt64(parsedValue) case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: parsedValue, err := strconv.ParseUint(value, 10, 64) parseError, protoValue = err, protoreflect.ValueOfUint64(parsedValue) case protoreflect.FloatKind: parsedValue, err := strconv.ParseFloat(value, 32) parseError, protoValue = err, protoreflect.ValueOfFloat32(float32(parsedValue)) case protoreflect.DoubleKind: parsedValue, err := strconv.ParseFloat(value, 64) parseError, protoValue = err, protoreflect.ValueOfFloat64(parsedValue) case protoreflect.BoolKind: parsedValue, err := parseBool(value) parseError, protoValue = err, protoreflect.ValueOfBool(parsedValue) case protoreflect.EnumKind: var parsedValue protoreflect.EnumNumber if numericValue, err := strconv.ParseFloat(value, 32); err == nil { parsedValue = protoreflect.EnumNumber(numericValue) } else { enum := fieldDescriptor.Enum().Values().ByName(protoreflect.Name(value)) if enum == nil { return fmt.Errorf("(UnknownEnumStringError) unknown enum symbol %q for field path %q", value, fieldPath) } parsedValue = enum.Number() } parseError, protoValue = nil, protoreflect.ValueOfEnum(parsedValue) default: // TODO: Handle lists // TODO: Handle oneofs return fmt.Errorf("terminal field %q of field path %q is of type %q, which is not handled yet", fieldName, fieldPath, kind) } if parseError != nil { return fmt.Errorf("terminal field %q of field path %q is of type %q with value string %q, which could not be parsed: %s", fieldName, fieldPath, kind, value, parseError) } message.Set(fieldDescriptor, protoValue) } return nil } // parseBool parses a proper JSON representation of a bool value (either of the strings "true" or // "false") into a bool data type. Other values cause an error. These are stricter parsing semantics // than those of strconv.ParseBool and adhere to the JSON standard. func parseBool(asString string) (bool, error) { switch asString { case "true": return true, nil case "false": return false, nil default: return false, fmt.Errorf("could not parse %q as a bool", asString) } } // findFieldByProtoName queries `fields` for the unique field whose lower-camel-cased name is given // by `fieldName` and returns the corresponding FieldDescriptor or nil if none can be found. This // returns an error if more than one entry in `fields` has the same lower-camel-cased field // representations (as would occur, for example, for fields with proto names `foo5_bar` and // `foo_5_bar`). func findProtoFieldByJSONName(fieldName string, fields protoreflect.FieldDescriptors) (result protoreflect.FieldDescriptor, err error) { if ToDottedLowerCamel(fieldName) != fieldName { return nil, fmt.Errorf("(QueryParameterNameIncorrectlyCasedError)field name %q is not lower-camel-cased", fieldName) } numFields := fields.Len() for idx := 0; idx < numFields; idx++ { candidate := fields.Get(idx) if candidate.JSONName() == fieldName { if result != nil { return nil, fmt.Errorf("internal error: more than one field name has JSON lower-camel-case representation %q", fieldName) } result = candidate } } return result, nil } func parseWellKnownType(message protoreflect.Message, fieldDescriptor protoreflect.FieldDescriptor, value string) (*protoreflect.Value, error) { messageFieldTypes, ok := message.Type().(protoreflect.MessageFieldTypes) if !ok { return nil, fmt.Errorf("expected message to implement protoreflect.MessageFieldTypes but it did not") } fieldMsg := messageFieldTypes.Message(fieldDescriptor.Index()) fullName := string(fieldMsg.Descriptor().FullName()) stringEncoded, isWellKnown := wellKnownTypes[fullName] if !isWellKnown { return nil, nil } quoted := value[0] == '"' && value[len(value)-1] == '"' if stringEncoded && !quoted { value = fmt.Sprintf("%q", value) } msgValue := fieldMsg.New() err := protojson.Unmarshal([]byte(value), msgValue.Interface()) if err != nil { return nil, fmt.Errorf("unable to unmarshal field %q in message %q: %w", string(fieldDescriptor.Name()), string(message.Descriptor().FullName()), err) } v := protoreflect.ValueOfMessage(msgValue) return &v, nil } ================================================ FILE: util/genrest/resttools/populatefield_test.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resttools import ( "reflect" "testing" "time" "github.com/google/go-cmp/cmp" genprotopb "github.com/googleapis/gapic-showcase/server/genproto" "google.golang.org/protobuf/encoding/prototext" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/fieldmaskpb" "google.golang.org/protobuf/types/known/timestamppb" ) func TestParseWellKnownType(t *testing.T) { // TODO: Test the other well-known types as the Showcase API // starts incorporating them. for _, tst := range []struct { name string msg protoreflect.Message field protoreflect.Name value string want proto.Message }{ { "google.protobuf.FieldMask", (&genprotopb.UpdateUserRequest{}).ProtoReflect(), "update_mask", "foo,bar,baz", &fieldmaskpb.FieldMask{Paths: []string{"foo", "bar", "baz"}}, }, { "google.protobuf.Timestamp", (&genprotopb.User{}).ProtoReflect(), "create_time", "2023-03-21T12:01:02.000000003Z", timestamppb.New(time.Date(2023, 03, 21, 12, 1, 2, 3, time.UTC)), }, { "google.protobuf.Duration", (&genprotopb.Sequence_Response{}).ProtoReflect(), "delay", "5s", durationpb.New(5 * time.Second), }, { "google.protobuf.FieldMask", (&genprotopb.UpdateUserRequest{}).ProtoReflect(), "update_mask", "\"foo,bar,baz\"", &fieldmaskpb.FieldMask{Paths: []string{"foo", "bar", "baz"}}, }, } { fd := tst.msg.Descriptor().Fields().ByName(tst.field) gotp, err := parseWellKnownType(tst.msg, fd, tst.value) if err != nil { t.Errorf("parsing %q led to error %s", tst.value, err) continue } if gotp == nil { t.Errorf("expected non-nil value from parsing: %s", tst.value) continue } got := gotp.Message().Interface() if diff := cmp.Diff(got, tst.want, cmp.Comparer(proto.Equal)); diff != "" { t.Errorf("%s: got(-),want(+):\n%s", "FieldMask", diff) continue } } } func TestPopulateOneFieldError(t *testing.T) { for idx, testCase := range []struct { field string value string }{ // field path errors {".fString", "hi"}, {"fChild..fString", "hi"}, {"fChild.", "hi"}, {"fChild.x", "hi"}, {"fChild.x.fString", "hi"}, {"fChild.fString.fChild", "hi"}, {"fChild.fChild", "hi"}, // parsing errors {"fInt32", "hello"}, {"fSint32", "hello"}, {"fSfixed32", "hello"}, {"fInt32", "2147483648"}, // max int32 + 1 {"fSint32", "2147483648"}, // max int32 + 1 {"fSfixed32", "2147483648"}, // max int32 + 1 {"fInt32", "1.1"}, {"fSint32", "1.1"}, {"fSfixed32", "1.1"}, {"fUint32", "hello"}, {"fFixed32", "hello"}, {"fUint32", "4294967296"}, // max uint32 + 1 {"fFixed32", "4294967296"}, // max uint32 + 1 {"fUint32", "1.1"}, {"fFixed32", "1.1"}, {"fUint32", "-1"}, {"fFixed32", "-1"}, {"fInt64", "hello"}, {"fSint64", "hello"}, {"fSfixed64", "hello"}, {"fInt64", "9223372036854775808"}, // max int64 + 1 {"fSint64", "9223372036854775808"}, // max int64 + 1 {"fSfixed64", "9223372036854775808"}, // max int64 + 1 {"fInt64", "1.1"}, {"fSint64", "1.1"}, {"fSfixed64", "1.1"}, {"fUint64", "hello"}, {"fFixed64", "hello"}, {"fUint64", "18446744073709551616"}, // max uint64 + 1 {"fFixed64", "18446744073709551616"}, // max uint64 + 1 {"fUint64", "1.1"}, {"fFixed64", "1.1"}, {"fUint64", "-1"}, {"fFixed64", "-1"}, {"fFloat", "hello"}, {"fDouble", "hello"}, {"fFloat", "1e+39"}, // exponent too large {"fDouble", "1e+309"}, // exponent too large {"fBool", "hello"}, {"fBool", "13"}, // wrong casing {"f_string", "alphabet"}, {"f_int32", "1"}, {"f_sint32", "2"}, {"f_sfixed32", "3"}, {"f_uint32", "4"}, {"f_fixed32", "5"}, {"f_int64", "6"}, {"f_sint64", "7"}, {"f_sfixed64", "8"}, {"f_uint64", "9"}, {"f_fixed64", "10"}, {"f_float", "11"}, {"f_double", "12"}, {"f_bool", "true"}, {"f_bytes", "greetings"}, } { complianceData := &genprotopb.ComplianceData{} err := PopulateOneField(complianceData, testCase.field, []string{testCase.value}) if err == nil { t.Errorf("test case %d: did not get expected error for %q: %q", idx, testCase.field, testCase.value) } } } func TestPopulateSingularFields(t *testing.T) { for idx, testCase := range []struct { label string fields map[string]string expectError bool expectProtoText string }{ { label: "scalar datatypes", fields: map[string]string{ "fString": "alphabet", "fInt32": "2147483647", // max int32 "fSint32": "2147483647", // max int32 "fSfixed32": "2147483647", // max int32 "fUint32": "4294967295", // max uint32 "fFixed32": "4294967295", // max uint32 "fInt64": "9223372036854775807", // max int64 "fSint64": "9223372036854775807", // max int64 "fSfixed64": "9223372036854775807", // max int64 "fUint64": "18446744073709551615", // max uint64 "fFixed64": "18446744073709551615", // max uint64 "fFloat": "3.40282346638528859811704183484516925440e+38", // max float32 (https://golang.org/pkg/math/#pkg-constants) "fDouble": "1.797693134862315708145274237317043567981e+308", // max float64 "fBool": "true", "fBytes": "greetings", }, expectProtoText: `f_string:"alphabet" f_int32:2147483647 f_sint32:2147483647 f_sfixed32:2147483647 f_uint32:4294967295 f_fixed32:4294967295 f_int64:9223372036854775807 f_sint64:9223372036854775807 f_sfixed64:9223372036854775807 f_uint64:18446744073709551615 f_fixed64:18446744073709551615 f_double:1.7976931348623157e+308 f_float:3.4028235e+38 f_bool:true f_bytes:"greetings"`, }, { label: "nested messages", fields: map[string]string{ "fString": "alphabet", "fChild.fChild.fString": "lexicon", "fInt32": "5", "fChild.fChild.fDouble": "53.47", "fChild.fChild.fBool": "true", "fChild.fBool": "true", }, expectProtoText: `f_child:{f_child:{f_string:"lexicon" f_bool:true f_double:53.47} f_bool:true} f_string:"alphabet" f_int32:5`, }, { label: "presence/zero values", fields: map[string]string{ "fString": "", "fInt32": "0", "fSint32": "0", "fSfixed32": "0", "fUint32": "0", "fFixed32": "0", "fInt64": "0", "fSint64": "0", "fSfixed64": "0", "fUint64": "0", "fFixed64": "0", "fFloat": "0", "fDouble": "0", "fBool": "false", "fBytes": "", "pString": "", "pInt32": "0", "pDouble": "0", "pBool": "false", }, expectProtoText: `p_string:"" p_int32:0 p_double:0 p_bool:false`, }, { label: "presence/zero values in nested messages", fields: map[string]string{ "fChild.fString": "", "fChild.fFloat": "0", "fChild.fDouble": "0", "fChild.fBool": "false", "fChild.pString": "", "fChild.pFloat": "0", "fChild.pDouble": "0", "fChild.pBool": "false", "pChild.fString": "", "pChild.fFloat": "0", "pChild.fDouble": "0", "pChild.fBool": "false", "pChild.pString": "", "pChild.pFloat": "0", "pChild.pDouble": "0", "pChild.pBool": "false", "fChild.fChild.fString": "", "fChild.fChild.fDouble": "0", "fChild.fChild.fBool": "false", "fChild.pChild.fString": "", "fChild.pChild.fDouble": "0", "fChild.pChild.fBool": "false", "pChild.fChild.fString": "", "pChild.fChild.fDouble": "0", "pChild.fChild.fBool": "false", "pChild.pChild.fString": "", "pChild.pChild.fDouble": "0", "pChild.pChild.fBool": "false", }, expectProtoText: `f_child:{f_child:{} p_string:"" p_float:0 p_double:0 p_bool:false p_child:{}} p_child:{f_child:{} p_string:"" p_float:0 p_double:0 p_bool:false p_child:{}}`, }, { label: "default value only in nested message", fields: map[string]string{ "fChild.fString": "", }, expectProtoText: `f_child:{}`, }, { label: "default value only in optional nested message", fields: map[string]string{ "pChild.fString": "", }, expectProtoText: `p_child:{}`, }, } { complianceData := &genprotopb.ComplianceData{} err := PopulateSingularFields(complianceData, testCase.fields) if got, want := (err != nil), testCase.expectError; got != want { t.Errorf("test case %d[%q] error: got %v, want %v", idx, testCase.label, err, want) continue } if testCase.expectError { continue } var expectProto genprotopb.ComplianceData err = prototext.Unmarshal([]byte(testCase.expectProtoText), &expectProto) if err != nil { t.Errorf("test case %d[%q] unexpected error unmarshaling expected proto: %s", idx, testCase.label, err) continue } if got, want := complianceData, &expectProto; !reflect.DeepEqual(got, want) { gotText, err := prototext.Marshal(got) if err != nil { gotText = []byte("") } t.Errorf("test case %d[%q] proto:\n got: %s\n want: %s", idx, testCase.label, gotText, testCase.expectProtoText) } } } func TestPopulateFields(t *testing.T) { for idx, testCase := range []struct { label string fields map[string][]string expectError bool expectProtoText string }{ { label: "non-repeated fields", fields: map[string][]string{ "fString": []string{"alphabet"}, }, expectProtoText: `f_string:"alphabet"`, }, { label: "repeated fields", fields: map[string][]string{ "fString": []string{"alphabet", "lexicon"}, }, // TODO: Make Populate*Field*() work with repeated fields. expectError: true, }, } { complianceData := &genprotopb.ComplianceData{} err := PopulateFields(complianceData, testCase.fields) if got, want := (err != nil), testCase.expectError; got != want { t.Errorf("test case %d[%q] error: got %v, want %v", idx, testCase.label, err, want) continue } if testCase.expectError { continue } var expectProto genprotopb.ComplianceData err = prototext.Unmarshal([]byte(testCase.expectProtoText), &expectProto) if err != nil { t.Errorf("test case %d[%q] unexpected error unmarshaling expected proto: %s", idx, testCase.label, err) continue } if got, want := complianceData, &expectProto; !reflect.DeepEqual(got, want) { gotText, err := prototext.Marshal(got) if err != nil { gotText = []byte("") } t.Errorf("test case %d[%q] proto:\n got: %s\n want: %s", idx, testCase.label, gotText, testCase.expectProtoText) } } } func TestParseBool(t *testing.T) { for idx, testCase := range []struct { asString string expectValue bool expectError bool }{ {"true", true, false}, {"false", false, false}, {"True", false, true}, {"False", false, true}, {"0", false, true}, {"1", false, true}, } { val, err := parseBool(testCase.asString) if got, want := (err != nil), testCase.expectError; got != want { t.Errorf("test case %d[%q] error: got %v, want %v", idx, testCase.asString, err, want) continue } if got, want := val, testCase.expectValue; got != want { t.Errorf("test case %d[%q] got: %v, want: %v", idx, testCase.asString, got, want) } } } ================================================ FILE: util/genrest/resttools/server_streamer.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resttools import ( "bytes" "context" "fmt" "io" "net/http" "google.golang.org/grpc" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" ) const ServerStreamingChunkSize = 30 // ServerStreamer implements REST server streaming functionality that can be called by streaming // RPCs to stream their responses over HTTP/JSON. The messages are encoded such that once the stream // is finished, the total payload represents a properly formed JSON array of objects. In order to // ensure this, users must call the End() method to terminate the stream properly, typically by // using `defer`. type ServerStreamer struct { buffer bytes.Buffer // buffers the output to be chunked chunkSize int output io.Writer // receives the actual output, flushed after each chunk flusher http.Flusher // flushes the output to create the chunks marshaler *protojson.MarshalOptions started bool grpc.ServerStream } // NewServerStreamer returns a ServerStreamer instance initialized to write to responseWriter. Users // must call the End() method to terminate the stream properly, typically by using `defer`. Note // that responseWriter must also be an http.Flusher. If chunkSize is positive, messages written to // this ServerStreamer are chunked-encoded into chunks of size chunkSize (except for the final // chunk, which could be smaller). If chunkSize is zero, each message is written into a single // chunk. func NewServerStreamer(responseWriter io.Writer, chunkSize int) (*ServerStreamer, error) { if responseWriter == nil { return nil, fmt.Errorf("error: responseWriter provided is nil") } flusher, ok := responseWriter.(http.Flusher) if !ok { return nil, fmt.Errorf("error: responseWriter provided does not implement http.Flusher") } if chunkSize < 0 { return nil, fmt.Errorf("error: chunkSize must be non-negative") } streamer := &ServerStreamer{ chunkSize: chunkSize, output: responseWriter, flusher: flusher, marshaler: ToJSON(), } return streamer, nil } // Send sends a `message` over the REST stream using chunked-encoding according to the constructor // chunkSize parameter. func (streamer *ServerStreamer) Send(message proto.Message) error { json, err := streamer.marshaler.Marshal(message) if err != nil { return fmt.Errorf("error json-encoding message: %s", err.Error()) } return streamer.sendJSONArrayMessage(json) } // End terminates the REST stream by sending the trailing bytes (the closing bracket for the array). func (streamer *ServerStreamer) End() error { if !streamer.started { return nil } return streamer.sendAsChunks([]byte("]"), true) } // Context is needed to satisfy grpc.ServerStream. func (streamer *ServerStreamer) Context() context.Context { return context.Background() } // sendJSONArrayMessage buffers `message` and then flushes as appropriate so that the chunks written // to streamer.output are of size streamer.chunkSize. Each `message` is assumed to be a JSON object // delimited by curly braces, inasmuch as `message`s are separated by commas, the first `message` is // preceded by an opening square bracket, and End() will send the final closing square // bracket. Empty `messages` do not get written. func (streamer *ServerStreamer) sendJSONArrayMessage(message []byte) error { if len(message) == 0 { return nil } var prefix []byte switch streamer.started { case false: prefix = []byte("[") streamer.started = true case true: prefix = []byte(",") } return streamer.sendAsChunks(append(prefix, message...), false) } // sendAsChunks writes `content` to streamer.output and flushes streamer.output so that each flushed // chunk is of size streamer.chunkSize. If streamer.chunkSize is 0, all of `content` (and any // previous contents of streamer.buffer) is flushed as a single chunk. If forceFlush is true, this // function ensures all bytes in `content` are flushed, even if that results in a trailing chunk of // size less than streamer.chunkSize. func (streamer *ServerStreamer) sendAsChunks(content []byte, forceFlush bool) error { // we're writing in two places below, so we define a local function for conciseness. writeOneChunk := func(data []byte) error { if _, err := streamer.output.Write(data); err != nil { return fmt.Errorf("error writing streamed http chunk: %s\n chunk: %q", err.Error(), string(data)) } // Flush() causes the chunk to be sent immediately, and chunked transfer encoding to // be set in the HTTP headers before the first chunk. // cf. https://stackoverflow.com/a/30603654 streamer.flusher.Flush() return nil } if _, err := streamer.buffer.Write(content); err != nil { return err } if streamer.chunkSize > 0 { for streamer.buffer.Len() >= streamer.chunkSize { if err := writeOneChunk(streamer.buffer.Next(streamer.chunkSize)); err != nil { return err } } if streamer.buffer.Len() == 0 { // reuse memory when possible streamer.buffer.Reset() } } if streamer.chunkSize <= 0 || forceFlush { if err := writeOneChunk(streamer.buffer.Bytes()); err != nil { return err } streamer.buffer.Reset() } return nil } ================================================ FILE: util/genrest/resttools/server_streamer_test.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resttools import ( "bytes" "fmt" "reflect" "testing" ) type wireBuffer struct { bytes.Buffer chunks []string } func (wb *wireBuffer) Flush() { wb.chunks = append(wb.chunks, wb.String()) wb.Reset() } func TestServerStreamer(t *testing.T) { for idx, testCase := range []struct { name string messages []string expectedPerMessageChunks []string chunkSize int expectedFixedSizeChunks []string }{ { name: "Single chunk", messages: []string{"greetings"}, expectedPerMessageChunks: []string{ "[greetings", "]", }, chunkSize: 4, expectedFixedSizeChunks: []string{ "[gre", "etin", "gs]", }, }, { name: "Two chunks", messages: []string{"greetings", " earthling"}, expectedPerMessageChunks: []string{ "[greetings", ", earthling", "]", }, chunkSize: 5, expectedFixedSizeChunks: []string{ "[gree", "tings", ", ea", "rthli", "ng]", }, }, { name: "Many chunks", messages: []string{"greetings", " people", "of ", "Earth"}, expectedPerMessageChunks: []string{ "[greetings", ", people", ",of ", ",Earth", "]", }, chunkSize: 4, expectedFixedSizeChunks: []string{ "[gre", "etin", "gs, ", " peo", "ple,", "of ,", "Eart", "h]", }, }, { name: "No chunks", messages: []string{}, expectedPerMessageChunks: nil, chunkSize: 3, expectedFixedSizeChunks: nil, }, { name: "Single empty chunk", messages: []string{""}, expectedPerMessageChunks: nil, chunkSize: 3, expectedFixedSizeChunks: nil, }, { name: "Intermediate empty chunk", messages: []string{"greetings", "", "earthlings"}, expectedPerMessageChunks: []string{ "[greetings", ",earthlings", "]", }, chunkSize: 4, expectedFixedSizeChunks: []string{ "[gre", "etin", "gs,e", "arth", "ling", "s]", }, }, } { label := fmt.Sprintf("[%d:%s:per-message chunks]", idx, testCase.name) streamWithChunkSize(t, label, 0, testCase.messages, testCase.expectedPerMessageChunks) label = fmt.Sprintf("[%d:%s: chunk size %d]", idx, testCase.name, testCase.chunkSize) streamWithChunkSize(t, label, testCase.chunkSize, testCase.messages, testCase.expectedFixedSizeChunks) } } func streamWithChunkSize(t *testing.T, label string, chunkSize int, messages, expectedChunks []string) { wire := &wireBuffer{} streamer, err := NewServerStreamer(wire, chunkSize) if err != nil { t.Fatalf("%s: could not construct ServerStreamer: %s", label, err) } for msgIdx, msg := range messages { if err := streamer.sendJSONArrayMessage([]byte(msg)); err != nil { t.Errorf("%s: error sending message #%d (%q): %s", label, msgIdx, msg, err) break } } if err := streamer.End(); err != nil { t.Errorf("%s: error ending stream: %s", label, err) } if got, want := wire.chunks, expectedChunks; !reflect.DeepEqual(got, want) { t.Errorf("%s: did not received expected chunks\n== got ===\n%#v\n== want ==\n%#v\n", label, got, want) } } ================================================ FILE: util/genrest/resttools/systemparam.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resttools import ( "fmt" "net/http" "net/url" "strings" ) // SystemParameters encapsulates the system parameters recognized by Showcase. These are a subset of // Google's accepted system parameters described in // https://cloud.google.com/apis/docs/system-parameters. type SystemParameters struct { EnumEncodingAsInt bool APIVersion string } // GetSystemParameters returns the SystemParameters encoded in request, and the query parameters in // the request's query string that are not themselves system parameters. func GetSystemParameters(request *http.Request) (systemParams *SystemParameters, queryParams map[string][]string, err error) { return processQueryString(request.URL.RawQuery) } // processQueryString returns the SystemParameters encoded in queryString, and the query parameters in // queryString that are not themselves system parameters. // // Since we want GAPICs to be strict in what they emit, and Showcase helps guarantee that, this // function is strict in what it accepts: // - no more than one instance of the $alt system parameter // - $alt may be appear as "$alt" or "alt", always lower case // - the only possible values for $alt are "json" or "json;enum-encoding=int"; again, lower case // - the semicolon in "json;enum-encoding=int" must be URL escaped as "%3B" or "%3b" // - the equal sign in "json;enum-encoding=int" may or may not be URL-escaped func processQueryString(queryString string) (systemParams *SystemParameters, queryParams map[string][]string, err error) { // We parse the raw query string manually rather than relying on request.URL.Query() so that // we can error out in the case of malformed strings (e.g. unencoded ampersands), rather // than having them ignored with potentially incorrect results. queryPairs, err := url.ParseQuery(queryString) if err != nil { return nil, nil, err } // TODO: Try removing this workaround when we update the Go version in the Showcase CI to // 1.17+. As of this writing, CI uses 1.16.3, and the tests fail // (https://github.com/googleapis/gapic-showcase/runs/6798834903?check_suite_focus=true#step:6:60) // without this explicit check. The tests pass without this workaround on local machines or in the Go // Playground (https://go.dev/play/p/ewyv5qj55an) using Go >=1.17 if strings.Contains(queryString, ";") { return nil, nil, fmt.Errorf("found unescaped semicolon in query string %q", queryString) } queryParams = map[string][]string(queryPairs) systemParams = &SystemParameters{} sawAltParam := false for param, values := range queryPairs { switch param { case "alt", "$alt": for _, val := range values { if sawAltParam { return systemParams, queryParams, fmt.Errorf("multiple instances of $alt system parameter") } switch val { case "json": // no op case "json;enum-encoding=int": // already URL-decoded systemParams.EnumEncodingAsInt = true default: return systemParams, queryParams, fmt.Errorf("unhandled value %q for system parameter %q", val, param) } } delete(queryParams, param) sawAltParam = true case "apiVersion", "$apiVersion": for _, val := range values { if systemParams.APIVersion != "" { return systemParams, queryParams, fmt.Errorf("multiple instances of $apiVersion system parameter") } systemParams.APIVersion = val } delete(queryParams, param) } } return systemParams, queryParams, nil } ================================================ FILE: util/genrest/resttools/systemparam_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package resttools import ( "fmt" "testing" "github.com/google/go-cmp/cmp" ) func TestProcessQueryString(t *testing.T) { for idx, testCase := range []struct { queryString string wantSystem *SystemParameters wantParams map[string][]string wantError bool }{ {queryString: ""}, { queryString: "foo=bar", wantParams: map[string][]string{ "foo": {"bar"}, }, }, { queryString: "$foo=bar", wantParams: map[string][]string{ "$foo": {"bar"}, }, }, { queryString: "%24foo=bar", wantParams: map[string][]string{ "$foo": {"bar"}, }, }, { queryString: "foo%3Dbar", wantParams: map[string][]string{ "foo=bar": {""}, }, }, { queryString: "foo%3Dbar=xyz", wantParams: map[string][]string{ "foo=bar": {"xyz"}, }, }, { queryString: "%24foo%3Dbar", wantParams: map[string][]string{ "$foo=bar": {""}, }, }, { queryString: "%24foo%3Dbar=xyz", wantParams: map[string][]string{ "$foo=bar": {"xyz"}, }, }, // system param incorrect { queryString: "%24alt%3Djson", wantParams: map[string][]string{ "$alt=json": {""}, }, }, { queryString: "$ALT=JSON", wantParams: map[string][]string{ "$ALT": {"JSON"}, }, }, { queryString: "%24ALT=JSON", wantParams: map[string][]string{ "$ALT": {"JSON"}, }, }, // system param by itself {queryString: "alt=json"}, {queryString: "$alt=json"}, {queryString: "%24alt=json"}, { queryString: "alt=json%3Benum-encoding=int", wantSystem: &SystemParameters{EnumEncodingAsInt: true}, }, { queryString: "$alt=json%3Benum-encoding=int", wantSystem: &SystemParameters{EnumEncodingAsInt: true}, }, { queryString: "%24alt=json%3Benum-encoding=int", wantSystem: &SystemParameters{EnumEncodingAsInt: true}, }, { queryString: "alt=json%3Benum-encoding%3Dint", wantSystem: &SystemParameters{EnumEncodingAsInt: true}, }, { queryString: "$alt=json%3Benum-encoding%3Dint", wantSystem: &SystemParameters{EnumEncodingAsInt: true}, }, { queryString: "%24alt=json%3Benum-encoding%3Dint", wantSystem: &SystemParameters{EnumEncodingAsInt: true}, }, // system param+query params in front { queryString: "foo=bar&alt=json", wantParams: map[string][]string{ "foo": {"bar"}, }, }, { queryString: "foo=bar&$alt=json", wantParams: map[string][]string{ "foo": {"bar"}, }, }, { queryString: "foo=bar&%24alt=json", wantParams: map[string][]string{ "foo": {"bar"}, }, }, { queryString: "foo=bar&alt=json%3Benum-encoding=int", wantSystem: &SystemParameters{EnumEncodingAsInt: true}, wantParams: map[string][]string{ "foo": {"bar"}, }, }, { queryString: "foo=bar&$alt=json%3Benum-encoding=int", wantSystem: &SystemParameters{EnumEncodingAsInt: true}, wantParams: map[string][]string{ "foo": {"bar"}, }, }, { queryString: "foo=bar&%24alt=json%3Benum-encoding=int", wantSystem: &SystemParameters{EnumEncodingAsInt: true}, wantParams: map[string][]string{ "foo": {"bar"}, }, }, // system param+query params in rear { queryString: "alt=json&foo=bar", wantParams: map[string][]string{ "foo": {"bar"}, }, }, { queryString: "$alt=json&foo=bar", wantParams: map[string][]string{ "foo": {"bar"}, }, }, { queryString: "%24alt=json&foo=bar", wantParams: map[string][]string{ "foo": {"bar"}, }, }, { queryString: "alt=json%3Benum-encoding=int&foo=bar", wantSystem: &SystemParameters{EnumEncodingAsInt: true}, wantParams: map[string][]string{ "foo": {"bar"}, }, }, { queryString: "$alt=json%3Benum-encoding=int&foo=bar", wantSystem: &SystemParameters{EnumEncodingAsInt: true}, wantParams: map[string][]string{ "foo": {"bar"}, }, }, { queryString: "%24alt=json%3Benum-encoding=int&foo=bar", wantSystem: &SystemParameters{EnumEncodingAsInt: true}, wantParams: map[string][]string{ "foo": {"bar"}, }, }, { queryString: "$apiVersion=v7_20260210", wantSystem: &SystemParameters{APIVersion: "v7_20260210"}, wantParams: map[string][]string{}, }, { queryString: "alt=json%3Benum-encoding=int&apiVersion=v7_20260210", wantSystem: &SystemParameters{ APIVersion: "v7_20260210", EnumEncodingAsInt: true, }, wantParams: map[string][]string{}, }, { queryString: "alt=json%3Benum-encoding=int&apiVersion=v7_20260210&foo=bar", wantSystem: &SystemParameters{ APIVersion: "v7_20260210", EnumEncodingAsInt: true, }, wantParams: map[string][]string{ "foo": []string{"bar"}, }, }, // system param errors { queryString: "$alt=foo", wantError: true, }, { queryString: "$alt", wantError: true, }, { queryString: "$alt=JSON", wantError: true, }, { queryString: "$alt=json%3Benum-encoding=string", wantError: true, }, { queryString: "$alt=json;enum-encoding=int", // unencoded semicolon wantError: true, }, { queryString: "$alt=json%3Benum-encoding=INT", wantError: true, }, { queryString: "foo&$alt=json&bar&alt=json", // repeated wantError: true, }, { queryString: "$apiVersion=v8&apiVersion=v9", // repeated wantError: true, }, } { t.Run(fmt.Sprintf("[%2d %q]", idx, testCase.queryString), func(t *testing.T) { systemParams, queryParams, err := processQueryString(testCase.queryString) if got, want := (err != nil), testCase.wantError; got != want { t.Errorf("error condition not met: want error: %v, got error:%v", testCase.wantError, err) } if err != nil { return } wantParams := testCase.wantParams if wantParams == nil { wantParams = map[string][]string{} } if diff := cmp.Diff(queryParams, wantParams); diff != "" { t.Errorf("query params mismatch (+want, -got):\n%s", diff) } wantSystem := testCase.wantSystem if wantSystem == nil { wantSystem = &SystemParameters{} } if diff := cmp.Diff(systemParams, wantSystem); diff != "" { t.Errorf("system params mismatch (+want, -got):\n%s", diff) } }) } } ================================================ FILE: util/genrest/testdata/TestConstructServerStreamer.go.baseline ================================================ // Catalog_StreamAuthorsServer implements catalogpb.Catalog_StreamAuthorsServer to provide server-side streaming over REST, returning all the // individual responses as part of a long JSON list. type Catalog_StreamAuthorsServer struct{ *resttools.ServerStreamer } // Send accumulates a response to be fetched later as part of response list returned over REST. func (streamer *Catalog_StreamAuthorsServer) Send(response *responsepb.AuthorEntry) error { return streamer.ServerStreamer.Send(response) } // Catalog_StreamTitlesServer implements catalogpb.Catalog_StreamTitlesServer to provide server-side streaming over REST, returning all the // individual responses as part of a long JSON list. type Catalog_StreamTitlesServer struct{ *resttools.ServerStreamer } // Send accumulates a response to be fetched later as part of response list returned over REST. func (streamer *Catalog_StreamTitlesServer) Send(response *responsepb.TitleEntry) error { return streamer.ServerStreamer.Send(response) } // Media_StreamAudioServer implements mediapb.Media_StreamAudioServer to provide server-side streaming over REST, returning all the // individual responses as part of a long JSON list. type Media_StreamAudioServer struct{ *resttools.ServerStreamer } // Send accumulates a response to be fetched later as part of response list returned over REST. func (streamer *Media_StreamAudioServer) Send(response *responsepb.AudioEntry) error { return streamer.ServerStreamer.Send(response) } // Media_StreamVideoServer implements mediapb.Media_StreamVideoServer to provide server-side streaming over REST, returning all the // individual responses as part of a long JSON list. type Media_StreamVideoServer struct{ *resttools.ServerStreamer } // Send accumulates a response to be fetched later as part of response list returned over REST. func (streamer *Media_StreamVideoServer) Send(response *responsepb.VideoEntry) error { return streamer.ServerStreamer.Send(response) } ================================================ FILE: version.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package version import ( _ "embed" ) // Version contains the current version of this project, as declared in the // version.txt file, for its tools to reference. // //go:embed version.txt var Version string ================================================ FILE: version.txt ================================================ 0.39.0