Protobuf (gRPC) Code Generator for Go Creating Invalid Code - go

Everything works when I have my proto file defining a service with a streaming response. However when I return a single value, then the generated code is invalid!
Proto File:
syntax = "proto3";
package analyticsServicesGlobal;
option go_package = "generated/analyticsServices";
service HealthCheck {
rpc Health (HealthCheckParam) returns (HealthCheckPayload) {}
}
message HealthCheckPayload {
string message = 1;
}
message HealthCheckParam {
string response = 1;
}
The code generation completes without issue : protoc --go_out=plugins=grpc:$GOPATH/src/gauss minimal.proto
The ide and command line compilation return this error in the generated Go code though:
./minimal.pb.go:130: cannot use handler (type func("gauss/vendor/golang.org/x/net/context".Context, interface {}) (interface {}, error)) as type grpc.UnaryHandler in argument to interceptor
./minimal.pb.go:139: cannot use _HealthCheck_Health_Handler (type func(interface {}, "gauss/vendor/golang.org/x/net/context".Context, func(interface {}) error, grpc.UnaryServerInterceptor) (interface {}, error)) as type grpc.methodHandler in field value
This issue shows up for any service where a non-stream response is returned. I have create this minimal proto file to demonstrate, but every similar service definition has the same issue.
I am on OSX using Go version 1.8.1, protoc version 3.3.0, and the latest protoc plugin for Go go get -u github.com/golang/protobuf/{proto,protoc-gen-go}
I'm sure I'm doing something wrong given the lack of reports on this issue - but I don't see what. Any suggestions are appreciated!

Related

kitex "could not import echoTest/kitex_gen/echo"

when I use kitex to start an examples, I Got an error like below
for my step:
mkdir -p Protobuf-test
new file whose name is "echo.proto" and content is like this
syntax = "proto3";
option go_package = "echo";
package echo;
message Request {
string msg = 1;
}
message Response {
string msg = 1;
}
service EchoService {
rpc ClientSideStreaming(stream Request) returns (Response){} // 客户端streaming
rpc ServerSideStreaming(Request) returns (stream Response){} // 服务端streaming
rpc BidiSideStreaming(stream Request) returns (stream Response){} //双向流
}
open a terminal executed a command
kitex -type protobuf -module echoTest -service echoTest echo.proto
please give me some advise, thanks very mush
I take a comparison to using "thrift", it is ok, in the directory "xx/kitex_gen/echo", there has a file named echo.go, but not when using protobuf as model

gRPC generated file doesn't have json definition

I'm trying to generate Go file from proto file but it doesn't have json definition in the method's input definition. Should I add the json definition by myself or there were something wrong with my script. Thank you, I sincerely appreciate your help.
Proto file
message RateRequest {
string Base = 1;
string Destination = 2;
}
Generated file
type RateRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
//No json definition here
Base string `protobuf:"bytes,1,opt,name=Base,proto3" json:"Base,omitempty"`
Destination string `protobuf:"bytes,2,opt,name=Destination,proto3" json:"Destination,omitempty"`
}
Protoc script
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
protos/currency.proto
grpcurl
grpcurl --plaintext -d '{Base: "GBP", Destination: "USD"}' localhost:9092 Currency.GetRate
// Error invoking method "Currency.GetRate": error getting request data: message type RateRequest has no known field named base
Since the error is
error getting request data: message type RateRequest has no known field named base
And the json is
json:"Base,omitempty"`
Then it seems it's looking for the wrong field, it should be
json:"base,omitempty"`

GRPC-GO:Client stub not shown in the generated pb.go file

