{"id":15399458,"url":"https://github.com/chai2010/pbgo","last_synced_at":"2025-04-10T20:52:00.429Z","repository":{"id":41512140,"uuid":"141013985","full_name":"chai2010/pbgo","owner":"chai2010","description":":computer: pbgo is a mini RPC/REST/Grpc-Gateway framework based on Protobuf","archived":false,"fork":false,"pushed_at":"2024-07-22T13:37:03.000Z","size":120,"stargazers_count":126,"open_issues_count":0,"forks_count":11,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-06T07:37:25.049Z","etag":null,"topics":["gateway","go","golang","grpc","pbgo","protobuf","rest"],"latest_commit_sha":null,"homepage":"https://godoc.org/github.com/chai2010/pbgo","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chai2010.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":"2018-07-15T09:21:40.000Z","updated_at":"2024-12-11T07:18:25.000Z","dependencies_parsed_at":"2024-10-21T12:07:01.168Z","dependency_job_id":null,"html_url":"https://github.com/chai2010/pbgo","commit_stats":{"total_commits":79,"total_committers":2,"mean_commits":39.5,"dds":"0.012658227848101222","last_synced_commit":"e7d5f8b820b8901f25dc5ff4cc8d4e7b85ff47b1"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chai2010%2Fpbgo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chai2010%2Fpbgo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chai2010%2Fpbgo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chai2010%2Fpbgo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chai2010","download_url":"https://codeload.github.com/chai2010/pbgo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248296912,"owners_count":21080306,"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":["gateway","go","golang","grpc","pbgo","protobuf","rest"],"created_at":"2024-10-01T15:48:57.538Z","updated_at":"2025-04-10T20:52:00.405Z","avatar_url":"https://github.com/chai2010.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"- *凹语言(凹读音“Wa”)(The Wa Programming Language): https://github.com/wa-lang/wa*\n\n----\n\n# pbgo: mini rpc/rest framework based on Protobuf\n\n[![Build Status](https://travis-ci.org/chai2010/pbgo.svg)](https://travis-ci.org/chai2010/pbgo)\n[![Go Report Card](https://goreportcard.com/badge/github.com/chai2010/pbgo)](https://goreportcard.com/report/github.com/chai2010/pbgo)\n[![GoDoc](https://godoc.org/github.com/chai2010/pbgo?status.svg)](https://godoc.org/github.com/chai2010/pbgo)\n\n## Features\n\n- protoc plugin generate code\n- define rpc api with Protobuf, generate stub code, work with standard `net/rpc` framework\n- define rest api with Protobuf, and generate service and client code\n- work with grpc framework\n\n## Install\n\n1. install `protoc` at first: http://github.com/google/protobuf/releases\n1. `go get github.com/chai2010/pbgo`\n1. `go get github.com/chai2010/pbgo/protoc-gen-pbgo`\n1. `go run hello.go`\n\n## Example (net/rpc)\n\ncreate proto file:\n\n```protobuf\nsyntax = \"proto3\";\npackage hello_pb;\n\nmessage String {\n\tstring value = 1;\n}\nmessage Message {\n\tstring value = 1;\n}\n\nservice HelloService {\n\trpc Hello (String) returns (String);\n\trpc Echo (Message) returns (Message);\n}\n```\n\ngenerate rpc code:\n\n```\n$ protoc -I=. -I=$GOPATH/src --pbgo_out=. hello.proto\n```\n\nuse generate code:\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net\"\n\t\"net/rpc\"\n\n\t\"github.com/chai2010/pbgo/examples/hello.pb\"\n)\n\ntype HelloService struct{}\n\nfunc (p *HelloService) Hello(request *hello_pb.String, reply *hello_pb.String) error {\n\treply.Value = \"hello:\" + request.GetValue()\n\treturn nil\n}\nfunc (p *HelloService) Echo(request *hello_pb.Message, reply *hello_pb.Message) error {\n\t*reply = *request\n\treturn nil\n}\n\nfunc startRpcServer() {\n\thello_pb.RegisterHelloService(rpc.DefaultServer, new(HelloService))\n\n\tlistener, err := net.Listen(\"tcp\", \":1234\")\n\tif err != nil {\n\t\tlog.Fatal(\"ListenTCP error:\", err)\n\t}\n\n\tfor {\n\t\tconn, err := listener.Accept()\n\t\tif err != nil {\n\t\t\tlog.Fatal(\"Accept error:\", err)\n\t\t}\n\n\t\tgo rpc.ServeConn(conn)\n\t}\n}\n\nfunc tryRpcClient() {\n\tclient, err := hello_pb.DialHelloService(\"tcp\", \"localhost:1234\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\treply, err := client.Hello(\u0026hello_pb.String{Value: \"gopher\"})\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tfmt.Println(reply.GetValue())\n}\n\nfunc main() {\n\tgo startRpcServer()\n\ttryRpcClient()\n}\n```\n\n\n## Example (rest api)\n\ncreate proto file:\n\n```protobuf\nsyntax = \"proto3\";\npackage hello_pb;\n\nimport \"github.com/chai2010/pbgo/pbgo.proto\";\n\nmessage String {\n\tstring value = 1;\n}\n\nmessage Message {\n\tstring value = 1;\n\trepeated int32 array = 2;\n\tmap\u003cstring,string\u003e dict = 3;\n\tString subfiled = 4;\n}\n\nmessage StaticFile {\n\tstring content_type = 1;\n\tbytes content_body = 2;\n}\n\nservice HelloService {\n\trpc Hello (String) returns (String) {\n\t\toption (pbgo.rest_api) = {\n\t\t\tget: \"/hello/:value\"\n\t\t\tpost: \"/hello\"\n\n\t\t\tadditional_bindings {\n\t\t\t\tmethod: \"DELETE\"; url: \"/hello\"\n\t\t\t}\n\t\t\tadditional_bindings {\n\t\t\t\tmethod: \"PATCH\"; url: \"/hello\"\n\t\t\t}\n\t\t};\n\t}\n\trpc Echo (Message) returns (Message) {\n\t\toption (pbgo.rest_api) = {\n\t\t\tget: \"/echo/:subfiled.value\"\n\t\t};\n\t}\n\trpc Static(String) returns (StaticFile) {\n\t\toption (pbgo.rest_api) = {\n\t\t\tadditional_bindings {\n\t\t\t\tmethod: \"GET\";\n\t\t\t\turl: \"/static/:value\";\n\t\t\t\tcontent_type: \":content_type\";\n\t\t\t\tcontent_body: \":content_body\"\n\t\t\t}\n\t\t};\n\t}\n}\n```\n\ngenerate rpc/rest code:\n\n```\n$ protoc -I=. -I=$GOPATH/src --pbgo_out=. hello.proto\n```\n\nuse generate code:\n\n```go\npackage main\n\nimport (\n\t\"io/ioutil\"\n\t\"log\"\n\t\"mime\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/chai2010/pbgo/examples/hello.pb\"\n)\n\ntype HelloService struct{}\n\nfunc (p *HelloService) Hello(request *hello_pb.String, reply *hello_pb.String) error {\n\treply.Value = \"hello:\" + request.GetValue()\n\treturn nil\n}\nfunc (p *HelloService) Echo(request *hello_pb.Message, reply *hello_pb.Message) error {\n\t*reply = *request\n\treturn nil\n}\nfunc (p *HelloService) Static(request *hello_pb.String, reply *hello_pb.StaticFile) error {\n\tdata, err := ioutil.ReadFile(\"./testdata/\" + request.Value)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treply.ContentType = mime.TypeByExtension(request.Value)\n\treply.ContentBody = data\n\treturn nil\n}\n\nfunc someMiddleware(next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(wr http.ResponseWriter, r *http.Request) {\n\t\ttimeStart := time.Now()\n\t\tdefer func() {\n\t\t\ttimeElapsed := time.Since(timeStart)\n\t\t\tlog.Println(r.Method, r.URL, timeElapsed)\n\t\t}()\n\n\t\tnext.ServeHTTP(wr, r)\n\t})\n}\n\nfunc main() {\n\trouter := hello_pb.HelloServiceHandler(new(HelloService))\n\tlog.Fatal(http.ListenAndServe(\":8080\", someMiddleware(router)))\n}\n```\n\nGo client:\n\n```go\nfunc main() {\n\tvar reply hello_pb.Message\n\terr := pbgo.HttpDo(\"GET\", \"http://127.0.0.1:8080/echo/xx\",\n\t\t\u0026hello_pb.Message{\n\t\t\tValue: \"chai2010\",\n\t\t\tArray: []int32{1, 2, 3},\n\t\t},\n\t\t\u0026reply,\n\t)\n\tif err != nil {\n\t\tprintln(\"aaa\")\n\t\tlog.Fatal(err)\n\t}\n\n\t// {chai2010 [1 2 3] map[] value:\"xx\"  {} [] 0}\n\tfmt.Println(reply)\n}\n```\n\nCURL client:\n\n```\n$ curl localhost:8080/hello/gopher\n{\"value\":\"hello:gopher\"}\n$ curl \"localhost:8080/hello/gopher?value=vgo\"\n{\"value\":\"hello:vgo\"}\n$ curl localhost:8080/hello -X POST --data '{\"value\":\"cgo\"}'\n{\"value\":\"hello:cgo\"}\n\n$ curl localhost:8080/echo/gopher\n{\"subfiled\":{\"value\":\"gopher\"}}\n$ curl \"localhost:8080/echo/gopher?array=123\u0026array=456\"\n{\"array\":[123,456],\"subfiled\":{\"value\":\"gopher\"}}\n$ curl \"localhost:8080/echo/gopher?dict%5Babc%5D=123\"\n{\"dict\":{\"abc\":\"123\"},\"subfiled\":{\"value\":\"gopher\"}}\n\n$ curl localhost:8080/static/gopher.png\n$ curl localhost:8080/static/hello.txt\n```\n\n## Rest Client\n\nhttps://github.com/chubin/wttr.in\n\n```\n$ curl http://wttr.in/wuhan?format=j1\n$ curl http://wttr.in/武汉?format=j1\n```\n\n```go\nfunc main() {\n\tvar reply struct {\n\t\tCurrentCondition []struct {\n\t\t\tFeelsLikeC       string `json:\"FeelsLikeC\"`\n\t\t\tFeelsLikeF       string `json:\"FeelsLikeF\"`\n\t\t\tCloudcover       string `json:\"cloudcover\"`\n\t\t\tHumidity         string `json:\"humidity\"`\n\t\t\tLocalObsDateTime string `json:\"localObsDateTime\"`\n\t\t\tObservation_time string `json:\"observation_time\"`\n\t\t} `json:\"current_condition\"`\n\t}\n\n\terr := pbgo.HttpGet(\"http://wttr.in/wuhan?format=j1\", nil, \u0026reply)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tjson, err := json.MarshalIndent(reply, \"\", \"  \")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tfmt.Println(string(json))\n}\n```\n\n## Form Example\n\nCreate [example/form_pb/comment.proto](example/form_pb/comment.proto):\n\n```proto\nsyntax = \"proto3\";\npackage form_pb;\n\nmessage Comment {\n\tstring user = 1;\n\tstring email = 2;\n\tstring url = 3;\n\tstring text = 4;\n\tstring next = 5; // redirect\n}\n```\n\ngenerate proto code:\n\n```\n$ protoc -I=. --go_out=. comment.proto\n```\n\ncreate web server:\n\n```go\npackage main\n\nimport (\n\t\"github.com/chai2010/pbgo\"\n\t\"github.com/chai2010/pbgo/examples/form_pb\"\n\t\"github.com/julienschmidt/httprouter\"\n)\n\nfunc main() {\n\trouter := httprouter.New()\n\n\t// http://localhost:8080\n\trouter.GET(\"/\", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {\n\t\tw.Header().Add(\"Content-Type\", \"text/html; charset=utf-8\")\n\n\t\tfmt.Fprint(w, `\n\t\t\t\u003cform method=\"POST\" action=\"/api/comment\"\u003e\n\t\t\t\t\u003cinput type=\"text\" name=\"user\" value=\"user name\"\u003e\n\t\t\t\t\u003cinput type=\"email\" name=\"email\" value=\"123@gmail.com\"\u003e\n\t\t\t\t\u003cinput name=\"url\" value=\"http://chai2010.cn\"\u003e\u003c/textarea\u003e\n\t\t\t\t\u003ctextarea name=\"text\" value=\"text\"\u003ewww\u003c/textarea\u003e\n\t\t\t\t\u003cinput type=\"text\" name=\"next\" value=\"/thanks\"\u003e\n\t\t\t\t\u003cbutton type=\"submit\"\u003eSend Test\u003c/button\u003e\n\t\t\t\u003c/form\u003e\n\t\t`)\n\t})\n\n\trouter.GET(\"/thanks\", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {\n\t\tfmt.Fprintln(w, \"Thanks\")\n\t})\n\n\t// curl -d \"user=chai\u0026email=11@qq.com\u0026text=hello\u0026next=http://github.com\" localhost:8080/api/comment\n\trouter.POST(\"/api/comment\", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {\n\t\tvar form form_pb.Comment\n\t\tif err := pbgo.BindForm(r, \u0026form); err != nil {\n\t\t\thttp.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)\n\t\t\tlog.Println(\"err:\", err)\n\t\t\treturn\n\t\t}\n\n\t\tif form.Next != \"\" {\n\t\t\thttp.Redirect(w, r, form.Next, http.StatusFound)\n\t\t}\n\n\t\tlog.Println(\"form:\", form)\n\t})\n\n\tlog.Fatal(http.ListenAndServe(\":8080\", router))\n}\n```\n\n```\n$ curl -d \"user=chai\u0026email=11@qq.com\u0026text=hello\u0026next=http://github.com\" localhost:8080/api/comment-form\n{\"user\":\"chai\",\"email\":\"11@qq.com\",\"text\":\"hello\",\"next\":\"http://github.com\"}\n```\n\n## gRPC \u0026 Rest Example\n\nSee https://github.com/chai2010/pbgo-grpc\n\n## BUGS\n\nReport bugs to \u003cchaishushan@gmail.com\u003e.\n\nThanks!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchai2010%2Fpbgo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchai2010%2Fpbgo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchai2010%2Fpbgo/lists"}