Skip to content

Commit

Permalink
Merge pull request #749 from danistrebel/feat/grpc-http-gateway-gener…
Browse files Browse the repository at this point in the history
…ator

Feat/grpc http gateway generator
  • Loading branch information
danistrebel authored Jul 8, 2024
2 parents 4665629 + 829ee4a commit 6e7a1cb
Show file tree
Hide file tree
Showing 23 changed files with 798 additions and 4 deletions.
5 changes: 3 additions & 2 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@
/tools/apigee-x-trial-provision @yuriylesyuk @danistrebel
/tools/decrypt-hybrid-assets @yuriylesyuk
/tools/endpoints-oas-importer @danistrebel
/tools/grpc-http-gateway-generator @danistrebel @omidtahouri
/tools/hybrid-quickstart @danistrebel
/tools/oas-apigee-mock @markjkelly
/tools/pipeline-linter @seymen @danistrebel
/tools/pipeline-runner @seymen @danistrebel
/tools/sf-dependency-list @yuriylesyuk
/tools/proxy-endpoint-unifier @anaik91
/tools/target-server-validator @anaik91
/tools/sf-dependency-list @yuriylesyuk
/tools/target-server-validator @anaik91
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ Apigee products.
A tool to unify/split proxy endpoints based on API basepath.
- [Apigee Target Server Validator](tools/target-server-validator) -
A tool to validate all targets in Target Servers & Apigee API Proxy Bundles.

- [gRPC to HTTP Gateway Generator](tools/grpc-http-gateway-generator) -
Generate gateways to expose gRPC services with HTTP API management.
## Labs

This folder contains raw assets used to generate content to teach a particular
Expand Down
76 changes: 76 additions & 0 deletions tools/grpc-http-gateway-generator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# gRPC to HTTP Gateway Generator

