# Configure gRPC Proxying

API7 Enterprise supports proxying gRPC traffic, allowing you to manage gRPC services with the same traffic management, security, and observability features as your HTTP services. You can also transcode RESTful HTTP requests to gRPC and enable gRPC-Web support for browser-based clients.

## Prerequisites[​](#prerequisites "Direct link to Prerequisites")

* An API7 Enterprise instance is running.
* A Gateway Group is created and a Gateway instance is running.
* A [token from the Dashboard](https://docs.api7.ai/api7-gateway/reference/obtain-dashboard-token.md).
* [Docker](https://docs.docker.com/get-docker/) is installed where the sample upstream will run.
* [`grpcurl`](https://github.com/fullstorydev/grpcurl) is installed for native gRPC verification.
* [ADC is installed and connected](https://docs.api7.ai/api7-gateway/getting-started/quick-start.md#step-3-create-a-service-and-route) to the target Gateway Group if you use the ADC configurations.

## Start a Sample gRPC Server[​](#start-a-sample-grpc-server "Direct link to Start a Sample gRPC Server")

Set `GATEWAY_CONTAINER` to the running API7 Gateway container. Create a dedicated network and connect the gateway to it:

```
export GATEWAY_CONTAINER=replace-with-gateway-container-name



docker network create gateway-grpc-net

docker network connect gateway-grpc-net "$GATEWAY_CONTAINER"
```

Start the maintained sample gRPC server on the shared network:

```
docker run -d \

  --name grpc-service \

  --network gateway-grpc-net \

  -p 50051:50051 \

  api7/grpc-server-example:1.0.2
```

Download the matching protocol definition:

```
curl -fLo helloworld.proto \

  "https://raw.githubusercontent.com/api7/grpc_server_example/release/1.0.2/proto/helloworld.proto"
```

The server exposes the `helloworld.Greeter` service and the `SayHello` method. Verify the upstream directly:

```
grpcurl -plaintext \

  -proto helloworld.proto \

  -d '{"name":"API7"}' \

  127.0.0.1:50051 \

  helloworld.Greeter.SayHello
```

For a non-Docker gateway deployment, run the sample server where the gateway can reach it and replace `grpc-service` in the upstream configurations with that address.

## Enable an HTTP/2 Listener for Native gRPC[​](#enable-an-http2-listener-for-native-grpc "Direct link to Enable an HTTP/2 Listener for Native gRPC")

Native gRPC clients require an HTTP/2 listener that they can reach. REST-to-gRPC and gRPC-Web clients can use the normal HTTP listener because the gateway translates those requests before calling the native gRPC upstream.

Expose an additional listener, such as port `9081`, from the gateway deployment. In the complete `config.yaml` used by the deployment, preserve the existing settings and add the listeners:

config.yaml

```
apisix:

  node_listen:

    - port: 9080

    - port: 9081

      enable_http2: true
```

Restart or recreate the gateway through its normal deployment workflow, then use port `9081` for native gRPC validation.

Recreating a Docker gateway removes the manual network attachment created earlier. Set `GATEWAY_CONTAINER` to the new container name and reconnect it before continuing:

```
export GATEWAY_CONTAINER=replace-with-recreated-gateway-container-name

docker network connect gateway-grpc-net "$GATEWAY_CONTAINER"
```

## Configure Admin API Access[​](#configure-admin-api-access "Direct link to Configure Admin API Access")

The Admin API examples use a Dashboard token. Export the token and replace `{gateway_group_id}` with the target Gateway Group ID in each request URL. The quickstart Gateway Group uses `default`.

```
export API_KEY=replace-with-dashboard-token
```

## Proxy Native gRPC[​](#proxy-native-grpc "Direct link to Proxy Native gRPC")

Create a Service with the `grpc` scheme and a Route that points to it. Use the `grpcs` scheme instead when the upstream accepts gRPC over TLS.

* Admin API
* ADC

Create the Service:

```
curl -k "https://localhost:7443/apisix/admin/services/grpc-native-service?gateway_group_id={gateway_group_id}" -X PUT \

  -H "X-API-KEY: ${API_KEY}" \

  -H "Content-Type: application/json" \

  -d '{

    "name": "grpc-native-service",

    "upstream": {

      "type": "roundrobin",

      "scheme": "grpc",

      "nodes": [

        {

          "host": "grpc-service",

          "port": 50051,

          "weight": 100

        }

      ]

    }

  }'
```

Create the Route:

```
curl -k "https://localhost:7443/apisix/admin/routes/grpc-native-route?gateway_group_id={gateway_group_id}" -X PUT \

  -H "X-API-KEY: ${API_KEY}" \

  -H "Content-Type: application/json" \

  -d '{

    "name": "grpc-native-route",

    "methods": ["POST"],

    "paths": ["/helloworld.Greeter/SayHello"],

    "service_id": "grpc-native-service"

  }'
```

Create the Service and Route:

adc.yaml

```
services:

  - name: grpc-native-service

    labels:

      docs-example: grpc-native

    upstream:

      scheme: grpc

      type: roundrobin

      nodes:

        - host: grpc-service

          port: 50051

          weight: 100

    routes:

      - name: grpc-native-route

        uris:

          - /helloworld.Greeter/SayHello

        methods:

          - POST
```

Preview changes owned by this example and confirm that the diff contains no unintended updates or deletions:

```
adc diff -f adc.yaml \

  --include-resource-type service \

  --label-selector docs-example=grpc-native
```

Synchronize the reviewed service configuration:

```
adc sync -f adc.yaml \

  --include-resource-type service \

  --label-selector docs-example=grpc-native
```

Send a native gRPC request through the HTTP/2 listener:

```
grpcurl -plaintext \

  -proto helloworld.proto \

  -d '{"name":"API7"}' \

  127.0.0.1:9081 \

  helloworld.Greeter.SayHello
```

The response should contain:

```
{

  "message": "Hello API7"

}
```

## Configure REST-to-gRPC Transcoding[​](#configure-rest-to-grpc-transcoding "Direct link to Configure REST-to-gRPC Transcoding")

The [`grpc-transcode`](https://docs.api7.ai/hub/grpc-transcode.md) plugin exposes a gRPC method to HTTP clients and converts between JSON and Protocol Buffers.

### Upload the Proto Definition[​](#upload-the-proto-definition "Direct link to Upload the Proto Definition")

Proto resources must be created through the Admin API. Install [`jq`](https://jqlang.org/download/) to encode the downloaded file as the request body:

```
jq -Rs '{content: .}' helloworld.proto | \

  curl -k "https://localhost:7443/apisix/admin/protos/helloworld-proto?gateway_group_id={gateway_group_id}" -X PUT \

    -H "X-API-KEY: ${API_KEY}" \

    -H "Content-Type: application/json" \

    -d @-
```

### Configure the Transcoding Route[​](#configure-the-transcoding-route "Direct link to Configure the Transcoding Route")

Create a separate Service and Route for the transcoding example:

* Admin API
* ADC

Create the Service:

```
curl -k "https://localhost:7443/apisix/admin/services/grpc-transcode-service?gateway_group_id={gateway_group_id}" -X PUT \

  -H "X-API-KEY: ${API_KEY}" \

  -H "Content-Type: application/json" \

  -d '{

    "name": "grpc-transcode-service",

    "upstream": {

      "type": "roundrobin",

      "scheme": "grpc",

      "nodes": [

        {

          "host": "grpc-service",

          "port": 50051,

          "weight": 100

        }

      ]

    }

  }'
```

Create the Route:

```
curl -k "https://localhost:7443/apisix/admin/routes/grpc-transcode-route?gateway_group_id={gateway_group_id}" -X PUT \

  -H "X-API-KEY: ${API_KEY}" \

  -H "Content-Type: application/json" \

  -d '{

    "name": "grpc-transcode-route",

    "methods": ["POST"],

    "paths": ["/hello"],

    "service_id": "grpc-transcode-service",

    "plugins": {

      "grpc-transcode": {

        "proto_id": "helloworld-proto",

        "service": "helloworld.Greeter",

        "method": "SayHello"

      }

    }

  }'
```

ADC cannot create proto resources. Run the Admin API proto command above before synchronizing this Service and Route.

Create the Service and Route:

adc.yaml

```
services:

  - name: grpc-transcode-service

    labels:

      docs-example: grpc-transcode

    upstream:

      scheme: grpc

      type: roundrobin

      nodes:

        - host: grpc-service

          port: 50051

          weight: 100

    routes:

      - name: grpc-transcode-route

        uris:

          - /hello

        methods:

          - POST

        plugins:

          grpc-transcode:

            _state: enabled

            proto_id: helloworld-proto

            service: helloworld.Greeter

            method: SayHello
```

Preview changes owned by this example and confirm that the diff contains no unintended updates or deletions:

```
adc diff -f adc.yaml \

  --include-resource-type service \

  --label-selector docs-example=grpc-transcode
```

Synchronize the reviewed service configuration:

```
adc sync -f adc.yaml \

  --include-resource-type service \

  --label-selector docs-example=grpc-transcode
```

Send an HTTP request to the transcoding route:

```
curl "http://127.0.0.1:9080/hello" -X POST \

  -H "Content-Type: application/json" \

  -d '{"name":"API7"}'
```

The gateway should return the decoded gRPC response:

```
{

  "items": [],

  "message": "Hello API7",

  "gender": "GENDER_UNKNOWN"

}
```

## Configure gRPC-Web[​](#configure-grpc-web "Direct link to Configure gRPC-Web")

The [`grpc-web`](https://docs.api7.ai/hub/grpc-web.md) plugin lets browser clients call a native gRPC upstream. Create a separate Service and Route for browser traffic. The browser client runs on a different port, so the Route must accept both `POST` requests and `OPTIONS` preflight requests.

* Admin API
* ADC

Create the Service:

```
curl -k "https://localhost:7443/apisix/admin/services/grpc-web-service?gateway_group_id={gateway_group_id}" -X PUT \

  -H "X-API-KEY: ${API_KEY}" \

  -H "Content-Type: application/json" \

  -d '{

    "name": "grpc-web-service",

    "upstream": {

      "type": "roundrobin",

      "scheme": "grpc",

      "nodes": [

        {

          "host": "grpc-service",

          "port": 50051,

          "weight": 100

        }

      ]

    }

  }'
```

Create the Route:

```
curl -k "https://localhost:7443/apisix/admin/routes/grpc-web-route?gateway_group_id={gateway_group_id}" -X PUT \

  -H "X-API-KEY: ${API_KEY}" \

  -H "Content-Type: application/json" \

  -d '{

    "name": "grpc-web-route",

    "methods": ["POST", "OPTIONS"],

    "paths": ["/grpc-web/*"],

    "service_id": "grpc-web-service",

    "plugins": {

      "grpc-web": {

        "cors_allow_headers": "content-type,x-grpc-web,x-user-agent"

      }

    }

  }'
```

Create the Service and Route:

adc.yaml

```
services:

  - name: grpc-web-service

    labels:

      docs-example: grpc-web

    upstream:

      scheme: grpc

      type: roundrobin

      nodes:

        - host: grpc-service

          port: 50051

          weight: 100

    routes:

      - name: grpc-web-route

        uris:

          - /grpc-web/*

        methods:

          - POST

          - OPTIONS

        plugins:

          grpc-web:

            _state: enabled

            cors_allow_headers: "content-type,x-grpc-web,x-user-agent"
```

Preview changes owned by this example and confirm that the diff contains no unintended updates or deletions:

```
adc diff -f adc.yaml \

  --include-resource-type service \

  --label-selector docs-example=grpc-web
```

Synchronize the reviewed service configuration:

```
adc sync -f adc.yaml \

  --include-resource-type service \

  --label-selector docs-example=grpc-web
```

### Create a Browser Client[​](#create-a-browser-client "Direct link to Create a Browser Client")

Install [Node.js](https://nodejs.org/), the [Protocol Buffers compiler](https://protobuf.dev/installation/), and [`protoc-gen-grpc-web`](https://github.com/grpc/grpc-web/releases) to generate the client. The final step uses [Python 3](https://www.python.org/downloads/) to serve the page locally.

Generate a browser client for the same `helloworld.Greeter` contract used by the Route.

Create a client directory and install the pinned browser dependencies:

```
mkdir grpc-web-client

cp helloworld.proto grpc-web-client/

cd grpc-web-client



npm init -y

npm install --save-exact grpc-web@2.1.1 google-protobuf@4.0.2

npm install --save-dev --save-exact \

  @protocolbuffers/protoc-gen-js@4.0.2 \

  esbuild@0.25.9
```

Generate the JavaScript message classes and client stub:

```
protoc -I=. \

  --plugin=protoc-gen-js=./node_modules/.bin/protoc-gen-js \

  --js_out=import_style=commonjs:. \

  --grpc-web_out=import_style=commonjs,mode=grpcwebtext:. \

  helloworld.proto
```

Create the browser client:

client.js

```
const { GreeterClient } = require('./helloworld_grpc_web_pb');

const { HelloRequest } = require('./helloworld_pb');



const output = document.querySelector('#output');

const client = new GreeterClient('http://127.0.0.1:9080/grpc-web');

const request = new HelloRequest();

request.setName('API7');



client.sayHello(request, {}, (error, response) => {

  output.textContent = error

    ? `error: ${error.message}`

    : response.getMessage();

});
```

Create a page that displays the result:

index.html

```
<!doctype html>

<html lang="en">

  <head>

    <meta charset="utf-8">

    <title>API7 Gateway gRPC-Web example</title>

  </head>

  <body>

    <pre id="output"></pre>

    <script src="bundle.js"></script>

  </body>

</html>
```

Bundle and serve the client:

```
./node_modules/.bin/esbuild client.js --bundle --outfile=bundle.js

python3 -m http.server 8088
```

Open `http://127.0.0.1:8088` in a browser. The page should display:

```
Hello API7
```

## Next Steps[​](#next-steps "Direct link to Next Steps")

* [Configure WebSocket Proxying](https://docs.api7.ai/api7-gateway/how-to-guides/protocol-proxy/websocket-proxy.md) — learn how to handle long-lived WebSocket connections.
* [Configure GraphQL Proxying](https://docs.api7.ai/api7-gateway/how-to-guides/protocol-proxy/graphql-proxy.md) — explore GraphQL-aware traffic management.
