{"id":19643995,"url":"https://github.com/siderolabs/grpc-proxy","last_synced_at":"2025-04-07T13:05:51.566Z","repository":{"id":38339445,"uuid":"224215613","full_name":"siderolabs/grpc-proxy","owner":"siderolabs","description":"gRPC Go Proxy library with support for one-to-many proxying and result aggregation.","archived":false,"fork":false,"pushed_at":"2025-01-23T07:49:37.000Z","size":186,"stargazers_count":64,"open_issues_count":2,"forks_count":17,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-03-31T12:06:48.134Z","etag":null,"topics":["grpc","grpc-go","grpc-proxy","one-to-many","proxy"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/siderolabs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","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":"2019-11-26T14:47:07.000Z","updated_at":"2025-03-26T09:27:30.000Z","dependencies_parsed_at":"2023-01-19T15:46:38.310Z","dependency_job_id":"4104f396-a933-4d24-924b-ef4306242192","html_url":"https://github.com/siderolabs/grpc-proxy","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siderolabs%2Fgrpc-proxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siderolabs%2Fgrpc-proxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siderolabs%2Fgrpc-proxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siderolabs%2Fgrpc-proxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/siderolabs","download_url":"https://codeload.github.com/siderolabs/grpc-proxy/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247657276,"owners_count":20974344,"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":["grpc","grpc-go","grpc-proxy","one-to-many","proxy"],"created_at":"2024-11-11T14:25:04.684Z","updated_at":"2025-04-07T13:05:51.522Z","avatar_url":"https://github.com/siderolabs.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# gRPC Proxy\n\n[![Go Report Card](https://goreportcard.com/badge/github.com/talos-systems/grpc-proxy)](https://goreportcard.com/report/github.com/talos-systems/grpc-proxy)\n[![GoDoc](http://img.shields.io/badge/GoDoc-Reference-blue.svg)](https://godoc.org/github.com/talos-systems/grpc-proxy)\n[![Apache 2.0 License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)\n\n[gRPC Go](https://github.com/grpc/grpc-go) Proxy server\n\n## Project Goal\n\nBuild a transparent reverse proxy for gRPC targets that will make it easy to expose gRPC services\nover the Internet.\n\nThis includes:\n\n* no needed knowledge of the semantics of requests exchanged in the call (independent rollouts)\n* easy declarative definition of backends and their mappings to frontends\n* simple round-robin load balancing of inbound requests from a single connection to multiple backends\n\n## Proxying Modes\n\nThere are two proxying modes supported:\n\n* one to one: in this mode data passed back and forth is transmitted as is without any modifications;\n* one to many: one client connection gets mapped into multiple upstream connections, results might be aggregated\n  (for unary calls), errors translated into response messages; this mode requires a special layout of protobuf messages.\n\n## Proxy Handler\n\nThe package [`proxy`](proxy/) contains a generic gRPC reverse proxy handler that allows a gRPC server not to\nknow about method names and their request/response data types.\nPlease consult the package documentation.\nHere you can find an example usage.\n\nFirst, define `Backend` implementation to identify specific upstream.\nFor one to one proxying, `SingleBackend` might be used:\n\n```go\nconn, err := grpc.NewClient(\n    \"api-service.staging.svc.local\",\n    grpc.WithDefaultCallOptions(grpc.ForceCodec(proxy.Codec())),\n)\nif err != nil {\n    log.Fatal(err)\n}\n\nbackend := \u0026proxy.SingleBackend{\n    GetConn: func(ctx context.Context) (context.Context, *grpc.ClientConn, error) {\n        md, _ := metadata.FromIncomingContext(ctx)\n\n        // Copy the inbound metadata explicitly.\n        outCtx := metadata.NewOutgoingContext(ctx, md.Copy())\n\n        return outCtx, conn, nil\n    },\n}\n```\n\nDefining a `StreamDirector` that decides where (if at all) to send the request\n\n```go\ndirector = func(ctx context.Context, fullMethodName string) (proxy.Mode, []proxy.Backend, error) {\n    // Make sure we never forward internal services.\n    if strings.HasPrefix(fullMethodName, \"/com.example.internal.\") {\n        return proxy.One2One, nil, status.Errorf(codes.Unimplemented, \"Unknown method\")\n    }\n\n    md, ok := metadata.FromIncomingContext(ctx)\n\n    if ok {\n        // Decide on which backend to dial\n        if val, exists := md[\":authority\"]; exists \u0026\u0026 val[0] == \"staging.api.example.com\" {\n            return proxy.One2One, []proxy.Backend{stagingBackend}, nil\n        } else if val, exists := md[\":authority\"]; exists \u0026\u0026 val[0] == \"api.example.com\" {\n            return proxy.One2One, []proxy.Backend{prodBackend}, nil\n        }\n    }\n\n    return proxy.One2One, nil, status.Errorf(codes.Unimplemented, \"Unknown method\")\n}\n```\n\nThen you need to register it with a `grpc.Server`.\nThe server may have other handlers that will be served locally:\n\n```go\nserver := grpc.NewServer(\n    grpc.ForceServerCodec(proxy.Codec()),\n    grpc.UnknownServiceHandler(\n        proxy.TransparentHandler(director),\n        proxy.WithMode(proxy.One2One),\n    ))\npb_test.RegisterTestServiceServer(server, \u0026testImpl{})\n```\n\n## One to Many Proxying\n\nIn one to many proxying mode, it's critical to identify source of each message proxied back from the upstreams.\nAlso upstream error shouldn't fail whole request and instead return errors as messages back.\nIn order to achieve this goal, protobuf response message should follow the same structure:\n\n1. Every response should be `repeated` list of response messages so that responses from multiple upstreams might be\nconcatenated to build a combined response from all the upstreams.\n\n2. Response should contain common metadata fields which allow grpc-proxy to inject source information and error information\ninto response.\n\n## Talks\n\n* \"Transparent gRPC proxy in Go\" at [GopherCon Russia 2021](https://www.gophercon-russia.ru/) [slides](https://speakerdeck.com/smira/transparent-grpc-gateway-in-go)\n\n## History\n\nThis is a fork of awesome [mwitkow/grpc-proxy](https://github.com/mwitkow/grpc-proxy) package with added support\nfor one to many proxying.\n\n## License\n\n`grpc-proxy` is released under the Apache 2.0 license.\nSee [LICENSE.txt](LICENSE.txt).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsiderolabs%2Fgrpc-proxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsiderolabs%2Fgrpc-proxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsiderolabs%2Fgrpc-proxy/lists"}