The purpose of this tool is to generate a gRPC to HTTP gateway based on a protocol buffer.
It leverages the [gRPC Gateway](https://github.com/grpc-ecosystem/grpc-gateway) project to generate the gateway code.

The generated gRPC gateway can then be used to create HTTP adapters for gRPC services and use them in a classical HTTP REST-based API management environment.

![Architecture Overview](./img/architecture.png)

## Prerequisites

The generator assumed you have the protobuf compiler `protoc` installed.

Note that `protoc` is pre-installed on Cloud Shell.

To install `protoc` with `apt`, run the following command:

```sh
apt install -y protobuf-compiler
```

## Generate the Gateway Code

The gateway is generated based on a protocol buffer file that you supply with the `--proto-path` flag:

```sh
./generate-gateway.sh --proto-path ./examples/currency.proto
```

Optionally you can also specify the desired output directory with the `--output` flag. If no output directory is specified the output will be generated in the `./generated/gateway` folder.

## Run the Gateway

You can run the gateway locally with the following commands and point to a gRPC server endpoint that runs on localhost port 9090:

```sh
(cd generated/gateway && go run main.go --grpc-server-endpoint localhost:9090)
```

If you preffer to run the gateway as a container use the following commands to build and run the gateway container:

```sh
(cd generated/gateway && docker build . -t gateway:latest)
docker run -p 8080:8080 -e GRPC_SERVER_ENDPOINT=localhost:9090 gateway:latest
```

## Try it out locally

With the gateway running you can call the automatically generated API endpoints of the gateway to consume your gRPC service.

With the gRPC Gateway pointing to an exposed currency service of the [microservice demo](https://github.com/GoogleCloudPlatform/microservices-demo) the currency conversion request would look like this:

```sh
curl -X POST localhost:8080/hipstershop.CurrencyService/Convert -d '{"from": {"units": 3, "currency_code": "USD", "nanos": 0}, "to_code": "CHF"}'
```

Whist the code to request supported currencies looks like this:

```sh
curl -X POST localhost:8080/hipstershop.CurrencyService/GetSupportedCurrencies
```

Note that the automatically generated API doesn't yet come in a RESTful format. This is one of the aspects that can be changed in an API management layer to improve the overall usability and security of the API.

### Deploy to Cloud Run

Once we've tested the gateway locally we can deploy it to Cloud Run for production use.

```sh
(cd generated/gateway && gcloud run deploy currency-grpc-gw --source . --allow-unauthenticated --region europe-west1 --project $PROJECT_ID)
```

## Expose the Cloud Run Service via Apigee

With the Gateway running in Cloud Run we can now expose it via Apigee.
For detailed instructions on how to expose a cloud run service in Apigee please see [this reference implementation](https://github.com/apigee/devrel/tree/main/references/cloud-run).
24 changes: 24 additions & 0 deletions tools/grpc-http-gateway-generator/buf.gen.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

version: v1
plugins:
- plugin: go
out: gen/go
opt:
- paths=source_relative
- plugin: go-grpc
out: gen/go
opt:
- paths=source_relative
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
Copyright 2024 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<APIProxy revision="1" name="currency-v1">
</APIProxy>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!--
Copyright 2024 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<AssignMessage name="AM.SetConversionPath">
<AssignVariable>
<Name>flow.target.pathsuffix</Name>
<Value>/hipstershop.CurrencyService/Convert</Value>
</AssignVariable>
</AssignMessage>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!--
Copyright 2024 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<AssignMessage name="AM.SetCurrenciesPath">
<AssignVariable>
<Name>flow.target.pathsuffix</Name>
<Value>/hipstershop.CurrencyService/GetSupportedCurrencies</Value>
</AssignVariable>
</AssignMessage>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!--
Copyright 2024 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<HTTPModifier continueOnError="false" enabled="true" name="HM.SetTargetMethod">
<Set>
<Verb>POST</Verb>
</Set>
</HTTPModifier>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!--
Copyright 2024 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<Javascript timeLimit="200" name="JS.SetTargetPath">
<ResourceURL>jsc://set-target-path.js</ResourceURL>
</Javascript>
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<!--
Copyright 2024 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<ProxyEndpoint name="default">
<Flows>
<Flow>
<Condition>request.verb = "GET" and proxy.pathsuffix = "/currencies"</Condition>
<Request>
<Step>
<Name>AM.SetCurrenciesPath</Name>
</Step>
</Request>
</Flow>
<Flow>
<Condition>request.verb = "POST" and proxy.pathsuffix = "/convert"</Condition>
<Request>
<Step>
<Name>AM.SetConversionPath</Name>
</Step>
</Request>
</Flow>
</Flows>
<PostFlow>
<Request>
<Step>
<Name>HM.SetTargetMethod</Name>
</Step>
</Request>
</PostFlow>
<HTTPProxyConnection>
<BasePath>/currency/v1</BasePath>
</HTTPProxyConnection>
<RouteRule name="default">
<TargetEndpoint>default</TargetEndpoint>
</RouteRule>
</ProxyEndpoint>
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
Copyright 2024 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

context.setVariable("target.copy.pathsuffix", false)

var existingTargetUrl = context.getVariable("target.url");
var targetPath = context.getVariable("flow.target.pathsuffix") || ""; // retrieve custom path, set by AM policies
var queryString = context.getVariable("request.querystring") || "";

var updatedTargetUrl = existingTargetUrl + targetPath + (queryString ? "?"+queryString : "");

context.setVariable("target.url",
existingTargetUrl + // use target base URL
targetPath + // append custom path
(queryString ? "?"+queryString : "") // conditionally append query params
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<!--
Copyright 2024 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<TargetEndpoint name="default">
<PreFlow>
<Request>
<Step>
<Name>JS.SetTargetPath</Name>
</Step>
</Request>
</PreFlow>
<HTTPTargetConnection>
<Authentication>
<GoogleIDToken>
<Audience>CLOUD_RUN_URL</Audience>
</GoogleIDToken>
</Authentication>
<URL>CLOUD_RUN_URL</URL>
</HTTPTargetConnection>
</TargetEndpoint>
Loading

0 comments on commit 6e7a1cb

Please sign in to comment.