{"id":19284251,"url":"https://github.com/eset/grpc-rest-proxy","last_synced_at":"2025-04-22T03:31:52.732Z","repository":{"id":251048672,"uuid":"829029496","full_name":"eset/grpc-rest-proxy","owner":"eset","description":"Gateway automatically translating REST requests to gRPC","archived":false,"fork":false,"pushed_at":"2024-11-07T10:05:26.000Z","size":165,"stargazers_count":6,"open_issues_count":1,"forks_count":0,"subscribers_count":6,"default_branch":"main","last_synced_at":"2024-11-07T10:38:18.895Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eset.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-07-15T15:58:48.000Z","updated_at":"2024-09-30T11:00:43.000Z","dependencies_parsed_at":"2024-11-07T10:31:21.231Z","dependency_job_id":"6f50327b-caa6-4ffa-92bf-8e72ccb4cfeb","html_url":"https://github.com/eset/grpc-rest-proxy","commit_stats":null,"previous_names":["eset/grpc-rest-proxy"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eset%2Fgrpc-rest-proxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eset%2Fgrpc-rest-proxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eset%2Fgrpc-rest-proxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eset%2Fgrpc-rest-proxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eset","download_url":"https://codeload.github.com/eset/grpc-rest-proxy/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223888518,"owners_count":17220074,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-09T21:37:31.172Z","updated_at":"2024-11-09T21:37:31.704Z","avatar_url":"https://github.com/eset.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GRPC REST Proxy\n\n[![Build](https://github.com/eset/grpc-rest-proxy/actions/workflows/build.yaml/badge.svg)](https://github.com/eset/grpc-rest-proxy/actions/workflows/build.yaml)\n[![Test](https://github.com/eset/grpc-rest-proxy/actions/workflows/test.yaml/badge.svg)](https://github.com/eset/grpc-rest-proxy/actions/workflows/test.yaml)\n[![Lint](https://github.com/eset/grpc-rest-proxy/actions/workflows/lint.yaml/badge.svg)](https://github.com/eset/grpc-rest-proxy/actions/workflows/lint.yaml)\n[![Vulncheck](https://github.com/eset/grpc-rest-proxy/actions/workflows/vulncheck.yaml/badge.svg)](https://github.com/eset/grpc-rest-proxy/actions/workflows/vulncheck.yaml)\n\nCopyright © ESET 2024-2028\n\nService that is automatically translating REST requests to gRPC and sending them to provided endpoint. REST is defined using [Google's proto HTTP annotation](https://github.com/googleapis/googleapis/blob/master/google/api/http.proto). Our implementation is able to load proto descriptors directly from grpc endpoint using server reflection service. Main advantage of this approach is elimination of the need to recompile protobufs or grpc-rest-proxy (to incorporate changes in protos), making translation and maintenance easier.\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"./docs/diagram.png\"\u003e\n\u003c/p\u003e\n\n## How to build\n#### Build main service\n```bash\nmake build\n```\n\n## Usage\nFor more information see:  [config-example.yaml](./config-example.yaml) or [cmd/service/main.go](./cmd/service/main.go).\n\n#### Available parameters\n```\nUsage of ./grpc-rest-proxy:\n  -c, --config string                                      path to config file\n      --descriptors.remote.exclude stringArray             remote descriptors to exclude (default [grpc.health.v1.Health,grpc.reflection.v1.ServerReflection])\n      --descriptors.remote.reflectionServiceName string    reflection service name (default \"grpc.reflection.v1.ServerReflection/ServerReflectionInfo\")\n      --descriptors.remote.timeout duration                request timeout for remote descriptors (default 1m0s)\n      --gateways.grpc.client.requestTimeout duration       requests timeout (default 5s)\n      --gateways.grpc.client.targetAddr string             address and port of the gRPC server (default \"0.0.0.0:50051\")\n      --gateways.grpc.client.tls                           use TLS for gRPC connection\n      --gateways.grpc.client.tlsSkipverify                 skip TLS verification\n      --gateways.grpc.requestTimeout duration              client request timeout (default 5s)\n      --transport.http.maxRequestSizeKB uint               maximum size of requests in KB (default 10024)\n      --transport.http.requestTimeout duration             request timeout (default 5s)\n      --transport.http.server.addr string                  address and port of the HTTP server (default \"0.0.0.0:8080\")\n      --transport.http.server.gracefulTimeout duration     graceful timeout (default 5s)\n      --transport.http.server.readHeaderTimeout duration   read header timeout (default 5s)\n      --transport.http.server.readTimeout duration         read timeout (default 10s)\n      --service.jsonencoder.useProtoNames                  use proto names in JSON response (instead of camel case)\n      --service.jsonencoder.emitUnpopulated                emit unpopulated fields in JSON response for empty gRPC values\n      --service.jsonencoder.emitDefaultValues              include default values in JSON response for empty gRPC values\n  -v, --version                                            print version\n```\n\n#### Precedence of configuration items:\n1. command line args\n2. config file\n3. default flags\n\nAll default values can be found in [cmd/service/main.go](./cmd/service/main.go).\n\n## How to load protobuf definitions\nTwo methods are currently supported: remote proto reflection server or local storage.\nRemote proto reflection server is used as default method when no other is specified by configuration or parameters.\n\n### Remote proto reflection server\nDuring startup, proto descriptors will be downloaded from endpoint specified in `gateways` section. Default endpoint address is `0.0.0.0:50051`.\n```yaml\ndescriptors:\n  kind: remote\n  remote:\n    # overall timeout for connecting and loading all definitions\n    timeout: 1m \n    reflectionServiceName: grpc.reflection.v1.ServerReflection/ServerReflectionInfo\n    # which services we want to exclude from parsing (making them private)\n    exclude:\n      - grpc.health.v1.Health\n      - grpc.reflection.v1.ServerReflection\n      - grpc.reflection.v1alpha.ServerReflection\n```\n\nProto reflection is allowed by adding following lines: \n\n```diff\n    import (\n        \"fmt\"\n\t    \"net\"\n\t    logging \"log/slog\"\n\n\t    jErrors \"github.com/juju/errors\"\n\t    \"github.com/spf13/pflag\"\n\t    \"google.golang.org/grpc\"\n+       \"google.golang.org/grpc/reflection\" \n\n\t    pb \"github.com/eset/grpc-rest-proxy/cmd/examples/grpcserver/gen/user/v1\"\n )\n\n func newServer() *grpc.Server {\n\tgrpcServer := grpc.NewServer()\n\tpb.RegisterUserServiceServer(grpcServer, NewUserService())\n\t// Register reflection service on gRPC server.\n+\treflection.Register(grpcServer)\n\treturn grpcServer\n}\n```\n\n\n### Local storage\nLocal directory will be recursively searched during startup for compiled proto descriptors (file extension `.desc`).\n```yaml\ndescriptors:\n  kind: \"local\"\n  local:\n    dir: \"/var/opt/myprotos/\"\n```\n\n## Run as Sidecar\nYou can run grpc-rest-proxy as a sidecar along with grpc service. All you need to do is supply image with configuration and update deployment of your service.\n\nAdvantages of sidecar:\n- Loaded proto definitions in gateway will always match service's.\n- Compatible with cannary releases.\n- Gateway's lifetime is tied to service, thus easier to manage.\n\n**Gateway must be set to load from remote proto repository. In this mode, it will automatically load all definitions from targeted endpoints in its configuration. Example: [config-sidecar.yaml](config-sidecar.yaml).**\n\nExample of Kubernetes deployment:\n```yaml\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: example-service\nspec:\n  replicas: 4\n  template:\n    metadata:\n    spec:\n      containers:\n        # main service with enabled grpc reflection\n        - name: service \n          image: \"example-service:latest\"\n          command:\n            - \"/app/example-service\"\n          ports:\n            - name: grpc-port\n              containerPort: 50051\n        # gateway that will connnect to service\n        - name: grpc-rest-proxy\n          image: grpcrestproxy.azurecr.io/grpc-rest-proxy:latest\n          command:\n            - \"/app/grpc-rest-proxy\"\n          args:\n            - \"--gateways.grpc.client.targetAddr=127.0.0.1:50051\"\n          ports:\n            - name: web-port\n              containerPort: 8080\n```\n\n### Error handling\nOn error, the proxy returns an HTTP status code and JSON response body. JSON is defined using our [Error protobuf message](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto). It contains code, message and details.\n\nThe backend endpoint can define its own protobuf messages containing details of the error and return it in standard grpc status. The proxy takes these messsages and serializes them into JSON response.\n\n```json\n{\n  \"code\": 404,\n  \"message\": \"User name not found.\",\n  \"details\": [\n    {\n      \"@type\": \"type.googleapis.com/user.v1.GetUserError\",\n      \"username\": \"John1234\",\n      \"recommendation\": \"Please check the username and try again.\"\n    }\n  ]\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feset%2Fgrpc-rest-proxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feset%2Fgrpc-rest-proxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feset%2Fgrpc-rest-proxy/lists"}