{"id":21106887,"url":"https://github.com/mult1mate/protoc-gen-httpgo","last_synced_at":"2026-05-20T03:36:06.150Z","repository":{"id":183043942,"uuid":"669519868","full_name":"MUlt1mate/protoc-gen-httpgo","owner":"MUlt1mate","description":"protoc plugin that generates HTTP server and client","archived":false,"fork":false,"pushed_at":"2026-03-28T16:51:30.000Z","size":380,"stargazers_count":19,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-28T18:32:35.766Z","etag":null,"topics":["generator","golang","protoc"],"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/MUlt1mate.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-07-22T14:44:33.000Z","updated_at":"2026-03-25T15:04:32.000Z","dependencies_parsed_at":"2025-07-12T19:14:25.562Z","dependency_job_id":"57e03083-86c6-49f8-adb4-6103d9378fbe","html_url":"https://github.com/MUlt1mate/protoc-gen-httpgo","commit_stats":null,"previous_names":["mult1mate/protoc-gen-httpgo"],"tags_count":29,"template":false,"template_full_name":null,"purl":"pkg:github/MUlt1mate/protoc-gen-httpgo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MUlt1mate%2Fprotoc-gen-httpgo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MUlt1mate%2Fprotoc-gen-httpgo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MUlt1mate%2Fprotoc-gen-httpgo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MUlt1mate%2Fprotoc-gen-httpgo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MUlt1mate","download_url":"https://codeload.github.com/MUlt1mate/protoc-gen-httpgo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MUlt1mate%2Fprotoc-gen-httpgo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33244778,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-20T03:30:51.439Z","status":"ssl_error","status_checked_at":"2026-05-20T03:30:49.443Z","response_time":356,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["generator","golang","protoc"],"created_at":"2024-11-20T00:30:13.232Z","updated_at":"2026-05-20T03:36:06.143Z","avatar_url":"https://github.com/MUlt1mate.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# protoc-gen-httpgo\n\n![workflow](https://github.com/MUlt1mate/protoc-gen-httpgo/actions/workflows/go.yml/badge.svg)\n![go-report](https://goreportcard.com/badge/github.com/MUlt1mate/protoc-gen-httpgo)\n[![Go Reference](https://pkg.go.dev/badge/github.com/MUlt1mate/protoc-gen-httpgo.svg)](https://pkg.go.dev/github.com/MUlt1mate/protoc-gen-httpgo)\n\n**httpgo** is a protoc plugin that generates native HTTP server and client code from your proto files.  \nIt is a lightweight, high-performance alternative to [grpc-gateway](https://github.com/grpc-ecosystem/grpc-gateway).\n\nChoose httpgo if you want to:\n\n- **Eliminate Proxy Overhead**: Serve HTTP directly from your application without a transcoding layer.\n- **Dual-Stack Support**: Use HTTP and gRPC simultaneously with minimal performance impact.\n- **Protobuf-First Design**: Define your API in Protobuf while leveraging the full flexibility of the HTTP ecosystem.\n\n## Table of Contents\n\n- [Performance](#performance)\n- [Features](#features)\n- [Usage](#usage)\n    - [Installation](#installation)\n    - [Definition](#definition)\n    - [Generation](#generation)\n        - [Parameters](#parameters)\n    - [Implementation](#implementation)\n        - [Server](#server)\n        - [Client](#client)\n        - [Middlewares](#middlewares)\n        - [Error handling](#error-handling)\n        - [Conventions](#conventions)\n        - [Files](#files)\n    - [Server-side streaming (SSE)](#server-side-streaming-sse)\n- [TODO](#todo)\n\n## Performance\n\nCheck [benchmark](./benchmark/README.md)\n\n- 30% faster than grpc-gateway + grpc\n- 95% reduction in memory overhead\n\n## Features\n\n- Generation of both server and client code\n    - Supports [gin](https://github.com/gin-gonic/gin) (server only)\n    - Supports [fiber](https://github.com/gofiber/fiber) (server only)\n    - Supports [fasthttp](https://github.com/valyala/fasthttp)\n    - Supports [net/http](https://pkg.go.dev/net/http)\n- Provides multiple options for Marshaling/Unmarshaling:\n    - Uses the native `encoding/json` by default\n    - Optional usage of [protojson](https://pkg.go.dev/google.golang.org/protobuf/encoding/protojson) for better\n      protocol buffer support\n- Uses standard\n  [google.api.http](https://cloud.google.com/service-infrastructure/docs/service-management/reference/rpc/google.api#httprule)\n  definitions for path mapping\n    - supports all HttpRule fields\n- Supports automatic URI generation\n- Supports a wide range of data types in path parameters\n- Supports middlewares\n- Supports multipart form with files\n- Supports server-side streaming RPCs over Server-Sent Events (SSE)\n- Zero additional dependencies in generated code\n\n## Usage\n\n### Installation\n\n```bash\n go install github.com/MUlt1mate/protoc-gen-httpgo@latest\n ```\n\n### Definition\n\nUse proto with RPC to define methods\n\n```protobuf\nimport \"google/api/annotations.proto\";\n\nservice TestService {\n  rpc TestMethod (TestMessage) returns (TestMessage) {\n    option (google.api.http) = {\n      get: \"/v1/test/{field1}\"\n    };\n  }\n}\n\nmessage TestMessage {\n  string field1 = 1;\n  string field2 = 2;\n}\n```\n\n### Generation\n\n```bash  \nprotoc -I=. --httpgo_out=paths=source_relative:. example/proto/example.proto\n```  \n\n#### Parameters\n\n| Name            | Values                        | Description                                                                                                      |\n|-----------------|-------------------------------|------------------------------------------------------------------------------------------------------------------|\n| paths           | source_relative, import       | Inherited from protogen, see [docs](https://protobuf.dev/reference/go/go-generated/#invocation) for more details |\n| marshaller      | json, protojson               | Specifies the data marshaling/unmarshaling package. Uses `encoding/json` by default.                             |\n| only            | server, client                | Use to generate either the server or client code exclusively                                                     |\n| autoURI         | false, true                   | Create method URI if annotation is missing.                                                                      |\n| bodylessMethods | GET;DELETE                    | List of semicolon separated http methods that should not have a body.                                            |\n| library         | gin, fiber, fasthttp, nethttp | Server library                                                                                                   |\n| stream          | none, sse                     | Wire format for server-side streaming RPCs. `sse` emits Server-Sent Events handlers; requires `only=server`.     |\n\nExample of parameters usage:\n\n```bash\nprotoc -I=. --httpgo_out=paths=source_relative,only=server,autoURI=true,library=fasthttp:. example/proto/example.proto\n```\n\nThe plugin will create an example.httpgo.go file with the following:\n\n- `Register{ServiceName}HTTPGoServer` - function to register server handlers\n- `{ServiceName}HTTPGoService` - interface with all client methods\n- `Get{ServiceName}HTTPGoClient` - client constructor that implements the above interface\n\n### Implementation\n\n#### Server\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\n\t\"github.com/MUlt1mate/protoc-gen-httpgo/example/implementation\"\n\t\"github.com/MUlt1mate/protoc-gen-httpgo/example/proto\"\n\t\"github.com/fasthttp/router\"\n\t\"github.com/valyala/fasthttp\"\n)\n\nfunc serverExample(ctx context.Context) (err error) {\n\tvar (\n\t\thandler proto.TestServiceHTTPGoService = \u0026implementation.Handler{}\n\t\tr                                      = router.New()\n\t)\n\tif err = proto.RegisterTestServiceHTTPGoServer(ctx, r, handler, serverMiddlewares); err != nil {\n\t\treturn err\n\t}\n\tgo func() { _ = fasthttp.ListenAndServe(\":8080\", r.Handler) }()\n\treturn nil\n}\n\n```\n\n#### Client\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\n\t\"github.com/MUlt1mate/protoc-gen-httpgo/example/proto\"\n\t\"github.com/valyala/fasthttp\"\n)\n\nfunc clientExample(ctx context.Context) (err error) {\n\tvar (\n\t\tclient     *proto.TestServiceHTTPGoClient\n\t\thttpClient = \u0026fasthttp.Client{}\n\t\thost       = \"http://localhost:8080\"\n\t)\n\tif client, err = proto.GetTestServiceHTTPGoClient(ctx, httpClient, host, clientMiddlewares); err != nil {\n\t\treturn err\n\t}\n\t// sending our request\n\t_, _ = client.TestMethod(context.Background(), \u0026proto.TestMessage{Field1: \"value\", Field2: \"rand\"})\n\treturn nil\n}\n\n```\n\n#### Middlewares\n\nYou can define custom middlewares with specific arguments and return values.\nPass a slice of middlewares to the constructor, and they will be invoked in the specified order.\nThere are ready-to-use examples with 9 server middlewares (monitoring, timeout, recovery, response, headers,\ntracing, auth, logging, validation) across all four implementations:\n[fasthttp](example/implementation/fasthttp/README.md),\n[fiber](example/implementation/fiber/README.md),\n[gin](example/implementation/gin/README.md),\n[nethttp](example/implementation/nethttp/README.md).\nAdditionally, 5 client middlewares (monitoring, tracing, logging, error handling, timeout) are included in the\n[fasthttp](example/implementation/fasthttp/README.md) and [nethttp](example/implementation/nethttp/README.md) examples;\nthe fiber and gin examples are server-only.\n\n```go\npackage fasthttp\n\nimport (\n\t\"context\"\n\t\"log\"\n\n\t\"github.com/valyala/fasthttp\"\n)\n\nvar ServerMiddlewares = []func(ctx context.Context, arg any, handler func(ctx context.Context, arg any) (resp any, err error)) (resp any, err error){\n\tLoggerServerMiddleware,\n}\nvar ClientMiddlewares = []func(ctx context.Context, req *fasthttp.Request, handler func(ctx context.Context, req *fasthttp.Request) (resp *fasthttp.Response, err error)) (resp *fasthttp.Response, err error){\n\tLoggerClientMiddleware,\n}\n\nfunc LoggerServerMiddleware(\n\tctx context.Context, arg any,\n\tnext func(ctx context.Context, arg any) (resp any, err error),\n) (resp any, err error) {\n\tlog.Println(\"server request\", arg)\n\tresp, err = next(ctx, arg)\n\tlog.Println(\"server response\", resp)\n\treturn resp, err\n}\n\nfunc LoggerClientMiddleware(\n\tctx context.Context,\n\treq *fasthttp.Request,\n\tnext func(ctx context.Context, req *fasthttp.Request) (resp *fasthttp.Response, err error),\n) (resp *fasthttp.Response, err error) {\n\tlog.Println(\"client request\", string(req.URL.String()))\n\tresp, err = next(ctx, req)\n\tlog.Println(\"client response\", string(resp.Body()))\n\treturn resp, err\n}\n\n```\n\nSee [example](https://github.com/MUlt1mate/protoc-gen-httpgo/tree/main/example) for more details.\n\n#### Error handling\n\nThe generated server code does not inspect the `error` returned by your handler: it marshals whatever value the handler\nreturned and writes it to the response body. If you want a non-nil error to produce an error response, handle it in a\nmiddleware — check `err` after calling `next`, and write the desired payload (for example by replacing `resp` with an\nerror struct, or setting the response status code directly via the transport-specific context stored on `ctx`).\n\nThe example implementations in `ResponseServerMiddleware` does exactly this: after calling `next`, if `err` is\nnon-nil it replaces `resp` with an error struct (`respError{Error: err.Error()}`) and clears `err` so the generated\ncode marshals the error payload into the response body.  \nPair it with `HeadersServerMiddleware` if you also need to map errors to HTTP status codes.\n\nFor SSE handlers the response body is the event stream itself, so there is nothing for a middleware to overwrite after\nthe stream completes. Middlewares still see the handler's `err` after `next` returns and can use it for logging,\nmetrics, or propagating cancellation — but they cannot turn it into a structured error body.\n\n#### Conventions\n\nGolang protobuf generator can produce fields with different case:\n\n```protobuf\nmessage InputMsgName {\n  int64 value = 1;\n}\n```\n\n```go\npackage main\n\nimport \"google.golang.org/protobuf/runtime/protoimpl\"\n\ntype InputMsgName struct {\n\tstate         protoimpl.MessageState\n\tsizeCache     protoimpl.SizeCache\n\tunknownFields protoimpl.UnknownFields\n\n\tValue int64 `protobuf:\"varint,1,opt,name=value,proto3\" json:\"value,omitempty\"`\n}\n\n```\n\nWe defined **v**alue and got **V**alue. This works just fine, but keep in mind that server will only check for arguments\nwith proto names.\n\n* /v1/test?value=1 - correct\n* /v1/test?Value=1 - incorrect\n\n#### Files\n\nTo send and receive files you need to define file field as a message with the following fields.\nThe message name can be anything — the plugin identifies file fields by their structure, not by name.\n\n```protobuf\nmessage Request {\n  FileMsg document = 1;\n  FileMsg anotherDocument = 2;\n}\n\nmessage FileMsg {\n  bytes file = 1;\n  string name = 2;\n  map\u003cstring, string\u003e headers = 3;\n}\n```\n\n### Server-side streaming (SSE)\n\nMark an RPC as server-streaming in your proto and generate with `stream=sse`:\n\n```protobuf\nservice TickerService {\n  rpc Ticks (TickRequest) returns (stream Tick) {\n    option (google.api.http) = {\n      get: \"/v1/ticks\"\n    };\n  }\n}\n```\n\n```bash\nprotoc -I=. --httpgo_out=paths=source_relative,only=server,stream=sse,library=nethttp:. ticker.proto\n```\n\nStreaming methods appear on the generated service interface with a callback instead of a single return value:\n\n```go\nTicks(context.Context, *TickRequest, func (*Tick) error) error\n```\n\nThe generated handler sets the SSE response headers:\n\n- `Content-Type: text/event-stream`\n- `Cache-Control: no-cache`\n- `Connection: keep-alive`\n\nand writes each message as a `data: \u003cjson\u003e\\n\\n` frame and flush.   \nCall `send` once per message from your implementation; return when the stream is complete or the client disconnects (\nobservable via the passed `context`).\n\nClient-streaming and bidirectional-streaming RPCs are still skipped.\n\n## TODO\n\n- implement more web servers\n- buf\n- WS streaming\n- optionally ignore unknown query parameters\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmult1mate%2Fprotoc-gen-httpgo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmult1mate%2Fprotoc-gen-httpgo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmult1mate%2Fprotoc-gen-httpgo/lists"}