Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow *.orion.pb.go files to access the exported-service-desc from *.pb.go #189

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 81 additions & 10 deletions protoc-gen-orion/orion.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,10 @@ type commentsInfo struct {
}

type data struct {
FileName string
PackageName string
Services []*service
FileName string
PackageName string
GoPackagePath string
Services []*service
}

type service struct {
Expand Down Expand Up @@ -96,13 +97,21 @@ type orionMiddleware struct {
Names string
}

type ProtocParams struct {
StandaloneMode bool
ExportedServiceDesc bool
}

var tmpl = `// Code generated by protoc-gen-orion. DO NOT EDIT.
// source: {{ .FileName }}

package {{ .PackageName }}
{{ if .Services }}
import (
orion "github.com/carousell/Orion/orion"
{{- if .GoPackagePath}}
{{ .PackageName }} "{{ .GoPackagePath }}"
{{- end }}
)

// If you see error please update your orion-protoc-gen by running 'go get -u github.com/carousell/Orion/protoc-gen-orion'
Expand Down Expand Up @@ -131,7 +140,7 @@ func Register{{.SvcName}}{{.MethodName}}Decoder(svr orion.Server, decoder orion.
orion.RegisterDecoder(svr, "{{.SvcName}}", "{{.MethodName}}", decoder)
}
{{ end }}
//Streams
// Streams
{{ range .Streams }}
// {{ . }}
{{ end }}
Expand Down Expand Up @@ -199,14 +208,19 @@ func main() {
filesToGenerate[v] = true
}

reqParams, err := parseProtocParams(request.GetParameter())
if err != nil {
logError(err, "parse protoc params")
}

response := new(plugin.CodeGeneratorResponse)
response.File = make([]*plugin.CodeGeneratorResponse_File, 0)

for _, file := range request.GetProtoFile() {
if _, ok := filesToGenerate[file.GetName()]; ok {
// check if file has any service
if len(file.Service) > 0 {
f := generateFile(populate(file))
f := generateFile(populate(file, reqParams))
response.File = append(response.File, f)
}
}
Expand Down Expand Up @@ -242,24 +256,26 @@ func generateFile(d *data) *plugin.CodeGeneratorResponse_File {
return file
}

func populate(file *descriptor.FileDescriptorProto) *data {
func populate(file *descriptor.FileDescriptorProto, params ProtocParams) *data {
d := new(data)
d.FileName = *file.Name
d.PackageName = strings.Replace(file.GetPackage(), ".", "_", 10)

if params.StandaloneMode {
d.GoPackagePath = parseGoPackage(file.GetOptions().GetGoPackage())
}
d.Services = make([]*service, 0)
generate(d, file)
generate(d, file, params)

return d
}

func generate(d *data, file *descriptor.FileDescriptorProto) {
func generate(d *data, file *descriptor.FileDescriptorProto, params ProtocParams) {
comments := extractComments(file)
for index, svc := range file.GetService() {

origServName := svc.GetName()
servName := generator.CamelCase(origServName) // use the same logic from go-grpc generator
serviceDescVar := "_" + servName + "_serviceDesc"
serviceDescVar := getServiceDescVar(d.PackageName, servName, params.ExportedServiceDesc, params.StandaloneMode)

s := new(service)
s.Encoders = make([]*encoder, 0)
Expand Down Expand Up @@ -430,3 +446,58 @@ func extractComments(file *descriptor.FileDescriptorProto) map[string]*descripto
}
return comments
}

func parseProtocParams(reqParam string) (ProtocParams, error) {
pp := ProtocParams{}
for _, param := range strings.Split(reqParam, ",") {
var value string
if i := strings.Index(param, "="); i >= 0 {
value = param[i+1:]
param = param[0:i]
}
switch param {
case "standalone-mode":
boolValue, err := parseBoolValue(value)
if err != nil {
return ProtocParams{}, fmt.Errorf(`bad value for parameter %q: %w`, param, err)
}
pp.StandaloneMode = boolValue
case "exported-service-desc":
boolValue, err := parseBoolValue(value)
if err != nil {
return ProtocParams{}, fmt.Errorf(`bad value for parameter %q: %w`, param, err)
}
pp.ExportedServiceDesc = boolValue
}
}
return pp, nil
}

func parseBoolValue(value string) (bool, error) {
switch value {
case "true":
return true, nil
case "false":
return false, nil
default:
return false, fmt.Errorf(`want "true" or "false"`)
}
}

func getServiceDescVar(packageName string, serviceName string, exportedServiceDesc bool, standAlone bool) string {
if standAlone {
return packageName + "." + serviceName + "_ServiceDesc"
}
if exportedServiceDesc {
return serviceName + "_ServiceDesc"
}
return "_" + serviceName + "_serviceDesc"
}

func parseGoPackage(goPackage string) string {
parts := strings.Split(goPackage, ";")
if len(parts) == 0 {
return ""
}
return parts[0]
}
15 changes: 15 additions & 0 deletions protoc-gen-orion/testprotos/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Generate the *.orion.pb.go into each folder.
# The generated files shouldn't be changed, unless you change the orion template format.
# Notice: Before running the script, you should install the testing binary of protoc-gen-orion in your device.
all:
# The default protoc-gen-orion will provide the unexported-service-desc.
# It's suitable for protoc-gen-go version lower and equal than v1.5.2
protoc --orion_out="." example/example.proto

# For protoc-gen-go version higher and equal than v1.20.0, please enable the exported-service-desc option.
protoc --orion_out="exported-service-desc=true:." exported_service_desc/example.proto

# Enable the standalone-mode option will allow your to place *.orion.pb.go and *.pb.go into different folder.
# The *.orion.pb.go imports the *.pb.go by go_package defined in *.proto.
protoc --orion_out="standalone-mode=true:." standalone_mode/example.proto
mv standalone_mode/example.proto.orion.pb.go standalone_mode/orion/
5 changes: 5 additions & 0 deletions protoc-gen-orion/testprotos/example/example.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package example

import "google.golang.org/grpc"

var _ExampleService_serviceDesc grpc.ServiceDesc
37 changes: 37 additions & 0 deletions protoc-gen-orion/testprotos/example/example.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
syntax = "proto3";

package example;

option go_package = "github.com/carousell/Orion/protoc-gen-orion/testprotos/example;example";

service ExampleService {
// Normal endpoint
rpc NormalGet(GetRequest) returns (GetResponse);

// HTTP endpoint
// ORION:URL: GET /example
rpc HttpGet(GetRequest) returns (GetResponse);

// HTTP endpoint with middleware
// ORION:URL: GET /auth/example
// ORION:MIDDLEWRE: auth
rpc AuthGet(GetRequest) returns (GetResponse);

// HTTP endpoint with middleware
// ORION:URL: GET /option/example
// ORION:OPTION: IGNORE_NR
rpc OptionGet(GetRequest) returns (GetResponse);

// HTTP endpoint with options
// ORION:URL: GET /auth/option/example
// ORION:MIDDLEWRE: auth
// ORION:OPTION: IGNORE_NR
rpc AuthOptionGet(GetRequest) returns (GetResponse);

// ORION:URL: GET /stream/example
rpc StreamGet(stream GetRequest) returns (stream GetResponse);
}

message GetRequest {}

message GetResponse {}
113 changes: 113 additions & 0 deletions protoc-gen-orion/testprotos/example/example.proto.orion.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package example

import "google.golang.org/grpc"

var ExampleService_ServiceDesc grpc.ServiceDesc
14 changes: 14 additions & 0 deletions protoc-gen-orion/testprotos/exported_service_desc/example.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
syntax = "proto3";

package example;

option go_package = "github.com/carousell/Orion/protoc-gen-orion/testprotos/exported_service_desc;example";

service ExampleService {
// Normal endpoint
rpc NormalGet(GetRequest) returns (GetResponse);
}

message GetRequest {}

message GetResponse {}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading