import from micro
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -13,3 +13,4 @@
|
|||||||
|
|
||||||
# Dependency directories (remove the comment below to include it)
|
# Dependency directories (remove the comment below to include it)
|
||||||
# vendor/
|
# vendor/
|
||||||
|
/protoc-gen-micro
|
||||||
|
|||||||
139
README.md
139
README.md
@@ -1 +1,138 @@
|
|||||||
# protoc-gen-micro
|
# protoc-gen-micro
|
||||||
|
|
||||||
|
This is protobuf code generation for micro. We use protoc-gen-micro to reduce boilerplate code.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```
|
||||||
|
go get github.com/micro/micro/v3/cmd/protoc-gen-micro@master
|
||||||
|
```
|
||||||
|
|
||||||
|
Also required:
|
||||||
|
|
||||||
|
- [protoc](https://github.com/google/protobuf)
|
||||||
|
- [protoc-gen-go](https://github.com/golang/protobuf)
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Define your service as `greeter.proto`
|
||||||
|
|
||||||
|
```
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
service Greeter {
|
||||||
|
rpc Hello(Request) returns (Response) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
message Request {
|
||||||
|
string name = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Response {
|
||||||
|
string msg = 1;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Generate the code
|
||||||
|
|
||||||
|
```
|
||||||
|
protoc --proto_path=$GOPATH/src:. --micro_out=. --go_out=. greeter.proto
|
||||||
|
```
|
||||||
|
|
||||||
|
Your output result should be:
|
||||||
|
|
||||||
|
```
|
||||||
|
./
|
||||||
|
greeter.proto # original protobuf file
|
||||||
|
greeter.pb.go # auto-generated by protoc-gen-go
|
||||||
|
greeter.micro.go # auto-generated by protoc-gen-micro
|
||||||
|
```
|
||||||
|
|
||||||
|
The micro generated code includes clients and handlers which reduce boiler plate code
|
||||||
|
|
||||||
|
### Server
|
||||||
|
|
||||||
|
Register the handler with your micro server
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Greeter struct{}
|
||||||
|
|
||||||
|
func (g *Greeter) Hello(ctx context.Context, req *proto.Request, rsp *proto.Response) error {
|
||||||
|
rsp.Msg = "Hello " + req.Name
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
proto.RegisterGreeterHandler(service.Server(), &Greeter{})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Client
|
||||||
|
|
||||||
|
Create a service client with your micro client
|
||||||
|
|
||||||
|
```go
|
||||||
|
client := proto.NewGreeterService("greeter", service.Client())
|
||||||
|
```
|
||||||
|
|
||||||
|
### Errors
|
||||||
|
|
||||||
|
If you see an error about `protoc-gen-micro` not being found or executable, it's likely your environment may not be configured correctly. If you've already installed `protoc`, `protoc-gen-go`, and `protoc-gen-micro` ensure you've included `$GOPATH/bin` in your `PATH`.
|
||||||
|
|
||||||
|
Alternative specify the Go plugin paths as arguments to the `protoc` command
|
||||||
|
|
||||||
|
```
|
||||||
|
protoc --plugin=protoc-gen-go=$GOPATH/bin/protoc-gen-go --plugin=protoc-gen-micro=$GOPATH/bin/protoc-gen-micro --proto_path=$GOPATH/src:. --micro_out=. --go_out=. greeter.proto
|
||||||
|
```
|
||||||
|
|
||||||
|
### Endpoint
|
||||||
|
|
||||||
|
Add a micro API endpoint which routes directly to an RPC method
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
1. Clone `github.com/googleapis/googleapis` to use this feature as it requires http annotations.
|
||||||
|
2. The protoc command must include `-I$GOPATH/src/github.com/googleapis/googleapis` for the annotations import.
|
||||||
|
|
||||||
|
```diff
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
import "google/api/annotations.proto";
|
||||||
|
|
||||||
|
service Greeter {
|
||||||
|
rpc Hello(Request) returns (Response) {
|
||||||
|
option (google.api.http) = { post: "/hello"; body: "*"; };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message Request {
|
||||||
|
string name = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Response {
|
||||||
|
string msg = 1;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The proto generates a `RegisterGreeterHandler` function with a [api.Endpoint](https://godoc.org/github.com/micro/go-micro/api#Endpoint).
|
||||||
|
|
||||||
|
```diff
|
||||||
|
func RegisterGreeterHandler(s server.Server, hdlr GreeterHandler, opts ...server.HandlerOption) error {
|
||||||
|
type greeter interface {
|
||||||
|
Hello(ctx context.Context, in *Request, out *Response) error
|
||||||
|
}
|
||||||
|
type Greeter struct {
|
||||||
|
greeter
|
||||||
|
}
|
||||||
|
h := &greeterHandler{hdlr}
|
||||||
|
opts = append(opts, api.WithEndpoint(&api.Endpoint{
|
||||||
|
Name: "Greeter.Hello",
|
||||||
|
Path: []string{"/hello"},
|
||||||
|
Method: []string{"POST"},
|
||||||
|
Handler: "rpc",
|
||||||
|
}))
|
||||||
|
return s.Handle(s.NewHandler(&Greeter{h}, opts...))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## LICENSE
|
||||||
|
|
||||||
|
protoc-gen-micro is a liberal reuse of protoc-gen-go hence we maintain the original license
|
||||||
|
|||||||
40
generator/Makefile
Normal file
40
generator/Makefile
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# Go support for Protocol Buffers - Google's data interchange format
|
||||||
|
#
|
||||||
|
# Copyright 2010 The Go Authors. All rights reserved.
|
||||||
|
# https://github.com/golang/protobuf
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are
|
||||||
|
# met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# * Redistributions in binary form must reproduce the above
|
||||||
|
# copyright notice, this list of conditions and the following disclaimer
|
||||||
|
# in the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
# * Neither the name of Google Inc. nor the names of its
|
||||||
|
# contributors may be used to endorse or promote products derived from
|
||||||
|
# this software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
include $(GOROOT)/src/Make.inc
|
||||||
|
|
||||||
|
TARG=github.com/golang/protobuf/compiler/generator
|
||||||
|
GOFILES=\
|
||||||
|
generator.go\
|
||||||
|
|
||||||
|
DEPS=../descriptor ../plugin ../../proto
|
||||||
|
|
||||||
|
include $(GOROOT)/src/Make.pkg
|
||||||
2734
generator/generator.go
Normal file
2734
generator/generator.go
Normal file
File diff suppressed because it is too large
Load Diff
135
generator/name_test.go
Normal file
135
generator/name_test.go
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
// Go support for Protocol Buffers - Google's data interchange format
|
||||||
|
//
|
||||||
|
// Copyright 2013 The Go Authors. All rights reserved.
|
||||||
|
// https://github.com/golang/protobuf
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
package generator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCamelCase(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
in, want string
|
||||||
|
}{
|
||||||
|
{"one", "One"},
|
||||||
|
{"one_two", "OneTwo"},
|
||||||
|
{"_my_field_name_2", "XMyFieldName_2"},
|
||||||
|
{"Something_Capped", "Something_Capped"},
|
||||||
|
{"my_Name", "My_Name"},
|
||||||
|
{"OneTwo", "OneTwo"},
|
||||||
|
{"_", "X"},
|
||||||
|
{"_a_", "XA_"},
|
||||||
|
}
|
||||||
|
for _, tc := range tests {
|
||||||
|
if got := CamelCase(tc.in); got != tc.want {
|
||||||
|
t.Errorf("CamelCase(%q) = %q, want %q", tc.in, got, tc.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGoPackageOption(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
in string
|
||||||
|
impPath GoImportPath
|
||||||
|
pkg GoPackageName
|
||||||
|
ok bool
|
||||||
|
}{
|
||||||
|
{"", "", "", false},
|
||||||
|
{"foo", "", "foo", true},
|
||||||
|
{"github.com/golang/bar", "github.com/golang/bar", "bar", true},
|
||||||
|
{"github.com/golang/bar;baz", "github.com/golang/bar", "baz", true},
|
||||||
|
{"github.com/golang/string", "github.com/golang/string", "string", true},
|
||||||
|
}
|
||||||
|
for _, tc := range tests {
|
||||||
|
d := &FileDescriptor{
|
||||||
|
FileDescriptorProto: &descriptor.FileDescriptorProto{
|
||||||
|
Options: &descriptor.FileOptions{
|
||||||
|
GoPackage: &tc.in,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
impPath, pkg, ok := d.goPackageOption()
|
||||||
|
if impPath != tc.impPath || pkg != tc.pkg || ok != tc.ok {
|
||||||
|
t.Errorf("go_package = %q => (%q, %q, %t), want (%q, %q, %t)", tc.in,
|
||||||
|
impPath, pkg, ok, tc.impPath, tc.pkg, tc.ok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPackageNames(t *testing.T) {
|
||||||
|
g := New()
|
||||||
|
g.packageNames = make(map[GoImportPath]GoPackageName)
|
||||||
|
g.usedPackageNames = make(map[GoPackageName]bool)
|
||||||
|
for _, test := range []struct {
|
||||||
|
importPath GoImportPath
|
||||||
|
want GoPackageName
|
||||||
|
}{
|
||||||
|
{"github.com/golang/foo", "foo"},
|
||||||
|
{"github.com/golang/second/package/named/foo", "foo1"},
|
||||||
|
{"github.com/golang/third/package/named/foo", "foo2"},
|
||||||
|
{"github.com/golang/conflicts/with/predeclared/ident/string", "string1"},
|
||||||
|
} {
|
||||||
|
if got := g.GoPackageName(test.importPath); got != test.want {
|
||||||
|
t.Errorf("GoPackageName(%v) = %v, want %v", test.importPath, got, test.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnescape(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
in string
|
||||||
|
out string
|
||||||
|
}{
|
||||||
|
// successful cases, including all kinds of escapes
|
||||||
|
{"", ""},
|
||||||
|
{"foo bar baz frob nitz", "foo bar baz frob nitz"},
|
||||||
|
{`\000\001\002\003\004\005\006\007`, string([]byte{0, 1, 2, 3, 4, 5, 6, 7})},
|
||||||
|
{`\a\b\f\n\r\t\v\\\?\'\"`, string([]byte{'\a', '\b', '\f', '\n', '\r', '\t', '\v', '\\', '?', '\'', '"'})},
|
||||||
|
{`\x10\x20\x30\x40\x50\x60\x70\x80`, string([]byte{16, 32, 48, 64, 80, 96, 112, 128})},
|
||||||
|
// variable length octal escapes
|
||||||
|
{`\0\018\222\377\3\04\005\6\07`, string([]byte{0, 1, '8', 0222, 255, 3, 4, 5, 6, 7})},
|
||||||
|
// malformed escape sequences left as is
|
||||||
|
{"foo \\g bar", "foo \\g bar"},
|
||||||
|
{"foo \\xg0 bar", "foo \\xg0 bar"},
|
||||||
|
{"\\", "\\"},
|
||||||
|
{"\\x", "\\x"},
|
||||||
|
{"\\xf", "\\xf"},
|
||||||
|
{"\\777", "\\777"}, // overflows byte
|
||||||
|
}
|
||||||
|
for _, tc := range tests {
|
||||||
|
s := unescape(tc.in)
|
||||||
|
if s != tc.out {
|
||||||
|
t.Errorf("doUnescape(%q) = %q; should have been %q", tc.in, s, tc.out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
go.mod
Normal file
9
go.mod
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
module github.com/unistack-org/protoc-gen-micro
|
||||||
|
|
||||||
|
go 1.15
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/golang/protobuf v1.4.3
|
||||||
|
google.golang.org/genproto v0.0.0-20201112120144-2985b7af83de
|
||||||
|
google.golang.org/protobuf v1.25.0 // indirect
|
||||||
|
)
|
||||||
70
go.sum
Normal file
70
go.sum
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||||
|
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||||
|
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||||
|
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
||||||
|
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
|
||||||
|
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||||
|
google.golang.org/genproto v0.0.0-20201112120144-2985b7af83de h1:CX+Qqbzx3Yphy3fo9WOQIac7DqeBhqCWeSqSuH8ddL0=
|
||||||
|
google.golang.org/genproto v0.0.0-20201112120144-2985b7af83de/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
|
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
|
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
|
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||||
|
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||||
|
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||||
|
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||||
|
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
99
main.go
Normal file
99
main.go
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
// Go support for Protocol Buffers - Google's data interchange format
|
||||||
|
//
|
||||||
|
// Copyright 2010 The Go Authors. All rights reserved.
|
||||||
|
// https://github.com/golang/protobuf
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// protoc-gen-micro is a plugin for the Google protocol buffer compiler to generate
|
||||||
|
// Go code. Run it by building this program and putting it in your path with
|
||||||
|
// the name
|
||||||
|
// protoc-gen-micro
|
||||||
|
// That word 'micro' at the end becomes part of the option string set for the
|
||||||
|
// protocol compiler, so once the protocol compiler (protoc) is installed
|
||||||
|
// you can run
|
||||||
|
// protoc --micro_out=output_directory --go_out=output_directory input_directory/file.proto
|
||||||
|
// to generate go-micro code for the protocol defined by file.proto.
|
||||||
|
// With that input, the output will be written to
|
||||||
|
// output_directory/file.micro.go
|
||||||
|
//
|
||||||
|
// The generated code is documented in the package comment for
|
||||||
|
// the library.
|
||||||
|
//
|
||||||
|
// See the README and documentation for protocol buffers to learn more:
|
||||||
|
// https://developers.google.com/protocol-buffers/
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
"github.com/unistack-org/protoc-gen-micro/generator"
|
||||||
|
_ "github.com/unistack-org/protoc-gen-micro/plugin/micro"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Begin by allocating a generator. The request and response structures are stored there
|
||||||
|
// so we can do error handling easily - the response structure contains the field to
|
||||||
|
// report failure.
|
||||||
|
g := generator.New()
|
||||||
|
|
||||||
|
data, err := ioutil.ReadAll(os.Stdin)
|
||||||
|
if err != nil {
|
||||||
|
g.Error(err, "reading input")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := proto.Unmarshal(data, g.Request); err != nil {
|
||||||
|
g.Error(err, "parsing input proto")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(g.Request.FileToGenerate) == 0 {
|
||||||
|
g.Fail("no files to generate")
|
||||||
|
}
|
||||||
|
|
||||||
|
g.CommandLineParameters(g.Request.GetParameter())
|
||||||
|
|
||||||
|
// Create a wrapped version of the Descriptors and EnumDescriptors that
|
||||||
|
// point to the file that defines them.
|
||||||
|
g.WrapTypes()
|
||||||
|
|
||||||
|
g.SetPackageNames()
|
||||||
|
g.BuildTypeNameMap()
|
||||||
|
|
||||||
|
g.GenerateAllFiles()
|
||||||
|
|
||||||
|
// Send back the results.
|
||||||
|
data, err = proto.Marshal(g.Response)
|
||||||
|
if err != nil {
|
||||||
|
g.Error(err, "failed to marshal output proto")
|
||||||
|
}
|
||||||
|
_, err = os.Stdout.Write(data)
|
||||||
|
if err != nil {
|
||||||
|
g.Error(err, "failed to write output proto")
|
||||||
|
}
|
||||||
|
}
|
||||||
583
plugin/micro/micro.go
Normal file
583
plugin/micro/micro.go
Normal file
@@ -0,0 +1,583 @@
|
|||||||
|
package micro
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"path"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
pb "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||||
|
"github.com/unistack-org/protoc-gen-micro/generator"
|
||||||
|
options "google.golang.org/genproto/googleapis/api/annotations"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Paths for packages used by code generated in this file,
|
||||||
|
// relative to the import_prefix of the generator.Generator.
|
||||||
|
const (
|
||||||
|
apiPkgPath = "github.com/unistack-org/micro/v3/api"
|
||||||
|
contextPkgPath = "context"
|
||||||
|
clientPkgPath = "github.com/unistack-org/micro/v3/client"
|
||||||
|
serverPkgPath = "github.com/unistack-org/micro/v3/server"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
generator.RegisterPlugin(new(micro))
|
||||||
|
}
|
||||||
|
|
||||||
|
// micro is an implementation of the Go protocol buffer compiler's
|
||||||
|
// plugin architecture. It generates bindings for go-micro support.
|
||||||
|
type micro struct {
|
||||||
|
gen *generator.Generator
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns the name of this plugin, "micro".
|
||||||
|
func (g *micro) Name() string {
|
||||||
|
return "micro"
|
||||||
|
}
|
||||||
|
|
||||||
|
// The names for packages imported in the generated code.
|
||||||
|
// They may vary from the final path component of the import path
|
||||||
|
// if the name is used by other packages.
|
||||||
|
var (
|
||||||
|
apiPkg string
|
||||||
|
contextPkg string
|
||||||
|
clientPkg string
|
||||||
|
serverPkg string
|
||||||
|
pkgImports map[generator.GoPackageName]bool
|
||||||
|
)
|
||||||
|
|
||||||
|
// Init initializes the plugin.
|
||||||
|
func (g *micro) Init(gen *generator.Generator) {
|
||||||
|
g.gen = gen
|
||||||
|
apiPkg = generator.RegisterUniquePackageName("api", nil)
|
||||||
|
contextPkg = generator.RegisterUniquePackageName("context", nil)
|
||||||
|
clientPkg = generator.RegisterUniquePackageName("client", nil)
|
||||||
|
serverPkg = generator.RegisterUniquePackageName("server", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given a type name defined in a .proto, return its object.
|
||||||
|
// Also record that we're using it, to guarantee the associated import.
|
||||||
|
func (g *micro) objectNamed(name string) generator.Object {
|
||||||
|
g.gen.RecordTypeUse(name)
|
||||||
|
return g.gen.ObjectNamed(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given a type name defined in a .proto, return its name as we will print it.
|
||||||
|
func (g *micro) typeName(str string) string {
|
||||||
|
return g.gen.TypeName(g.objectNamed(str))
|
||||||
|
}
|
||||||
|
|
||||||
|
// P forwards to g.gen.P.
|
||||||
|
func (g *micro) P(args ...interface{}) { g.gen.P(args...) }
|
||||||
|
|
||||||
|
// Generate generates code for the services in the given file.
|
||||||
|
func (g *micro) Generate(file *generator.FileDescriptor) {
|
||||||
|
if len(file.FileDescriptorProto.Service) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
g.P("// Reference imports to suppress errors if they are not otherwise used.")
|
||||||
|
g.P("var _ ", apiPkg, ".Endpoint")
|
||||||
|
g.P("var _ ", contextPkg, ".Context")
|
||||||
|
g.P("var _ ", clientPkg, ".Option")
|
||||||
|
g.P("var _ ", serverPkg, ".Option")
|
||||||
|
g.P()
|
||||||
|
|
||||||
|
for i, service := range file.FileDescriptorProto.Service {
|
||||||
|
g.generateService(file, service, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateImports generates the import declaration for this file.
|
||||||
|
func (g *micro) GenerateImports(file *generator.FileDescriptor, imports map[generator.GoImportPath]generator.GoPackageName) {
|
||||||
|
if len(file.FileDescriptorProto.Service) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
g.P("import (")
|
||||||
|
g.P(apiPkg, " ", strconv.Quote(path.Join(g.gen.ImportPrefix, apiPkgPath)))
|
||||||
|
g.P(contextPkg, " ", strconv.Quote(path.Join(g.gen.ImportPrefix, contextPkgPath)))
|
||||||
|
g.P(clientPkg, " ", strconv.Quote(path.Join(g.gen.ImportPrefix, clientPkgPath)))
|
||||||
|
g.P(serverPkg, " ", strconv.Quote(path.Join(g.gen.ImportPrefix, serverPkgPath)))
|
||||||
|
g.P(")")
|
||||||
|
g.P()
|
||||||
|
|
||||||
|
// We need to keep track of imported packages to make sure we don't produce
|
||||||
|
// a name collision when generating types.
|
||||||
|
pkgImports = make(map[generator.GoPackageName]bool)
|
||||||
|
for _, name := range imports {
|
||||||
|
pkgImports[name] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// reservedClientName records whether a client name is reserved on the client side.
|
||||||
|
var reservedClientName = map[string]bool{
|
||||||
|
// TODO: do we need any in go-micro?
|
||||||
|
}
|
||||||
|
|
||||||
|
func unexport(s string) string {
|
||||||
|
if len(s) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
name := strings.ToLower(s[:1]) + s[1:]
|
||||||
|
if pkgImports[generator.GoPackageName(name)] {
|
||||||
|
return name + "_"
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateService generates all the code for the named service.
|
||||||
|
func (g *micro) generateService(file *generator.FileDescriptor, service *pb.ServiceDescriptorProto, index int) {
|
||||||
|
path := fmt.Sprintf("6,%d", index) // 6 means service.
|
||||||
|
|
||||||
|
origServName := service.GetName()
|
||||||
|
serviceName := strings.ToLower(service.GetName())
|
||||||
|
if pkg := file.GetPackage(); pkg != "" {
|
||||||
|
serviceName = pkg
|
||||||
|
}
|
||||||
|
servName := generator.CamelCase(origServName)
|
||||||
|
servAlias := servName + "Service"
|
||||||
|
|
||||||
|
// strip suffix
|
||||||
|
if strings.HasSuffix(servAlias, "ServiceService") {
|
||||||
|
servAlias = strings.TrimSuffix(servAlias, "Service")
|
||||||
|
}
|
||||||
|
|
||||||
|
g.P()
|
||||||
|
g.P("// Api Endpoints for ", servName, " service")
|
||||||
|
g.P()
|
||||||
|
|
||||||
|
g.P("func New", servName, "Endpoints () []*", apiPkg, ".Endpoint {")
|
||||||
|
g.P("return []*", apiPkg, ".Endpoint{")
|
||||||
|
for _, method := range service.Method {
|
||||||
|
if method.Options != nil && proto.HasExtension(method.Options, options.E_Http) {
|
||||||
|
g.P("&", apiPkg, ".Endpoint{")
|
||||||
|
g.generateEndpoint(servName, method)
|
||||||
|
g.P("},")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.P("}")
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
|
||||||
|
g.P()
|
||||||
|
g.P("// Client API for ", servName, " service")
|
||||||
|
g.P()
|
||||||
|
|
||||||
|
// Client interface.
|
||||||
|
g.P("type ", servAlias, " interface {")
|
||||||
|
for i, method := range service.Method {
|
||||||
|
g.gen.PrintComments(fmt.Sprintf("%s,2,%d", path, i)) // 2 means method in a service.
|
||||||
|
g.P(g.generateClientSignature(servName, method))
|
||||||
|
}
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
|
||||||
|
// Client structure.
|
||||||
|
g.P("type ", unexport(servAlias), " struct {")
|
||||||
|
g.P("c ", clientPkg, ".Client")
|
||||||
|
g.P("name string")
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
|
||||||
|
// NewClient factory.
|
||||||
|
g.P("func New", servAlias, " (name string, c ", clientPkg, ".Client) ", servAlias, " {")
|
||||||
|
/*
|
||||||
|
g.P("if c == nil {")
|
||||||
|
g.P("c = ", clientPkg, ".NewClient()")
|
||||||
|
g.P("}")
|
||||||
|
g.P("if len(name) == 0 {")
|
||||||
|
g.P(`name = "`, serviceName, `"`)
|
||||||
|
g.P("}")
|
||||||
|
*/
|
||||||
|
g.P("return &", unexport(servAlias), "{")
|
||||||
|
g.P("c: c,")
|
||||||
|
g.P("name: name,")
|
||||||
|
g.P("}")
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
var methodIndex, streamIndex int
|
||||||
|
serviceDescVar := "_" + servName + "_serviceDesc"
|
||||||
|
// Client method implementations.
|
||||||
|
for _, method := range service.Method {
|
||||||
|
var descExpr string
|
||||||
|
if !method.GetServerStreaming() {
|
||||||
|
// Unary RPC method
|
||||||
|
descExpr = fmt.Sprintf("&%s.Methods[%d]", serviceDescVar, methodIndex)
|
||||||
|
methodIndex++
|
||||||
|
} else {
|
||||||
|
// Streaming RPC method
|
||||||
|
descExpr = fmt.Sprintf("&%s.Streams[%d]", serviceDescVar, streamIndex)
|
||||||
|
streamIndex++
|
||||||
|
}
|
||||||
|
g.generateClientMethod(serviceName, servName, serviceDescVar, method, descExpr)
|
||||||
|
}
|
||||||
|
|
||||||
|
g.P("// Server API for ", servName, " service")
|
||||||
|
g.P()
|
||||||
|
|
||||||
|
// Server interface.
|
||||||
|
serverType := servName + "Handler"
|
||||||
|
g.P("type ", serverType, " interface {")
|
||||||
|
for i, method := range service.Method {
|
||||||
|
g.gen.PrintComments(fmt.Sprintf("%s,2,%d", path, i)) // 2 means method in a service.
|
||||||
|
g.P(g.generateServerSignature(servName, method))
|
||||||
|
}
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
|
||||||
|
// Server registration.
|
||||||
|
g.P("func Register", servName, "Handler(s ", serverPkg, ".Server, hdlr ", serverType, ", opts ...", serverPkg, ".HandlerOption) error {")
|
||||||
|
g.P("type ", unexport(servName), " interface {")
|
||||||
|
|
||||||
|
// generate interface methods
|
||||||
|
for _, method := range service.Method {
|
||||||
|
methName := generator.CamelCase(method.GetName())
|
||||||
|
inType := g.typeName(method.GetInputType())
|
||||||
|
outType := g.typeName(method.GetOutputType())
|
||||||
|
|
||||||
|
if !method.GetServerStreaming() && !method.GetClientStreaming() {
|
||||||
|
g.P(methName, "(ctx ", contextPkg, ".Context, req *", inType, ", rsp *", outType, ") error")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
g.P(methName, "(ctx ", contextPkg, ".Context, stream server.Stream) error")
|
||||||
|
}
|
||||||
|
g.P("}")
|
||||||
|
g.P("type ", servName, " struct {")
|
||||||
|
g.P(unexport(servName))
|
||||||
|
g.P("}")
|
||||||
|
g.P("h := &", unexport(servName), "Handler{hdlr}")
|
||||||
|
for _, method := range service.Method {
|
||||||
|
if method.Options != nil && proto.HasExtension(method.Options, options.E_Http) {
|
||||||
|
g.P("opts = append(opts, ", apiPkg, ".WithEndpoint(&", apiPkg, ".Endpoint{")
|
||||||
|
g.generateEndpoint(servName, method)
|
||||||
|
g.P("}))")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.P("return s.Handle(s.NewHandler(&", servName, "{h}, opts...))")
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
|
||||||
|
g.P("type ", unexport(servName), "Handler struct {")
|
||||||
|
g.P(serverType)
|
||||||
|
g.P("}")
|
||||||
|
|
||||||
|
// Server handler implementations.
|
||||||
|
var handlerNames []string
|
||||||
|
for _, method := range service.Method {
|
||||||
|
hname := g.generateServerMethod(servName, method)
|
||||||
|
handlerNames = append(handlerNames, hname)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateEndpoint creates the api endpoint
|
||||||
|
func (g *micro) generateEndpoint(servName string, method *pb.MethodDescriptorProto) {
|
||||||
|
if method.Options == nil || !proto.HasExtension(method.Options, options.E_Http) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// http rules
|
||||||
|
r, err := proto.GetExtension(method.Options, options.E_Http)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rule := r.(*options.HttpRule)
|
||||||
|
var meth string
|
||||||
|
var path string
|
||||||
|
switch {
|
||||||
|
case len(rule.GetDelete()) > 0:
|
||||||
|
meth = "DELETE"
|
||||||
|
path = rule.GetDelete()
|
||||||
|
case len(rule.GetGet()) > 0:
|
||||||
|
meth = "GET"
|
||||||
|
path = rule.GetGet()
|
||||||
|
case len(rule.GetPatch()) > 0:
|
||||||
|
meth = "PATCH"
|
||||||
|
path = rule.GetPatch()
|
||||||
|
case len(rule.GetPost()) > 0:
|
||||||
|
meth = "POST"
|
||||||
|
path = rule.GetPost()
|
||||||
|
case len(rule.GetPut()) > 0:
|
||||||
|
meth = "PUT"
|
||||||
|
path = rule.GetPut()
|
||||||
|
}
|
||||||
|
if len(meth) == 0 || len(path) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// TODO: process additional bindings
|
||||||
|
g.P("Name:", fmt.Sprintf(`"%s.%s",`, servName, method.GetName()))
|
||||||
|
g.P("Path:", fmt.Sprintf(`[]string{"%s"},`, path))
|
||||||
|
g.P("Method:", fmt.Sprintf(`[]string{"%s"},`, meth))
|
||||||
|
if len(rule.GetGet()) == 0 {
|
||||||
|
g.P("Body:", fmt.Sprintf(`"%s",`, rule.GetBody()))
|
||||||
|
}
|
||||||
|
if method.GetServerStreaming() || method.GetClientStreaming() {
|
||||||
|
g.P("Stream: true,")
|
||||||
|
}
|
||||||
|
g.P(`Handler: "rpc",`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateClientSignature returns the client-side signature for a method.
|
||||||
|
func (g *micro) generateClientSignature(servName string, method *pb.MethodDescriptorProto) string {
|
||||||
|
origMethName := method.GetName()
|
||||||
|
methName := generator.CamelCase(origMethName)
|
||||||
|
if reservedClientName[methName] {
|
||||||
|
methName += "_"
|
||||||
|
}
|
||||||
|
reqArg := ", req *" + g.typeName(method.GetInputType())
|
||||||
|
if method.GetClientStreaming() {
|
||||||
|
reqArg = ""
|
||||||
|
}
|
||||||
|
respName := "*" + g.typeName(method.GetOutputType())
|
||||||
|
if method.GetServerStreaming() || method.GetClientStreaming() {
|
||||||
|
respName = servName + "_" + generator.CamelCase(origMethName) + "Service"
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s(ctx %s.Context%s, opts ...%s.CallOption) (%s, error)", methName, contextPkg, reqArg, clientPkg, respName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *micro) generateClientMethod(reqServ, servName, serviceDescVar string, method *pb.MethodDescriptorProto, descExpr string) {
|
||||||
|
methName := generator.CamelCase(method.GetName())
|
||||||
|
reqMethod := fmt.Sprintf("%s.%s", servName, methName)
|
||||||
|
inType := g.typeName(method.GetInputType())
|
||||||
|
outType := g.typeName(method.GetOutputType())
|
||||||
|
|
||||||
|
servAlias := servName + "Service"
|
||||||
|
|
||||||
|
// strip suffix
|
||||||
|
if strings.HasSuffix(servAlias, "ServiceService") {
|
||||||
|
servAlias = strings.TrimSuffix(servAlias, "Service")
|
||||||
|
}
|
||||||
|
|
||||||
|
g.P("func (c *", unexport(servAlias), ") ", g.generateClientSignature(servName, method), "{")
|
||||||
|
if !method.GetServerStreaming() && !method.GetClientStreaming() {
|
||||||
|
g.P("rsp := &", outType, "{}")
|
||||||
|
// TODO: Pass descExpr to Invoke.
|
||||||
|
g.P(`err := c.c.Call(ctx, c.c.NewRequest(c.name, "`, reqMethod, `", req), rsp, opts...)`)
|
||||||
|
g.P("if err != nil { return nil, err }")
|
||||||
|
g.P("return rsp, nil")
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
streamType := unexport(servAlias) + methName
|
||||||
|
g.P(`stream, err := c.c.Stream(ctx, c.c.NewRequest(c.name, "`, reqMethod, `", &`, inType, `{}), opts...)`)
|
||||||
|
g.P("if err != nil { return nil, err }")
|
||||||
|
|
||||||
|
if !method.GetClientStreaming() {
|
||||||
|
g.P("if err := stream.Send(req); err != nil { return nil, err }")
|
||||||
|
}
|
||||||
|
|
||||||
|
g.P("return &", streamType, "{stream}, nil")
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
|
||||||
|
genSend := method.GetClientStreaming()
|
||||||
|
genRecv := method.GetServerStreaming()
|
||||||
|
|
||||||
|
// Stream auxiliary types and methods.
|
||||||
|
g.P("type ", servName, "_", methName, "Service interface {")
|
||||||
|
g.P("Context() context.Context")
|
||||||
|
g.P("SendMsg(interface{}) error")
|
||||||
|
g.P("RecvMsg(interface{}) error")
|
||||||
|
|
||||||
|
if genSend && !genRecv {
|
||||||
|
// client streaming, the server will send a response upon close
|
||||||
|
g.P("CloseAndRecv() (*", outType, ", error)")
|
||||||
|
}
|
||||||
|
g.P("Close() error")
|
||||||
|
|
||||||
|
if genSend {
|
||||||
|
g.P("Send(*", inType, ") error")
|
||||||
|
}
|
||||||
|
if genRecv {
|
||||||
|
g.P("Recv() (*", outType, ", error)")
|
||||||
|
}
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
|
||||||
|
g.P("type ", streamType, " struct {")
|
||||||
|
g.P("stream ", clientPkg, ".Stream")
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
|
||||||
|
if genSend && !genRecv {
|
||||||
|
// client streaming, the server will send a response upon close
|
||||||
|
g.P("func (x *", streamType, ") CloseAndRecv() (*", outType, ", error) {")
|
||||||
|
g.P("if err := x.stream.Close(); err != nil {")
|
||||||
|
g.P("return nil, err")
|
||||||
|
g.P("}")
|
||||||
|
g.P("r := new(", outType, ")")
|
||||||
|
g.P("err := x.RecvMsg(r)")
|
||||||
|
g.P("return r, err")
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
}
|
||||||
|
g.P("func (x *", streamType, ") Close() error {")
|
||||||
|
g.P("return x.stream.Close()")
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
|
||||||
|
g.P("func (x *", streamType, ") Context() context.Context {")
|
||||||
|
g.P("return x.stream.Context()")
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
|
||||||
|
g.P("func (x *", streamType, ") SendMsg(m interface{}) error {")
|
||||||
|
g.P("return x.stream.Send(m)")
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
|
||||||
|
g.P("func (x *", streamType, ") RecvMsg(m interface{}) error {")
|
||||||
|
g.P("return x.stream.Recv(m)")
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
|
||||||
|
if genSend {
|
||||||
|
g.P("func (x *", streamType, ") Send(m *", inType, ") error {")
|
||||||
|
g.P("return x.stream.Send(m)")
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if genRecv {
|
||||||
|
g.P("func (x *", streamType, ") Recv() (*", outType, ", error) {")
|
||||||
|
g.P("m := &", outType, "{}")
|
||||||
|
g.P("err := x.stream.Recv(m)")
|
||||||
|
g.P("if err != nil {")
|
||||||
|
g.P("return nil, err")
|
||||||
|
g.P("}")
|
||||||
|
g.P("return m, nil")
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateServerSignature returns the server-side signature for a method.
|
||||||
|
func (g *micro) generateServerSignature(servName string, method *pb.MethodDescriptorProto) string {
|
||||||
|
origMethName := method.GetName()
|
||||||
|
methName := generator.CamelCase(origMethName)
|
||||||
|
if reservedClientName[methName] {
|
||||||
|
methName += "_"
|
||||||
|
}
|
||||||
|
|
||||||
|
var reqArgs []string
|
||||||
|
ret := "error"
|
||||||
|
reqArgs = append(reqArgs, contextPkg+".Context")
|
||||||
|
|
||||||
|
if !method.GetClientStreaming() {
|
||||||
|
reqArgs = append(reqArgs, "*"+g.typeName(method.GetInputType()))
|
||||||
|
}
|
||||||
|
if method.GetServerStreaming() || method.GetClientStreaming() {
|
||||||
|
reqArgs = append(reqArgs, servName+"_"+generator.CamelCase(origMethName)+"Stream")
|
||||||
|
}
|
||||||
|
if !method.GetClientStreaming() && !method.GetServerStreaming() {
|
||||||
|
reqArgs = append(reqArgs, "*"+g.typeName(method.GetOutputType()))
|
||||||
|
}
|
||||||
|
return methName + "(" + strings.Join(reqArgs, ", ") + ") " + ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *micro) generateServerMethod(servName string, method *pb.MethodDescriptorProto) string {
|
||||||
|
methName := generator.CamelCase(method.GetName())
|
||||||
|
hname := fmt.Sprintf("_%s_%s_Handler", servName, methName)
|
||||||
|
serveType := servName + "Handler"
|
||||||
|
inType := g.typeName(method.GetInputType())
|
||||||
|
outType := g.typeName(method.GetOutputType())
|
||||||
|
|
||||||
|
if !method.GetServerStreaming() && !method.GetClientStreaming() {
|
||||||
|
g.P("func (h *", unexport(servName), "Handler) ", methName, "(ctx ", contextPkg, ".Context, req *", inType, ", rsp *", outType, ") error {")
|
||||||
|
g.P("return h.", serveType, ".", methName, "(ctx, req, rsp)")
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
return hname
|
||||||
|
}
|
||||||
|
streamType := unexport(servName) + methName + "Stream"
|
||||||
|
g.P("func (h *", unexport(servName), "Handler) ", methName, "(ctx ", contextPkg, ".Context, stream server.Stream) error {")
|
||||||
|
if !method.GetClientStreaming() {
|
||||||
|
g.P("m := &", inType, "{}")
|
||||||
|
g.P("if err := stream.Recv(m); err != nil { return err }")
|
||||||
|
g.P("return h.", serveType, ".", methName, "(ctx, m, &", streamType, "{stream})")
|
||||||
|
} else {
|
||||||
|
g.P("return h.", serveType, ".", methName, "(ctx, &", streamType, "{stream})")
|
||||||
|
}
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
|
||||||
|
genSend := method.GetServerStreaming()
|
||||||
|
genRecv := method.GetClientStreaming()
|
||||||
|
|
||||||
|
// Stream auxiliary types and methods.
|
||||||
|
g.P("type ", servName, "_", methName, "Stream interface {")
|
||||||
|
g.P("Context() context.Context")
|
||||||
|
g.P("SendMsg(interface{}) error")
|
||||||
|
g.P("RecvMsg(interface{}) error")
|
||||||
|
if !genSend {
|
||||||
|
// client streaming, the server will send a response upon close
|
||||||
|
g.P("SendAndClose(*", outType, ") error")
|
||||||
|
}
|
||||||
|
g.P("Close() error")
|
||||||
|
|
||||||
|
if genSend {
|
||||||
|
g.P("Send(*", outType, ") error")
|
||||||
|
}
|
||||||
|
|
||||||
|
if genRecv {
|
||||||
|
g.P("Recv() (*", inType, ", error)")
|
||||||
|
}
|
||||||
|
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
|
||||||
|
g.P("type ", streamType, " struct {")
|
||||||
|
g.P("stream ", serverPkg, ".Stream")
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
|
||||||
|
if !genSend {
|
||||||
|
// client streaming, the server will send a response upon close
|
||||||
|
g.P("func (x *", streamType, ") SendAndClose(in *", outType, ") error {")
|
||||||
|
g.P("if err := x.SendMsg(in); err != nil {")
|
||||||
|
g.P("return err")
|
||||||
|
g.P("}")
|
||||||
|
g.P("return x.stream.Close()")
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
}
|
||||||
|
// other types of rpc don't send a response when the stream closes
|
||||||
|
g.P("func (x *", streamType, ") Close() error {")
|
||||||
|
g.P("return x.stream.Close()")
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
|
||||||
|
g.P("func (x *", streamType, ") Context() context.Context {")
|
||||||
|
g.P("return x.stream.Context()")
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
|
||||||
|
g.P("func (x *", streamType, ") SendMsg(m interface{}) error {")
|
||||||
|
g.P("return x.stream.Send(m)")
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
|
||||||
|
g.P("func (x *", streamType, ") RecvMsg(m interface{}) error {")
|
||||||
|
g.P("return x.stream.Recv(m)")
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
|
||||||
|
if genSend {
|
||||||
|
g.P("func (x *", streamType, ") Send(m *", outType, ") error {")
|
||||||
|
g.P("return x.stream.Send(m)")
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
}
|
||||||
|
|
||||||
|
if genRecv {
|
||||||
|
g.P("func (x *", streamType, ") Recv() (*", inType, ", error) {")
|
||||||
|
g.P("m := &", inType, "{}")
|
||||||
|
g.P("if err := x.stream.Recv(m); err != nil { return nil, err }")
|
||||||
|
g.P("return m, nil")
|
||||||
|
g.P("}")
|
||||||
|
g.P()
|
||||||
|
}
|
||||||
|
|
||||||
|
return hname
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user