{"id":19839223,"url":"https://github.com/sudorandom/unknownconnect-go","last_synced_at":"2026-05-19T03:21:56.169Z","repository":{"id":225383116,"uuid":"765781597","full_name":"sudorandom/unknownconnect-go","owner":"sudorandom","description":"Interceptor for ConnectRPC to highlight unknown fields in proto messages","archived":false,"fork":false,"pushed_at":"2024-03-17T14:20:55.000Z","size":32,"stargazers_count":3,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-28T22:20:01.837Z","etag":null,"topics":["connectrpc","grpc","protobuf"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sudorandom.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-03-01T15:52:23.000Z","updated_at":"2024-07-11T20:07:27.000Z","dependencies_parsed_at":"2024-03-11T22:26:53.448Z","dependency_job_id":"49eaed2b-15f9-4151-9f0d-afd3a2526d89","html_url":"https://github.com/sudorandom/unknownconnect-go","commit_stats":null,"previous_names":["sudorandom/unknownconnect-go"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/sudorandom/unknownconnect-go","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sudorandom%2Funknownconnect-go","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sudorandom%2Funknownconnect-go/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sudorandom%2Funknownconnect-go/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sudorandom%2Funknownconnect-go/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sudorandom","download_url":"https://codeload.github.com/sudorandom/unknownconnect-go/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sudorandom%2Funknownconnect-go/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262188397,"owners_count":23272341,"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":["connectrpc","grpc","protobuf"],"created_at":"2024-11-12T12:21:10.009Z","updated_at":"2026-05-19T03:21:56.121Z","avatar_url":"https://github.com/sudorandom.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# unknownconnect-go\n[![Go](https://github.com/sudorandom/unknownconnect-go/actions/workflows/go.yml/badge.svg)](https://github.com/sudorandom/unknownconnect-go/actions/workflows/go.yml) [![Go Report Card](https://goreportcard.com/badge/github.com/sudorandom/unknownconnect-go)](https://goreportcard.com/report/github.com/sudorandom/unknownconnect-go) [![Go Reference](https://pkg.go.dev/badge/github.com/sudorandom/unknownconnect-go.svg)](https://pkg.go.dev/github.com/sudorandom/unknownconnect-go)\n\nunknownconnect-go is an interceptor for [ConnectRPC](https://connectrpc.com/) clients and servers that tells you if you are receiving protobuf messages with unknown fields. This is useful to know when you should upgrade your gRPC clients or servers to the latest version.\n\n```bash\ngo get -u github.com/sudorandom/unknownconnect-go\n```\n\n## Docs\n```go\npackage unknownconnect // import \"github.com/sudorandom/unknownconnect-go\"\n\n// Interceptors\nfunc NewInterceptor(opts ...option) *interceptor\nfunc WithCallback(callback UnknownCallback) option\nfunc WithDrop() option\ntype UnknownCallback func(context.Context, connect.Spec, proto.Message) error\n\n// Helpers\nfunc DropUnknownFields(msg protoreflect.Message)\nfunc ForEachUnknownField(msg protoreflect.Message, cb func(msg protoreflect.Message) bool)\nfunc MessageHasUnknownFields(msg protoreflect.Message) bool\n\n```\n\n\n## Server Examples\nShort example (logging):\n```go\nunknownconnect.NewInterceptor(\n    unknownconnect.WithCallback(func(ctx context.Context, spec connect.Spec, msg proto.Message) error {\n        slog.Warn(\"received a protobuf message with unknown fields\", slog.Any(\"spec\", spec), slog.Any(\"msg\", msg))\n        return nil\n    }),\n)\n```\n\nDropping unknown fields:\n```go\nunknownconnect.NewInterceptor(unknownconnect.WithDrop())\n```\n\nFull example (returning an error):\n```go\nimport (\n    \"log/slog\"\n\n    \"connectrpc.com/connect\"\n    unknownconnect \"github.com/sudorandom/unknownconnect-go\"\n)\n\nfunc main() {\n    greeter := \u0026GreetServer{}\n    mux := http.NewServeMux()\n    path, handler := greetv1connect.NewGreetServiceHandler(greeter, connect.WithInterceptors(\n        unknownconnect.NewInterceptor(\n            unknownconnect.WithCallback(func(ctx context.Context, spec connect.Spec, msg proto.Message) error {\n                return connect.NewError(connect.InvalidArgument, err)\n            }),\n    )))\n    mux.Handle(path, handler)\n    http.ListenAndServe(\"localhost:8080\", h2c.NewHandler(mux, \u0026http2.Server{}))\n}\n```\n\nThe first example simply emits a warning log and the second example will fail the request if the server receives a message with unknown fields. You can decide what to do. Here are some ideas:\n\n- Add to a metric that counts how often this happens\n- Drop the unknown fields\n- Fail the request/response; maybe the most useful in non-production integration environments\n- Emit a log\n- Add an annotation to the context to be used in the handler\n- ???\n\n## Client Examples\nAnd it works the same for clients, too:\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"log/slog\"\n    \"net/http\"\n\n    greetv1 \"example/gen/greet/v1\"\n    \"example/gen/greet/v1/greetv1connect\"\n\n    \"connectrpc.com/connect\"\n)\n\nfunc main() {\n    client := greetv1connect.NewGreetServiceClient(\n        http.DefaultClient,\n        \"http://localhost:8080\",\n        connect.WithInterceptors(\n            unknownconnect.NewInterceptor(\n                unknownconnect.WithCallback(func(ctx context.Context, spec connect.Spec, msg proto.Message) error {\n                    slog.Warn(\"received a protobuf message with unknown fields\", slog.Any(\"spec\", spec), slog.Any(\"msg\", msg))\n                    return nil\n                }),\n        )),\n    )\n    res, err := client.Greet(\n        context.Background(),\n        connect.NewRequest(\u0026greetv1.GreetRequest{Name: \"Jane\"}),\n    )\n    if err != nil {\n        slog.Error(err.Error())\n        return\n    }\n    slog.Info(res.Msg.Greeting)\n}\n```\n\n## Why?\ngRPC systems can be quite complex. When making additions to protobuf files the server or the client often gets updated at different times. In a perfect world, this would all be synchronized. But we live in reality. Sometimes release schedules differ between components. Sometimes you just forget to update a component. Many times you might be consuming a gRPC service managed by another team and *they don't tell you that they're changing things*. I believe this interceptor helps with all of these cases. It allows you to raise the issue before it becomes a problem.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsudorandom%2Funknownconnect-go","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsudorandom%2Funknownconnect-go","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsudorandom%2Funknownconnect-go/lists"}