I am trying to learn GRPC from the official doc, Here is the tutorial I have followed grpc-go
Generating the proto using this command
protoc --go_out=$PWD helloworld/helloworld.proto
This above command will generate the file helloworld.pb.go without any problem but the problem is the code for the client stub is missing from the generated file
syntax = "proto3";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
The actual error i am getting from the client connection which is
undefined: helloworld.NewGreeterClient
And this has occurred from the line c := pb.NewGreeterClient(conn) in the greeter_client/main.go file
The reason behind because the client stub not generated in the generated file
Issue resolved i have some problems with the command
Here is the actual command
protoc --go_out=plugins=grpc:$PWD helloworld.proto
Add --I to your command. e.g.
protoc -I helloworld --go_out=${PWD} helloworld/*.proto

Autogenerate REST endpoints from .proto

I am having problem with compiling the .proto file. Looking to generate REST endpoints from the .proto files. Below is the code and error :
syntax = "proto3";
package pb;
import "google/protobuf/empty.proto";
import "google/api/annotations.proto";
service UrlShortener {
rpc Hello(HelloRequest) returns (HelloResponse);
rpc Encrypt(EncryptRequest) returns (EncryptResponse);
rpc Decrypt(DecryptRequest) returns (DecryptResponse) {
option (google.api.http) = {
get: "/{hash}"
};
}
}
message HelloRequest {
string Name = 1;
}
message HelloResponse {
string Message = 1;
}
message EncryptRequest {
string OriginalUrl = 1;
}
message EncryptResponse {
UrlMap ResponseMap = 1;
}
message DecryptRequest {
string hash = 1;
}
Error :
github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis: warning: directory does not exist.
google/api/annotations.proto: File not found.
urlshortener.proto: Import "google/api/annotations.proto" was not found or had errors.
Please help with fixing this.
I tried : go get -u github.com/grpc-ecosystem/grpc-gateway
But it failed saying : no buildable go source files in path.
I think you have more than one errors in your definition
You are missing the syntax version at the very beginning of your definition:
syntax = "proto3";
There are some undefined types
service.proto:32:3: "UrlMap" is not defined.
service.proto:12:40: "DecryptResponse" is not defined.
You are importing and unused empty.proto
You can use the googleapies from
{GOPATH}/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis
Then run using:
protoc -I${GOPATH}/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis -I/usr/local/include -I. service.proto --go_out=plugins=grpc:.
I made the previous changes and it compiles, so I have the service.pb.go file
Edited:
Take a look of this grpc-gateway, maybe can help you
https://github.com/grpc-ecosystem/grpc-gateway
Found out the solution : The problem is that google/api/annotations has moved from the earlier path grpc-ecosystem/grpc-gateway/third_party/googleapis to https://github.com/grpc-ecosystem/grpc-gateway/tree/master/third_party/googleapis/google/api.
Running the following resolved the error : go get -u github.com/grpc-ecosystem/grpc-gateway/...

Unable to test a Golang CLI tool's output

I have a cli tool written in Go which produces the following output:
Command: config get
Env: int
Component: foo-component
Unable to find any configuration within Cosmos (http://api.foo.com) for foo-component.
I would like to verify this output within a test.
The test I have written (and doesn't pass) is as follows:
package command
import (
"testing"
"github.com/my/package/foo"
)
type FakeCliContext struct{}
func (s FakeCliContext) String(name string) string {
return "foobar"
}
func ExampleInvalidComponentReturnsError() {
fakeBaseURL := "http://api.foo.com"
fakeCliContext := &FakeCliContext{}
fakeFetchFlag := func(foo.CliContext) (map[string]string, error) {
return map[string]string{
"env": "int",
"component": "foo-component",
}, nil
}
GetConfig(*fakeCliContext, fakeFetchFlag, fakeBaseURL)
// Output:
// Command: config get
// Env: int
// Component: foo-component
//
// Unable to find any configuration within Cosmos (http://api.foo.com) for foo-component.
}
The majority of the code is creating fake objects that I'm injecting into my function call GetConfig.
Effectively there is no return value from GetConfig only a side effect of text being printed to stdout.
So I'm using the Example<NameOfTest> format to try and verify the output.
But all I just back when I run go test -v is:
=== RUN ExampleInvalidComponentReturnsError
exit status 1
FAIL github.com/my/package/thing 0.418s
Does anyone know what I might be missing?
I've found that if I add an additional test after the 'Example' one above, for example called Test<NameOfTest> (but consistenting of effectively the same code), then this will actually display the function's output into my stdout when running the test:
func TestInvalidComponentReturnsError(t *testing.T) {
fakeBaseURL := "http://api.foo.com"
fakeCliContext := &FakeCliContext{}
fakeFetchFlag := func(utils.CliContext) (map[string]string, error) {
return map[string]string{
"env": "int",
"component": "foo-component",
}, nil
}
GetConfig(*fakeCliContext, fakeFetchFlag, fakeBaseURL)
}
The above example test will now show the following output when executing go test -v:
=== RUN TestInvalidComponentReturnsError
Command: config get
Env: int
Component: foo-component
Unable to find any configuration within Cosmos (http://api.foo.com) for foo-component.
exit status 1
FAIL github.com/bbc/apollo/command 0.938s
OK so the solution to this problem was part architecture and part removal/refactor of code.
I extracted the private functions from the cli command package so they became public functions in a separate function
I refactored the code so that all dependencies were injected, this then allowed me to mock these objects and verify the the expected methods were called
Now the private functions are in a package and made public, I'm able to test those things specifically, outside of the cli context
Finally, I removed the use of os.Exit as that was a nightmare to deal with and wasn't really necessary

Resources