diff --git a/.travis.yml b/.travis.yml index 53c2f252adf..9888fae9ea8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,7 @@ cache: - $HOME/local before_install: - ./.travis.build-protoc.sh 3.0.0-beta-3 +- wget http://repo1.maven.org/maven2/io/swagger/swagger-codegen-cli/2.1.6/swagger-codegen-cli-2.1.6.jar -O swagger-codegen-cli.jar - go get github.com/golang/lint/golint install: - go get github.com/gengo/grpc-gateway/protoc-gen-grpc-gateway @@ -18,7 +19,7 @@ install: - go get github.com/gengo/grpc-gateway/examples - go get github.com/gengo/grpc-gateway/examples/server script: -- make realclean && make examples +- make realclean && make examples SWAGGER_CODEGEN="java -jar swagger-codegen-cli.jar" - if ! go version | grep devel; then test -z "$(git status --porcelain)" || (git status; git diff; exit 1); fi - env GLOG_logtostderr=1 go test -race -v github.com/gengo/grpc-gateway/... - golint github.com/gengo/grpc-gateway/protoc-gen-grpc-gateway/... diff --git a/Makefile b/Makefile index 7a56ac69bc3..3299297a953 100644 --- a/Makefile +++ b/Makefile @@ -56,6 +56,24 @@ EXAMPLE_GWSRCS=$(EXAMPLES:.proto=.pb.gw.go) EXAMPLE_SWAGGERSRCS=$(EXAMPLES:.proto=.swagger.json) EXAMPLE_DEPS=examples/sub/message.proto examples/sub2/message.proto EXAMPLE_DEPSRCS=$(EXAMPLE_DEPS:.proto=.pb.go) + +EXAMPLE_CLIENT_DIR=examples/clients +ECHO_EXAMPLE_SPEC=examples/examplepb/echo_service.swagger.json +ECHO_EXAMPLE_SRCS=$(EXAMPLE_CLIENT_DIR)/echo/EchoServiceApi.go \ + $(EXAMPLE_CLIENT_DIR)/echo/ExamplepbSimpleMessage.go +ABE_EXAMPLE_SPEC=examples/examplepb/a_bit_of_everything.swagger.json +ABE_EXAMPLE_SRCS=$(EXAMPLE_CLIENT_DIR)/abe/ABitOfEverythingServiceApi.go \ + $(EXAMPLE_CLIENT_DIR)/abe/ABitOfEverythingNested.go \ + $(EXAMPLE_CLIENT_DIR)/abe/ExamplepbABitOfEverything.go \ + $(EXAMPLE_CLIENT_DIR)/abe/ExamplepbNumericEnum.go \ + $(EXAMPLE_CLIENT_DIR)/abe/ExamplepbIdMessage.go \ + $(EXAMPLE_CLIENT_DIR)/abe/NestedDeepEnum.go \ + $(EXAMPLE_CLIENT_DIR)/abe/ProtobufEmpty.go \ + $(EXAMPLE_CLIENT_DIR)/abe/Sub2IdMessage.go \ + $(EXAMPLE_CLIENT_DIR)/abe/SubStringMessage.go +EXAMPLE_CLIENT_SRCS=$(ECHO_EXAMPLE_SRCS) $(ABE_EXAMPLE_SRCS) +SWAGGER_CODEGEN=swagger-codegen + PROTOC_INC_PATH=$(dir $(shell which protoc))/../include generate: $(OPTIONS_GO) $(RUNTIME_GO) @@ -88,7 +106,16 @@ $(EXAMPLE_GWSRCS): $(GATEWAY_PLUGIN) $(EXAMPLES) $(EXAMPLE_SWAGGERSRCS): $(SWAGGER_PLUGIN) $(SWAGGER_EXAMPLES) protoc -I $(PROTOC_INC_PATH) -I. -I$(GOOGLEAPIS_DIR) --plugin=$(SWAGGER_PLUGIN) --swagger_out=logtostderr=true,$(PKGMAP):. $(SWAGGER_EXAMPLES) -examples: $(EXAMPLE_SVCSRCS) $(EXAMPLE_GWSRCS) $(EXAMPLE_DEPSRCS) $(EXAMPLE_SWAGGERSRCS) +$(ECHO_EXAMPLE_SRCS): $(ECHO_EXAMPLE_SPEC) + $(SWAGGER_CODEGEN) generate -i $(ECHO_EXAMPLE_SPEC) \ + -l go -o examples/clients --additional-properties packageName=echo + @rm -f $(EXAMPLE_CLIENT_DIR)/README.md $(EXAMPLE_CLIENT_DIR)/git_push.sh $(EXAMPLE_CLIENT_DIR)/.gitignore +$(ABE_EXAMPLE_SRCS): $(ABE_EXAMPLE_SPEC) + $(SWAGGER_CODEGEN) generate -i $(ABE_EXAMPLE_SPEC) \ + -l go -o examples/clients --additional-properties packageName=abe + @rm -f $(EXAMPLE_CLIENT_DIR)/README.md $(EXAMPLE_CLIENT_DIR)/git_push.sh $(EXAMPLE_CLIENT_DIR)/.gitignore + +examples: $(EXAMPLE_SVCSRCS) $(EXAMPLE_GWSRCS) $(EXAMPLE_DEPSRCS) $(EXAMPLE_SWAGGERSRCS) $(EXAMPLE_CLIENT_SRCS) test: examples go test -race $(PKG)/... @@ -101,5 +128,6 @@ realclean: distclean rm -f $(EXAMPLE_SWAGGERSRCS) rm -f $(GO_PLUGIN) rm -f $(SWAGGER_PLUGIN) + rm -f $(EXAMPLE_CLIENT_SRCS) .PHONY: generate examples test clean distclean realclean diff --git a/examples/client_test.go b/examples/client_test.go new file mode 100644 index 00000000000..41f29fc593f --- /dev/null +++ b/examples/client_test.go @@ -0,0 +1,162 @@ +package main + +import ( + "reflect" + "testing" + + "github.com/gengo/grpc-gateway/examples/clients/abe" + "github.com/gengo/grpc-gateway/examples/clients/echo" +) + +func TestClientIntegration(t *testing.T) { +} + +func TestEchoClient(t *testing.T) { + if testing.Short() { + t.Skip() + return + } + + cl := echo.NewEchoServiceApiWithBasePath("http://localhost:8080") + resp, err := cl.Echo("foo") + if err != nil { + t.Errorf(`cl.Echo("foo") failed with %v; want success`, err) + } + if got, want := resp.Id, "foo"; got != want { + t.Errorf("resp.Id = %q; want %q", got, want) + } +} + +func TestEchoBodyClient(t *testing.T) { + if testing.Short() { + t.Skip() + return + } + + cl := echo.NewEchoServiceApiWithBasePath("http://localhost:8080") + req := echo.ExamplepbSimpleMessage{Id: "foo"} + resp, err := cl.EchoBody(req) + if err != nil { + t.Errorf("cl.EchoBody(%#v) failed with %v; want success", req, err) + } + if got, want := resp.Id, "foo"; got != want { + t.Errorf("resp.Id = %q; want %q", got, want) + } +} + +func TestAbitOfEverythingClient(t *testing.T) { + if testing.Short() { + t.Skip() + return + } + + cl := abe.NewABitOfEverythingServiceApiWithBasePath("http://localhost:8080") + testABEClientCreate(t, cl) + testABEClientCreateBody(t, cl) +} + +func testABEClientCreate(t *testing.T, cl *abe.ABitOfEverythingServiceApi) { + want := abe.ExamplepbABitOfEverything{ + FloatValue: 1.5, + DoubleValue: 2.5, + Int64Value: "4294967296", + Uint64Value: "9223372036854775807", + Int32Value: -2147483648, + Fixed64Value: "9223372036854775807", + Fixed32Value: 4294967295, + BoolValue: true, + StringValue: "strprefix/foo", + Uint32Value: 4294967295, + Sfixed32Value: 2147483647, + Sfixed64Value: "-4611686018427387904", + Sint32Value: 2147483647, + Sint64Value: "4611686018427387903", + NonConventionalNameValue: "camelCase", + } + resp, err := cl.Create( + want.FloatValue, + want.DoubleValue, + want.Int64Value, + want.Uint64Value, + want.Int32Value, + want.Fixed64Value, + want.Fixed32Value, + want.BoolValue, + want.StringValue, + want.Uint32Value, + want.Sfixed32Value, + want.Sfixed64Value, + want.Sint32Value, + want.Sint64Value, + want.NonConventionalNameValue, + ) + if err != nil { + t.Errorf("cl.Create(%#v) failed with %v; want success", want, err) + } + if resp.Uuid == "" { + t.Errorf("resp.Uuid is empty; want not empty") + } + resp.Uuid = "" + if got := resp; !reflect.DeepEqual(got, want) { + t.Errorf("resp = %#v; want %#v", got, want) + } +} + +func testABEClientCreateBody(t *testing.T, cl *abe.ABitOfEverythingServiceApi) { + t.Log("TODO: support enum") + return + + want := abe.ExamplepbABitOfEverything{ + FloatValue: 1.5, + DoubleValue: 2.5, + Int64Value: "4294967296", + Uint64Value: "9223372036854775807", + Int32Value: -2147483648, + Fixed64Value: "9223372036854775807", + Fixed32Value: 4294967295, + BoolValue: true, + StringValue: "strprefix/foo", + Uint32Value: 4294967295, + Sfixed32Value: 2147483647, + Sfixed64Value: "-4611686018427387904", + Sint32Value: 2147483647, + Sint64Value: "4611686018427387903", + NonConventionalNameValue: "camelCase", + + Nested: []abe.ABitOfEverythingNested{ + { + Name: "bar", + Amount: 10, + }, + { + Name: "baz", + Amount: 20, + }, + }, + RepeatedStringValue: []string{"a", "b", "c"}, + OneofString: "x", + MapValue: map[string]abe.ExamplepbNumericEnum{ + // "a": abe.ExamplepbNumericEnum_ONE, + // "b": abe.ExamplepbNumericEnum_ZERO, + }, + MappedStringValue: map[string]string{ + "a": "x", + "b": "y", + }, + MappedNestedValue: map[string]abe.ABitOfEverythingNested{ + "a": {Name: "x", Amount: 1}, + "b": {Name: "y", Amount: 2}, + }, + } + resp, err := cl.CreateBody(want) + if err != nil { + t.Errorf("cl.CreateBody(%#v) failed with %v; want success", want, err) + } + if resp.Uuid == "" { + t.Errorf("resp.Uuid is empty; want not empty") + } + resp.Uuid = "" + if got := resp; !reflect.DeepEqual(got, want) { + t.Errorf("resp = %#v; want %#v", got, want) + } +} diff --git a/examples/clients/abe/ABitOfEverythingNested.go b/examples/clients/abe/ABitOfEverythingNested.go new file mode 100644 index 00000000000..ab15b89cfbd --- /dev/null +++ b/examples/clients/abe/ABitOfEverythingNested.go @@ -0,0 +1,11 @@ +package abe + +import ( +) + +type ABitOfEverythingNested struct { + Amount int64 `json:"amount,omitempty"` + Name string `json:"name,omitempty"` + Ok NestedDeepEnum `json:"ok,omitempty"` + +} diff --git a/examples/clients/abe/ABitOfEverythingServiceApi.go b/examples/clients/abe/ABitOfEverythingServiceApi.go new file mode 100644 index 00000000000..855d2755155 --- /dev/null +++ b/examples/clients/abe/ABitOfEverythingServiceApi.go @@ -0,0 +1,648 @@ +package abe + +import ( + "strings" + "fmt" + "encoding/json" + "errors" + "github.com/dghubble/sling" +) + +type ABitOfEverythingServiceApi struct { + basePath string +} + +func NewABitOfEverythingServiceApi() *ABitOfEverythingServiceApi{ + return &ABitOfEverythingServiceApi { + basePath: "http://localhost", + } +} + +func NewABitOfEverythingServiceApiWithBasePath(basePath string) *ABitOfEverythingServiceApi{ + return &ABitOfEverythingServiceApi { + basePath: basePath, + } +} + +/** + * + * + * @param floatValue + * @param doubleValue + * @param int64Value + * @param uint64Value + * @param int32Value + * @param fixed64Value + * @param fixed32Value + * @param boolValue + * @param stringValue + * @param uint32Value + * @param sfixed32Value + * @param sfixed64Value + * @param sint32Value + * @param sint64Value + * @param nonConventionalNameValue + * @return ExamplepbABitOfEverything + */ +//func (a ABitOfEverythingServiceApi) Create (floatValue float32, doubleValue float64, int64Value string, uint64Value string, int32Value int32, fixed64Value string, fixed32Value int64, boolValue bool, stringValue string, uint32Value int64, sfixed32Value int32, sfixed64Value string, sint32Value int32, sint64Value string, nonConventionalNameValue string) (ExamplepbABitOfEverything, error) { +func (a ABitOfEverythingServiceApi) Create (floatValue float32, doubleValue float64, int64Value string, uint64Value string, int32Value int32, fixed64Value string, fixed32Value int64, boolValue bool, stringValue string, uint32Value int64, sfixed32Value int32, sfixed64Value string, sint32Value int32, sint64Value string, nonConventionalNameValue string) (ExamplepbABitOfEverything, error) { + + _sling := sling.New().Post(a.basePath) + + // create path and map variables + path := "/v1/example/a_bit_of_everything/{float_value}/{double_value}/{int64_value}/separator/{uint64_value}/{int32_value}/{fixed64_value}/{fixed32_value}/{bool_value}/{string_value}/{uint32_value}/{sfixed32_value}/{sfixed64_value}/{sint32_value}/{sint64_value}/{nonConventionalNameValue}" + path = strings.Replace(path, "{" + "float_value" + "}", fmt.Sprintf("%v", floatValue), -1) + path = strings.Replace(path, "{" + "double_value" + "}", fmt.Sprintf("%v", doubleValue), -1) + path = strings.Replace(path, "{" + "int64_value" + "}", fmt.Sprintf("%v", int64Value), -1) + path = strings.Replace(path, "{" + "uint64_value" + "}", fmt.Sprintf("%v", uint64Value), -1) + path = strings.Replace(path, "{" + "int32_value" + "}", fmt.Sprintf("%v", int32Value), -1) + path = strings.Replace(path, "{" + "fixed64_value" + "}", fmt.Sprintf("%v", fixed64Value), -1) + path = strings.Replace(path, "{" + "fixed32_value" + "}", fmt.Sprintf("%v", fixed32Value), -1) + path = strings.Replace(path, "{" + "bool_value" + "}", fmt.Sprintf("%v", boolValue), -1) + path = strings.Replace(path, "{" + "string_value" + "}", fmt.Sprintf("%v", stringValue), -1) + path = strings.Replace(path, "{" + "uint32_value" + "}", fmt.Sprintf("%v", uint32Value), -1) + path = strings.Replace(path, "{" + "sfixed32_value" + "}", fmt.Sprintf("%v", sfixed32Value), -1) + path = strings.Replace(path, "{" + "sfixed64_value" + "}", fmt.Sprintf("%v", sfixed64Value), -1) + path = strings.Replace(path, "{" + "sint32_value" + "}", fmt.Sprintf("%v", sint32Value), -1) + path = strings.Replace(path, "{" + "sint64_value" + "}", fmt.Sprintf("%v", sint64Value), -1) + path = strings.Replace(path, "{" + "nonConventionalNameValue" + "}", fmt.Sprintf("%v", nonConventionalNameValue), -1) + + _sling = _sling.Path(path) + + // accept header + accepts := []string { "application/json" } + for key := range accepts { + _sling = _sling.Set("Accept", accepts[key]) + break // only use the first Accept + } + + + var successPayload = new(ExamplepbABitOfEverything) + + // We use this map (below) so that any arbitrary error JSON can be handled. + // FIXME: This is in the absence of this Go generator honoring the non-2xx + // response (error) models, which needs to be implemented at some point. + var failurePayload map[string]interface{} + + httpResponse, err := _sling.Receive(successPayload, &failurePayload) + + if err == nil { + // err == nil only means that there wasn't a sub-application-layer error (e.g. no network error) + if failurePayload != nil { + // If the failurePayload is present, there likely was some kind of non-2xx status + // returned (and a JSON payload error present) + var str []byte + str, err = json.Marshal(failurePayload) + if err == nil { // For safety, check for an error marshalling... probably superfluous + // This will return the JSON error body as a string + err = errors.New(string(str)) + } + } else { + // So, there was no network-type error, and nothing in the failure payload, + // but we should still check the status code + if httpResponse == nil { + // This should never happen... + err = errors.New("No HTTP Response received.") + } else if code := httpResponse.StatusCode; 200 > code || code > 299 { + err = errors.New("HTTP Error: " + string(httpResponse.StatusCode)) + } + } + } + + return *successPayload, err +} +/** + * + * + * @param body + * @return ExamplepbABitOfEverything + */ +//func (a ABitOfEverythingServiceApi) CreateBody (body ExamplepbABitOfEverything) (ExamplepbABitOfEverything, error) { +func (a ABitOfEverythingServiceApi) CreateBody (body ExamplepbABitOfEverything) (ExamplepbABitOfEverything, error) { + + _sling := sling.New().Post(a.basePath) + + // create path and map variables + path := "/v1/example/a_bit_of_everything" + + _sling = _sling.Path(path) + + // accept header + accepts := []string { "application/json" } + for key := range accepts { + _sling = _sling.Set("Accept", accepts[key]) + break // only use the first Accept + } + +// body params + _sling = _sling.BodyJSON(body) + + var successPayload = new(ExamplepbABitOfEverything) + + // We use this map (below) so that any arbitrary error JSON can be handled. + // FIXME: This is in the absence of this Go generator honoring the non-2xx + // response (error) models, which needs to be implemented at some point. + var failurePayload map[string]interface{} + + httpResponse, err := _sling.Receive(successPayload, &failurePayload) + + if err == nil { + // err == nil only means that there wasn't a sub-application-layer error (e.g. no network error) + if failurePayload != nil { + // If the failurePayload is present, there likely was some kind of non-2xx status + // returned (and a JSON payload error present) + var str []byte + str, err = json.Marshal(failurePayload) + if err == nil { // For safety, check for an error marshalling... probably superfluous + // This will return the JSON error body as a string + err = errors.New(string(str)) + } + } else { + // So, there was no network-type error, and nothing in the failure payload, + // but we should still check the status code + if httpResponse == nil { + // This should never happen... + err = errors.New("No HTTP Response received.") + } else if code := httpResponse.StatusCode; 200 > code || code > 299 { + err = errors.New("HTTP Error: " + string(httpResponse.StatusCode)) + } + } + } + + return *successPayload, err +} +/** + * + * + * @param singleNestedName + * @param body + * @return ExamplepbABitOfEverything + */ +//func (a ABitOfEverythingServiceApi) DeepPathEcho (singleNestedName string, body ExamplepbABitOfEverything) (ExamplepbABitOfEverything, error) { +func (a ABitOfEverythingServiceApi) DeepPathEcho (singleNestedName string, body ExamplepbABitOfEverything) (ExamplepbABitOfEverything, error) { + + _sling := sling.New().Post(a.basePath) + + // create path and map variables + path := "/v1/example/a_bit_of_everything/{single_nested.name}" + path = strings.Replace(path, "{" + "single_nested.name" + "}", fmt.Sprintf("%v", singleNestedName), -1) + + _sling = _sling.Path(path) + + // accept header + accepts := []string { "application/json" } + for key := range accepts { + _sling = _sling.Set("Accept", accepts[key]) + break // only use the first Accept + } + +// body params + _sling = _sling.BodyJSON(body) + + var successPayload = new(ExamplepbABitOfEverything) + + // We use this map (below) so that any arbitrary error JSON can be handled. + // FIXME: This is in the absence of this Go generator honoring the non-2xx + // response (error) models, which needs to be implemented at some point. + var failurePayload map[string]interface{} + + httpResponse, err := _sling.Receive(successPayload, &failurePayload) + + if err == nil { + // err == nil only means that there wasn't a sub-application-layer error (e.g. no network error) + if failurePayload != nil { + // If the failurePayload is present, there likely was some kind of non-2xx status + // returned (and a JSON payload error present) + var str []byte + str, err = json.Marshal(failurePayload) + if err == nil { // For safety, check for an error marshalling... probably superfluous + // This will return the JSON error body as a string + err = errors.New(string(str)) + } + } else { + // So, there was no network-type error, and nothing in the failure payload, + // but we should still check the status code + if httpResponse == nil { + // This should never happen... + err = errors.New("No HTTP Response received.") + } else if code := httpResponse.StatusCode; 200 > code || code > 299 { + err = errors.New("HTTP Error: " + string(httpResponse.StatusCode)) + } + } + } + + return *successPayload, err +} +/** + * + * + * @param uuid + * @return ProtobufEmpty + */ +//func (a ABitOfEverythingServiceApi) Delete (uuid string) (ProtobufEmpty, error) { +func (a ABitOfEverythingServiceApi) Delete (uuid string) (ProtobufEmpty, error) { + + _sling := sling.New().Delete(a.basePath) + + // create path and map variables + path := "/v1/example/a_bit_of_everything/{uuid}" + path = strings.Replace(path, "{" + "uuid" + "}", fmt.Sprintf("%v", uuid), -1) + + _sling = _sling.Path(path) + + // accept header + accepts := []string { "application/json" } + for key := range accepts { + _sling = _sling.Set("Accept", accepts[key]) + break // only use the first Accept + } + + + var successPayload = new(ProtobufEmpty) + + // We use this map (below) so that any arbitrary error JSON can be handled. + // FIXME: This is in the absence of this Go generator honoring the non-2xx + // response (error) models, which needs to be implemented at some point. + var failurePayload map[string]interface{} + + httpResponse, err := _sling.Receive(successPayload, &failurePayload) + + if err == nil { + // err == nil only means that there wasn't a sub-application-layer error (e.g. no network error) + if failurePayload != nil { + // If the failurePayload is present, there likely was some kind of non-2xx status + // returned (and a JSON payload error present) + var str []byte + str, err = json.Marshal(failurePayload) + if err == nil { // For safety, check for an error marshalling... probably superfluous + // This will return the JSON error body as a string + err = errors.New(string(str)) + } + } else { + // So, there was no network-type error, and nothing in the failure payload, + // but we should still check the status code + if httpResponse == nil { + // This should never happen... + err = errors.New("No HTTP Response received.") + } else if code := httpResponse.StatusCode; 200 > code || code > 299 { + err = errors.New("HTTP Error: " + string(httpResponse.StatusCode)) + } + } + } + + return *successPayload, err +} +/** + * + * + * @param value + * @return SubStringMessage + */ +//func (a ABitOfEverythingServiceApi) Echo (value string) (SubStringMessage, error) { +func (a ABitOfEverythingServiceApi) Echo (value string) (SubStringMessage, error) { + + _sling := sling.New().Get(a.basePath) + + // create path and map variables + path := "/v1/example/a_bit_of_everything/echo/{value}" + path = strings.Replace(path, "{" + "value" + "}", fmt.Sprintf("%v", value), -1) + + _sling = _sling.Path(path) + + // accept header + accepts := []string { "application/json" } + for key := range accepts { + _sling = _sling.Set("Accept", accepts[key]) + break // only use the first Accept + } + + + var successPayload = new(SubStringMessage) + + // We use this map (below) so that any arbitrary error JSON can be handled. + // FIXME: This is in the absence of this Go generator honoring the non-2xx + // response (error) models, which needs to be implemented at some point. + var failurePayload map[string]interface{} + + httpResponse, err := _sling.Receive(successPayload, &failurePayload) + + if err == nil { + // err == nil only means that there wasn't a sub-application-layer error (e.g. no network error) + if failurePayload != nil { + // If the failurePayload is present, there likely was some kind of non-2xx status + // returned (and a JSON payload error present) + var str []byte + str, err = json.Marshal(failurePayload) + if err == nil { // For safety, check for an error marshalling... probably superfluous + // This will return the JSON error body as a string + err = errors.New(string(str)) + } + } else { + // So, there was no network-type error, and nothing in the failure payload, + // but we should still check the status code + if httpResponse == nil { + // This should never happen... + err = errors.New("No HTTP Response received.") + } else if code := httpResponse.StatusCode; 200 > code || code > 299 { + err = errors.New("HTTP Error: " + string(httpResponse.StatusCode)) + } + } + } + + return *successPayload, err +} +/** + * + * + * @return SubStringMessage + */ +//func (a ABitOfEverythingServiceApi) Echo_1 () (SubStringMessage, error) { +func (a ABitOfEverythingServiceApi) Echo_1 () (SubStringMessage, error) { + + _sling := sling.New().Get(a.basePath) + + // create path and map variables + path := "/v2/example/echo" + + _sling = _sling.Path(path) + + // accept header + accepts := []string { "application/json" } + for key := range accepts { + _sling = _sling.Set("Accept", accepts[key]) + break // only use the first Accept + } + + + var successPayload = new(SubStringMessage) + + // We use this map (below) so that any arbitrary error JSON can be handled. + // FIXME: This is in the absence of this Go generator honoring the non-2xx + // response (error) models, which needs to be implemented at some point. + var failurePayload map[string]interface{} + + httpResponse, err := _sling.Receive(successPayload, &failurePayload) + + if err == nil { + // err == nil only means that there wasn't a sub-application-layer error (e.g. no network error) + if failurePayload != nil { + // If the failurePayload is present, there likely was some kind of non-2xx status + // returned (and a JSON payload error present) + var str []byte + str, err = json.Marshal(failurePayload) + if err == nil { // For safety, check for an error marshalling... probably superfluous + // This will return the JSON error body as a string + err = errors.New(string(str)) + } + } else { + // So, there was no network-type error, and nothing in the failure payload, + // but we should still check the status code + if httpResponse == nil { + // This should never happen... + err = errors.New("No HTTP Response received.") + } else if code := httpResponse.StatusCode; 200 > code || code > 299 { + err = errors.New("HTTP Error: " + string(httpResponse.StatusCode)) + } + } + } + + return *successPayload, err +} +/** + * + * + * @param body + * @return SubStringMessage + */ +//func (a ABitOfEverythingServiceApi) Echo_2 (body SubStringMessage) (SubStringMessage, error) { +func (a ABitOfEverythingServiceApi) Echo_2 (body SubStringMessage) (SubStringMessage, error) { + + _sling := sling.New().Post(a.basePath) + + // create path and map variables + path := "/v2/example/echo" + + _sling = _sling.Path(path) + + // accept header + accepts := []string { "application/json" } + for key := range accepts { + _sling = _sling.Set("Accept", accepts[key]) + break // only use the first Accept + } + +// body params + _sling = _sling.BodyJSON(body) + + var successPayload = new(SubStringMessage) + + // We use this map (below) so that any arbitrary error JSON can be handled. + // FIXME: This is in the absence of this Go generator honoring the non-2xx + // response (error) models, which needs to be implemented at some point. + var failurePayload map[string]interface{} + + httpResponse, err := _sling.Receive(successPayload, &failurePayload) + + if err == nil { + // err == nil only means that there wasn't a sub-application-layer error (e.g. no network error) + if failurePayload != nil { + // If the failurePayload is present, there likely was some kind of non-2xx status + // returned (and a JSON payload error present) + var str []byte + str, err = json.Marshal(failurePayload) + if err == nil { // For safety, check for an error marshalling... probably superfluous + // This will return the JSON error body as a string + err = errors.New(string(str)) + } + } else { + // So, there was no network-type error, and nothing in the failure payload, + // but we should still check the status code + if httpResponse == nil { + // This should never happen... + err = errors.New("No HTTP Response received.") + } else if code := httpResponse.StatusCode; 200 > code || code > 299 { + err = errors.New("HTTP Error: " + string(httpResponse.StatusCode)) + } + } + } + + return *successPayload, err +} +/** + * + * + * @param uuid + * @return ExamplepbABitOfEverything + */ +//func (a ABitOfEverythingServiceApi) Lookup (uuid string) (ExamplepbABitOfEverything, error) { +func (a ABitOfEverythingServiceApi) Lookup (uuid string) (ExamplepbABitOfEverything, error) { + + _sling := sling.New().Get(a.basePath) + + // create path and map variables + path := "/v1/example/a_bit_of_everything/{uuid}" + path = strings.Replace(path, "{" + "uuid" + "}", fmt.Sprintf("%v", uuid), -1) + + _sling = _sling.Path(path) + + // accept header + accepts := []string { "application/json" } + for key := range accepts { + _sling = _sling.Set("Accept", accepts[key]) + break // only use the first Accept + } + + + var successPayload = new(ExamplepbABitOfEverything) + + // We use this map (below) so that any arbitrary error JSON can be handled. + // FIXME: This is in the absence of this Go generator honoring the non-2xx + // response (error) models, which needs to be implemented at some point. + var failurePayload map[string]interface{} + + httpResponse, err := _sling.Receive(successPayload, &failurePayload) + + if err == nil { + // err == nil only means that there wasn't a sub-application-layer error (e.g. no network error) + if failurePayload != nil { + // If the failurePayload is present, there likely was some kind of non-2xx status + // returned (and a JSON payload error present) + var str []byte + str, err = json.Marshal(failurePayload) + if err == nil { // For safety, check for an error marshalling... probably superfluous + // This will return the JSON error body as a string + err = errors.New(string(str)) + } + } else { + // So, there was no network-type error, and nothing in the failure payload, + // but we should still check the status code + if httpResponse == nil { + // This should never happen... + err = errors.New("No HTTP Response received.") + } else if code := httpResponse.StatusCode; 200 > code || code > 299 { + err = errors.New("HTTP Error: " + string(httpResponse.StatusCode)) + } + } + } + + return *successPayload, err +} +/** + * + * + * @return ProtobufEmpty + */ +//func (a ABitOfEverythingServiceApi) Timeout () (ProtobufEmpty, error) { +func (a ABitOfEverythingServiceApi) Timeout () (ProtobufEmpty, error) { + + _sling := sling.New().Get(a.basePath) + + // create path and map variables + path := "/v2/example/timeout" + + _sling = _sling.Path(path) + + // accept header + accepts := []string { "application/json" } + for key := range accepts { + _sling = _sling.Set("Accept", accepts[key]) + break // only use the first Accept + } + + + var successPayload = new(ProtobufEmpty) + + // We use this map (below) so that any arbitrary error JSON can be handled. + // FIXME: This is in the absence of this Go generator honoring the non-2xx + // response (error) models, which needs to be implemented at some point. + var failurePayload map[string]interface{} + + httpResponse, err := _sling.Receive(successPayload, &failurePayload) + + if err == nil { + // err == nil only means that there wasn't a sub-application-layer error (e.g. no network error) + if failurePayload != nil { + // If the failurePayload is present, there likely was some kind of non-2xx status + // returned (and a JSON payload error present) + var str []byte + str, err = json.Marshal(failurePayload) + if err == nil { // For safety, check for an error marshalling... probably superfluous + // This will return the JSON error body as a string + err = errors.New(string(str)) + } + } else { + // So, there was no network-type error, and nothing in the failure payload, + // but we should still check the status code + if httpResponse == nil { + // This should never happen... + err = errors.New("No HTTP Response received.") + } else if code := httpResponse.StatusCode; 200 > code || code > 299 { + err = errors.New("HTTP Error: " + string(httpResponse.StatusCode)) + } + } + } + + return *successPayload, err +} +/** + * + * + * @param uuid + * @param body + * @return ProtobufEmpty + */ +//func (a ABitOfEverythingServiceApi) Update (uuid string, body ExamplepbABitOfEverything) (ProtobufEmpty, error) { +func (a ABitOfEverythingServiceApi) Update (uuid string, body ExamplepbABitOfEverything) (ProtobufEmpty, error) { + + _sling := sling.New().Put(a.basePath) + + // create path and map variables + path := "/v1/example/a_bit_of_everything/{uuid}" + path = strings.Replace(path, "{" + "uuid" + "}", fmt.Sprintf("%v", uuid), -1) + + _sling = _sling.Path(path) + + // accept header + accepts := []string { "application/json" } + for key := range accepts { + _sling = _sling.Set("Accept", accepts[key]) + break // only use the first Accept + } + +// body params + _sling = _sling.BodyJSON(body) + + var successPayload = new(ProtobufEmpty) + + // We use this map (below) so that any arbitrary error JSON can be handled. + // FIXME: This is in the absence of this Go generator honoring the non-2xx + // response (error) models, which needs to be implemented at some point. + var failurePayload map[string]interface{} + + httpResponse, err := _sling.Receive(successPayload, &failurePayload) + + if err == nil { + // err == nil only means that there wasn't a sub-application-layer error (e.g. no network error) + if failurePayload != nil { + // If the failurePayload is present, there likely was some kind of non-2xx status + // returned (and a JSON payload error present) + var str []byte + str, err = json.Marshal(failurePayload) + if err == nil { // For safety, check for an error marshalling... probably superfluous + // This will return the JSON error body as a string + err = errors.New(string(str)) + } + } else { + // So, there was no network-type error, and nothing in the failure payload, + // but we should still check the status code + if httpResponse == nil { + // This should never happen... + err = errors.New("No HTTP Response received.") + } else if code := httpResponse.StatusCode; 200 > code || code > 299 { + err = errors.New("HTTP Error: " + string(httpResponse.StatusCode)) + } + } + } + + return *successPayload, err +} diff --git a/examples/clients/abe/ExamplepbABitOfEverything.go b/examples/clients/abe/ExamplepbABitOfEverything.go new file mode 100644 index 00000000000..25084255678 --- /dev/null +++ b/examples/clients/abe/ExamplepbABitOfEverything.go @@ -0,0 +1,33 @@ +package abe + +import ( +) + +type ExamplepbABitOfEverything struct { + BoolValue bool `json:"bool_value,omitempty"` + DoubleValue float64 `json:"double_value,omitempty"` + EnumValue ExamplepbNumericEnum `json:"enum_value,omitempty"` + Fixed32Value int64 `json:"fixed32_value,omitempty"` + Fixed64Value string `json:"fixed64_value,omitempty"` + FloatValue float32 `json:"float_value,omitempty"` + Int32Value int32 `json:"int32_value,omitempty"` + Int64Value string `json:"int64_value,omitempty"` + MapValue map[string]ExamplepbNumericEnum `json:"map_value,omitempty"` + MappedNestedValue map[string]ABitOfEverythingNested `json:"mapped_nested_value,omitempty"` + MappedStringValue map[string]string `json:"mapped_string_value,omitempty"` + Nested []ABitOfEverythingNested `json:"nested,omitempty"` + NonConventionalNameValue string `json:"nonConventionalNameValue,omitempty"` + OneofEmpty ProtobufEmpty `json:"oneof_empty,omitempty"` + OneofString string `json:"oneof_string,omitempty"` + RepeatedStringValue []string `json:"repeated_string_value,omitempty"` + Sfixed32Value int32 `json:"sfixed32_value,omitempty"` + Sfixed64Value string `json:"sfixed64_value,omitempty"` + SingleNested ABitOfEverythingNested `json:"single_nested,omitempty"` + Sint32Value int32 `json:"sint32_value,omitempty"` + Sint64Value string `json:"sint64_value,omitempty"` + StringValue string `json:"string_value,omitempty"` + Uint32Value int64 `json:"uint32_value,omitempty"` + Uint64Value string `json:"uint64_value,omitempty"` + Uuid string `json:"uuid,omitempty"` + +} diff --git a/examples/clients/abe/ExamplepbNumericEnum.go b/examples/clients/abe/ExamplepbNumericEnum.go new file mode 100644 index 00000000000..51cffc77f69 --- /dev/null +++ b/examples/clients/abe/ExamplepbNumericEnum.go @@ -0,0 +1,8 @@ +package abe + +import ( +) + +type ExamplepbNumericEnum struct { + +} diff --git a/examples/clients/abe/NestedDeepEnum.go b/examples/clients/abe/NestedDeepEnum.go new file mode 100644 index 00000000000..b48e231216c --- /dev/null +++ b/examples/clients/abe/NestedDeepEnum.go @@ -0,0 +1,8 @@ +package abe + +import ( +) + +type NestedDeepEnum struct { + +} diff --git a/examples/clients/abe/ProtobufEmpty.go b/examples/clients/abe/ProtobufEmpty.go new file mode 100644 index 00000000000..ac37afeb862 --- /dev/null +++ b/examples/clients/abe/ProtobufEmpty.go @@ -0,0 +1,8 @@ +package abe + +import ( +) + +type ProtobufEmpty struct { + +} diff --git a/examples/clients/abe/Sub2IdMessage.go b/examples/clients/abe/Sub2IdMessage.go new file mode 100644 index 00000000000..77ebe152ba0 --- /dev/null +++ b/examples/clients/abe/Sub2IdMessage.go @@ -0,0 +1,9 @@ +package abe + +import ( +) + +type Sub2IdMessage struct { + Uuid string `json:"uuid,omitempty"` + +} diff --git a/examples/clients/abe/SubStringMessage.go b/examples/clients/abe/SubStringMessage.go new file mode 100644 index 00000000000..f278dbf258b --- /dev/null +++ b/examples/clients/abe/SubStringMessage.go @@ -0,0 +1,9 @@ +package abe + +import ( +) + +type SubStringMessage struct { + Value string `json:"value,omitempty"` + +} diff --git a/examples/clients/echo/EchoServiceApi.go b/examples/clients/echo/EchoServiceApi.go new file mode 100644 index 00000000000..0cf5b582740 --- /dev/null +++ b/examples/clients/echo/EchoServiceApi.go @@ -0,0 +1,145 @@ +package echo + +import ( + "strings" + "fmt" + "encoding/json" + "errors" + "github.com/dghubble/sling" +) + +type EchoServiceApi struct { + basePath string +} + +func NewEchoServiceApi() *EchoServiceApi{ + return &EchoServiceApi { + basePath: "http://localhost", + } +} + +func NewEchoServiceApiWithBasePath(basePath string) *EchoServiceApi{ + return &EchoServiceApi { + basePath: basePath, + } +} + +/** + * Echo method receives a simple message and returns it. + * The message posted as the id parameter will also be\nreturned. + * @param id + * @return ExamplepbSimpleMessage + */ +//func (a EchoServiceApi) Echo (id string) (ExamplepbSimpleMessage, error) { +func (a EchoServiceApi) Echo (id string) (ExamplepbSimpleMessage, error) { + + _sling := sling.New().Post(a.basePath) + + // create path and map variables + path := "/v1/example/echo/{id}" + path = strings.Replace(path, "{" + "id" + "}", fmt.Sprintf("%v", id), -1) + + _sling = _sling.Path(path) + + // accept header + accepts := []string { "application/json" } + for key := range accepts { + _sling = _sling.Set("Accept", accepts[key]) + break // only use the first Accept + } + + + var successPayload = new(ExamplepbSimpleMessage) + + // We use this map (below) so that any arbitrary error JSON can be handled. + // FIXME: This is in the absence of this Go generator honoring the non-2xx + // response (error) models, which needs to be implemented at some point. + var failurePayload map[string]interface{} + + httpResponse, err := _sling.Receive(successPayload, &failurePayload) + + if err == nil { + // err == nil only means that there wasn't a sub-application-layer error (e.g. no network error) + if failurePayload != nil { + // If the failurePayload is present, there likely was some kind of non-2xx status + // returned (and a JSON payload error present) + var str []byte + str, err = json.Marshal(failurePayload) + if err == nil { // For safety, check for an error marshalling... probably superfluous + // This will return the JSON error body as a string + err = errors.New(string(str)) + } + } else { + // So, there was no network-type error, and nothing in the failure payload, + // but we should still check the status code + if httpResponse == nil { + // This should never happen... + err = errors.New("No HTTP Response received.") + } else if code := httpResponse.StatusCode; 200 > code || code > 299 { + err = errors.New("HTTP Error: " + string(httpResponse.StatusCode)) + } + } + } + + return *successPayload, err +} +/** + * EchoBody method receives a simple message and returns it. + * + * @param body + * @return ExamplepbSimpleMessage + */ +//func (a EchoServiceApi) EchoBody (body ExamplepbSimpleMessage) (ExamplepbSimpleMessage, error) { +func (a EchoServiceApi) EchoBody (body ExamplepbSimpleMessage) (ExamplepbSimpleMessage, error) { + + _sling := sling.New().Post(a.basePath) + + // create path and map variables + path := "/v1/example/echo_body" + + _sling = _sling.Path(path) + + // accept header + accepts := []string { "application/json" } + for key := range accepts { + _sling = _sling.Set("Accept", accepts[key]) + break // only use the first Accept + } + +// body params + _sling = _sling.BodyJSON(body) + + var successPayload = new(ExamplepbSimpleMessage) + + // We use this map (below) so that any arbitrary error JSON can be handled. + // FIXME: This is in the absence of this Go generator honoring the non-2xx + // response (error) models, which needs to be implemented at some point. + var failurePayload map[string]interface{} + + httpResponse, err := _sling.Receive(successPayload, &failurePayload) + + if err == nil { + // err == nil only means that there wasn't a sub-application-layer error (e.g. no network error) + if failurePayload != nil { + // If the failurePayload is present, there likely was some kind of non-2xx status + // returned (and a JSON payload error present) + var str []byte + str, err = json.Marshal(failurePayload) + if err == nil { // For safety, check for an error marshalling... probably superfluous + // This will return the JSON error body as a string + err = errors.New(string(str)) + } + } else { + // So, there was no network-type error, and nothing in the failure payload, + // but we should still check the status code + if httpResponse == nil { + // This should never happen... + err = errors.New("No HTTP Response received.") + } else if code := httpResponse.StatusCode; 200 > code || code > 299 { + err = errors.New("HTTP Error: " + string(httpResponse.StatusCode)) + } + } + } + + return *successPayload, err +} diff --git a/examples/clients/echo/ExamplepbSimpleMessage.go b/examples/clients/echo/ExamplepbSimpleMessage.go new file mode 100644 index 00000000000..ed9ada35b70 --- /dev/null +++ b/examples/clients/echo/ExamplepbSimpleMessage.go @@ -0,0 +1,9 @@ +package echo + +import ( +) + +type ExamplepbSimpleMessage struct { + Id string `json:"id,omitempty"` + +} diff --git a/examples/examplepb/a_bit_of_everything.swagger.json b/examples/examplepb/a_bit_of_everything.swagger.json index 801180b197c..fc6611d210f 100644 --- a/examples/examplepb/a_bit_of_everything.swagger.json +++ b/examples/examplepb/a_bit_of_everything.swagger.json @@ -96,15 +96,15 @@ "name": "int64_value", "in": "path", "required": true, - "type": "integer", + "type": "string", "format": "int64" }, { "name": "uint64_value", "in": "path", "required": true, - "type": "integer", - "format": "int64" + "type": "string", + "format": "uint64" }, { "name": "int32_value", @@ -117,15 +117,15 @@ "name": "fixed64_value", "in": "path", "required": true, - "type": "integer", - "format": "int64" + "type": "string", + "format": "uint64" }, { "name": "fixed32_value", "in": "path", "required": true, "type": "integer", - "format": "int32" + "format": "int64" }, { "name": "bool_value", @@ -159,8 +159,8 @@ "name": "sfixed64_value", "in": "path", "required": true, - "type": "integer", - "format": "int32" + "type": "string", + "format": "int64" }, { "name": "sint32_value", @@ -173,7 +173,7 @@ "name": "sint64_value", "in": "path", "required": true, - "type": "integer", + "type": "string", "format": "int64" }, { @@ -402,11 +402,11 @@ }, "fixed32_value": { "type": "integer", - "format": "int32" + "format": "int64" }, "fixed64_value": { - "type": "integer", - "format": "int64" + "type": "string", + "format": "uint64" }, "float_value": { "type": "number", @@ -417,7 +417,7 @@ "format": "int32" }, "int64_value": { - "type": "integer", + "type": "string", "format": "int64" }, "map_value": { @@ -468,8 +468,8 @@ "format": "int32" }, "sfixed64_value": { - "type": "integer", - "format": "int32" + "type": "string", + "format": "int64" }, "single_nested": { "$ref": "#/definitions/ABitOfEverythingNested" @@ -479,7 +479,7 @@ "format": "int32" }, "sint64_value": { - "type": "integer", + "type": "string", "format": "int64" }, "string_value": { @@ -492,8 +492,8 @@ "title": "TODO(yugui) add bytes_value" }, "uint64_value": { - "type": "integer", - "format": "int64" + "type": "string", + "format": "uint64" }, "uuid": { "type": "string", diff --git a/examples/integration_test.go b/examples/integration_test.go index 60599ba714d..eee2a6d6d4b 100644 --- a/examples/integration_test.go +++ b/examples/integration_test.go @@ -13,7 +13,6 @@ import ( "time" gw "github.com/gengo/grpc-gateway/examples/examplepb" - server "github.com/gengo/grpc-gateway/examples/server" sub "github.com/gengo/grpc-gateway/examples/sub" "github.com/gengo/grpc-gateway/runtime" "github.com/golang/protobuf/jsonpb" @@ -28,37 +27,17 @@ type errorBody struct { Code int `json:"code"` } -func TestIntegration(t *testing.T) { +func TestEcho(t *testing.T) { if testing.Short() { t.Skip() return } - go func() { - if err := server.Run(); err != nil { - t.Errorf("server.Run() failed with %v; want success", err) - return - } - }() - go func() { - if err := Run(":8080"); err != nil { - t.Errorf("gw.Run() failed with %v; want success", err) - return - } - }() - - time.Sleep(100 * time.Millisecond) testEcho(t, 8080, "application/json") testEchoBody(t) - testABECreate(t) - testABECreateBody(t) - testABEBulkCreate(t) - testABELookup(t) - testABELookupNotFound(t) - testABEList(t) - testAdditionalBindings(t) - testTimeout(t) +} +func TestForwardResponseOption(t *testing.T) { go func() { if err := Run( ":8081", @@ -161,6 +140,21 @@ func testEchoBody(t *testing.T) { } } +func TestABE(t *testing.T) { + if testing.Short() { + t.Skip() + return + } + + testABECreate(t) + testABECreateBody(t) + testABEBulkCreate(t) + testABELookup(t) + testABELookupNotFound(t) + testABEList(t) + testAdditionalBindings(t) +} + func testABECreate(t *testing.T) { want := gw.ABitOfEverything{ FloatValue: 1.5, @@ -584,7 +578,7 @@ func testAdditionalBindings(t *testing.T) { } } -func testTimeout(t *testing.T) { +func TestTimeout(t *testing.T) { url := "http://localhost:8080/v2/example/timeout" req, err := http.NewRequest("GET", url, nil) if err != nil { diff --git a/examples/main_test.go b/examples/main_test.go new file mode 100644 index 00000000000..c5ed4d46638 --- /dev/null +++ b/examples/main_test.go @@ -0,0 +1,45 @@ +package main + +import ( + "flag" + "fmt" + "os" + "testing" + "time" + + server "github.com/gengo/grpc-gateway/examples/server" +) + +func runServers() <-chan error { + ch := make(chan error, 2) + go func() { + if err := server.Run(); err != nil { + ch <- fmt.Errorf("cannot run grpc service: %v", err) + } + }() + go func() { + if err := Run(":8080"); err != nil { + ch <- fmt.Errorf("cannot run gateway service: %v", err) + } + }() + return ch +} + +func TestMain(m *testing.M) { + flag.Parse() + errCh := runServers() + + ch := make(chan int, 1) + go func() { + time.Sleep(100 * time.Millisecond) + ch <- m.Run() + }() + + select { + case err := <-errCh: + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + case status := <-ch: + os.Exit(status) + } +} diff --git a/protoc-gen-swagger/genswagger/template.go b/protoc-gen-swagger/genswagger/template.go index 93bf01ebc68..c12f78ce573 100644 --- a/protoc-gen-swagger/genswagger/template.go +++ b/protoc-gen-swagger/genswagger/template.go @@ -146,15 +146,22 @@ func primitiveSchema(t pbdescriptor.FieldDescriptorProto_Type) (ftype, format st case pbdescriptor.FieldDescriptorProto_TYPE_FLOAT: return "number", "float", true case pbdescriptor.FieldDescriptorProto_TYPE_INT64: - return "integer", "int64", true + return "string", "int64", true case pbdescriptor.FieldDescriptorProto_TYPE_UINT64: - return "integer", "int64", true + // 64bit integer types are marshaled as string in the default JSONPb marshaler. + // TODO(yugui) Add an option to declare 64bit integers as int64. + // + // NOTE: uint64 is not a predefined format of integer type in Swagger spec. + // So we cannot expect that uint64 is commonly supported by swagger processor. + return "string", "uint64", true case pbdescriptor.FieldDescriptorProto_TYPE_INT32: return "integer", "int32", true case pbdescriptor.FieldDescriptorProto_TYPE_FIXED64: - return "integer", "int64", true + // Ditto. + return "string", "uint64", true case pbdescriptor.FieldDescriptorProto_TYPE_FIXED32: - return "integer", "int32", true + // Ditto. + return "integer", "int64", true case pbdescriptor.FieldDescriptorProto_TYPE_BOOL: return "boolean", "boolean", true case pbdescriptor.FieldDescriptorProto_TYPE_STRING: @@ -162,15 +169,16 @@ func primitiveSchema(t pbdescriptor.FieldDescriptorProto_Type) (ftype, format st case pbdescriptor.FieldDescriptorProto_TYPE_BYTES: return "string", "byte", true case pbdescriptor.FieldDescriptorProto_TYPE_UINT32: + // Ditto. return "integer", "int64", true case pbdescriptor.FieldDescriptorProto_TYPE_SFIXED32: return "integer", "int32", true case pbdescriptor.FieldDescriptorProto_TYPE_SFIXED64: - return "integer", "int32", true + return "string", "int64", true case pbdescriptor.FieldDescriptorProto_TYPE_SINT32: return "integer", "int32", true case pbdescriptor.FieldDescriptorProto_TYPE_SINT64: - return "integer", "int64", true + return "string", "int64", true default: return "", "", false }