diff --git a/examples/clients/echo/BUILD.bazel b/examples/clients/echo/BUILD.bazel index 99243f3cded..090b56aafab 100644 --- a/examples/clients/echo/BUILD.bazel +++ b/examples/clients/echo/BUILD.bazel @@ -9,6 +9,7 @@ go_library( "api_response.go", "configuration.go", "echo_service_api.go", + "examplepb_embedded.go", "examplepb_simple_message.go", ], importpath = "github.com/grpc-ecosystem/grpc-gateway/examples/clients/echo", diff --git a/examples/clients/echo/echo_service_api.go b/examples/clients/echo/echo_service_api.go index 41316dce169..775d0b3a7e6 100644 --- a/examples/clients/echo/echo_service_api.go +++ b/examples/clients/echo/echo_service_api.go @@ -104,9 +104,16 @@ func (a EchoServiceApi) Echo(id string) (*ExamplepbSimpleMessage, *APIResponse, * * @param id * @param num + * @param lineNum + * @param lang + * @param statusProgress + * @param statusNote + * @param en + * @param noProgress + * @param noNote * @return *ExamplepbSimpleMessage */ -func (a EchoServiceApi) Echo2(id string, num string) (*ExamplepbSimpleMessage, *APIResponse, error) { +func (a EchoServiceApi) Echo2(id string, num string, lineNum string, lang string, statusProgress string, statusNote string, en string, noProgress string, noNote string) (*ExamplepbSimpleMessage, *APIResponse, error) { var localVarHttpMethod = strings.ToUpper("Get") // create path and map variables @@ -124,6 +131,13 @@ func (a EchoServiceApi) Echo2(id string, num string) (*ExamplepbSimpleMessage, * for key := range a.Configuration.DefaultHeader { localVarHeaderParams[key] = a.Configuration.DefaultHeader[key] } + localVarQueryParams.Add("line_num", a.Configuration.APIClient.ParameterToString(lineNum, "")) + localVarQueryParams.Add("lang", a.Configuration.APIClient.ParameterToString(lang, "")) + localVarQueryParams.Add("status.progress", a.Configuration.APIClient.ParameterToString(statusProgress, "")) + localVarQueryParams.Add("status.note", a.Configuration.APIClient.ParameterToString(statusNote, "")) + localVarQueryParams.Add("en", a.Configuration.APIClient.ParameterToString(en, "")) + localVarQueryParams.Add("no.progress", a.Configuration.APIClient.ParameterToString(noProgress, "")) + localVarQueryParams.Add("no.note", a.Configuration.APIClient.ParameterToString(noNote, "")) // to determine the Content-Type header localVarHttpContentTypes := []string{ "application/json", } @@ -161,6 +175,233 @@ func (a EchoServiceApi) Echo2(id string, num string) (*ExamplepbSimpleMessage, * return successPayload, localVarAPIResponse, err } +/** + * Echo method receives a simple message and returns it. + * The message posted as the id parameter will also be returned. + * + * @param id + * @param num + * @param lang + * @param lineNum + * @param statusProgress + * @param statusNote + * @param en + * @param noProgress + * @param noNote + * @return *ExamplepbSimpleMessage + */ +func (a EchoServiceApi) Echo3(id string, num string, lang string, lineNum string, statusProgress string, statusNote string, en string, noProgress string, noNote string) (*ExamplepbSimpleMessage, *APIResponse, error) { + + var localVarHttpMethod = strings.ToUpper("Get") + // create path and map variables + localVarPath := a.Configuration.BasePath + "/v1/example/echo/{id}/{num}/{lang}" + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", fmt.Sprintf("%v", id), -1) + localVarPath = strings.Replace(localVarPath, "{"+"num"+"}", fmt.Sprintf("%v", num), -1) + localVarPath = strings.Replace(localVarPath, "{"+"lang"+"}", fmt.Sprintf("%v", lang), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := make(map[string]string) + var localVarPostBody interface{} + var localVarFileName string + var localVarFileBytes []byte + // add default headers if any + for key := range a.Configuration.DefaultHeader { + localVarHeaderParams[key] = a.Configuration.DefaultHeader[key] + } + localVarQueryParams.Add("line_num", a.Configuration.APIClient.ParameterToString(lineNum, "")) + localVarQueryParams.Add("status.progress", a.Configuration.APIClient.ParameterToString(statusProgress, "")) + localVarQueryParams.Add("status.note", a.Configuration.APIClient.ParameterToString(statusNote, "")) + localVarQueryParams.Add("en", a.Configuration.APIClient.ParameterToString(en, "")) + localVarQueryParams.Add("no.progress", a.Configuration.APIClient.ParameterToString(noProgress, "")) + localVarQueryParams.Add("no.note", a.Configuration.APIClient.ParameterToString(noNote, "")) + + // to determine the Content-Type header + localVarHttpContentTypes := []string{ "application/json", } + + // set Content-Type header + localVarHttpContentType := a.Configuration.APIClient.SelectHeaderContentType(localVarHttpContentTypes) + if localVarHttpContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHttpContentType + } + // to determine the Accept header + localVarHttpHeaderAccepts := []string{ + "application/json", + } + + // set Accept header + localVarHttpHeaderAccept := a.Configuration.APIClient.SelectHeaderAccept(localVarHttpHeaderAccepts) + if localVarHttpHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHttpHeaderAccept + } + var successPayload = new(ExamplepbSimpleMessage) + localVarHttpResponse, err := a.Configuration.APIClient.CallAPI(localVarPath, localVarHttpMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFileName, localVarFileBytes) + + var localVarURL, _ = url.Parse(localVarPath) + localVarURL.RawQuery = localVarQueryParams.Encode() + var localVarAPIResponse = &APIResponse{Operation: "Echo3", Method: localVarHttpMethod, RequestURL: localVarURL.String()} + if localVarHttpResponse != nil { + localVarAPIResponse.Response = localVarHttpResponse.RawResponse + localVarAPIResponse.Payload = localVarHttpResponse.Body() + } + + if err != nil { + return successPayload, localVarAPIResponse, err + } + err = json.Unmarshal(localVarHttpResponse.Body(), &successPayload) + return successPayload, localVarAPIResponse, err +} + +/** + * Echo method receives a simple message and returns it. + * The message posted as the id parameter will also be returned. + * + * @param id + * @param lineNum + * @param statusNote + * @param num + * @param lang + * @param statusProgress + * @param en + * @param noProgress + * @return *ExamplepbSimpleMessage + */ +func (a EchoServiceApi) Echo4(id string, lineNum string, statusNote string, num string, lang string, statusProgress string, en string, noProgress string) (*ExamplepbSimpleMessage, *APIResponse, error) { + + var localVarHttpMethod = strings.ToUpper("Get") + // create path and map variables + localVarPath := a.Configuration.BasePath + "/v1/example/echo1/{id}/{line_num}/{status.note}" + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", fmt.Sprintf("%v", id), -1) + localVarPath = strings.Replace(localVarPath, "{"+"line_num"+"}", fmt.Sprintf("%v", lineNum), -1) + localVarPath = strings.Replace(localVarPath, "{"+"status.note"+"}", fmt.Sprintf("%v", statusNote), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := make(map[string]string) + var localVarPostBody interface{} + var localVarFileName string + var localVarFileBytes []byte + // add default headers if any + for key := range a.Configuration.DefaultHeader { + localVarHeaderParams[key] = a.Configuration.DefaultHeader[key] + } + localVarQueryParams.Add("num", a.Configuration.APIClient.ParameterToString(num, "")) + localVarQueryParams.Add("lang", a.Configuration.APIClient.ParameterToString(lang, "")) + localVarQueryParams.Add("status.progress", a.Configuration.APIClient.ParameterToString(statusProgress, "")) + localVarQueryParams.Add("en", a.Configuration.APIClient.ParameterToString(en, "")) + localVarQueryParams.Add("no.progress", a.Configuration.APIClient.ParameterToString(noProgress, "")) + + // to determine the Content-Type header + localVarHttpContentTypes := []string{ "application/json", } + + // set Content-Type header + localVarHttpContentType := a.Configuration.APIClient.SelectHeaderContentType(localVarHttpContentTypes) + if localVarHttpContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHttpContentType + } + // to determine the Accept header + localVarHttpHeaderAccepts := []string{ + "application/json", + } + + // set Accept header + localVarHttpHeaderAccept := a.Configuration.APIClient.SelectHeaderAccept(localVarHttpHeaderAccepts) + if localVarHttpHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHttpHeaderAccept + } + var successPayload = new(ExamplepbSimpleMessage) + localVarHttpResponse, err := a.Configuration.APIClient.CallAPI(localVarPath, localVarHttpMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFileName, localVarFileBytes) + + var localVarURL, _ = url.Parse(localVarPath) + localVarURL.RawQuery = localVarQueryParams.Encode() + var localVarAPIResponse = &APIResponse{Operation: "Echo4", Method: localVarHttpMethod, RequestURL: localVarURL.String()} + if localVarHttpResponse != nil { + localVarAPIResponse.Response = localVarHttpResponse.RawResponse + localVarAPIResponse.Payload = localVarHttpResponse.Body() + } + + if err != nil { + return successPayload, localVarAPIResponse, err + } + err = json.Unmarshal(localVarHttpResponse.Body(), &successPayload) + return successPayload, localVarAPIResponse, err +} + +/** + * Echo method receives a simple message and returns it. + * The message posted as the id parameter will also be returned. + * + * @param noNote + * @param id Id represents the message identifier. + * @param num + * @param lineNum + * @param lang + * @param statusProgress + * @param en + * @param noProgress + * @return *ExamplepbSimpleMessage + */ +func (a EchoServiceApi) Echo5(noNote string, id string, num string, lineNum string, lang string, statusProgress string, en string, noProgress string) (*ExamplepbSimpleMessage, *APIResponse, error) { + + var localVarHttpMethod = strings.ToUpper("Get") + // create path and map variables + localVarPath := a.Configuration.BasePath + "/v1/example/echo2/{no.note}" + localVarPath = strings.Replace(localVarPath, "{"+"no.note"+"}", fmt.Sprintf("%v", noNote), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := make(map[string]string) + var localVarPostBody interface{} + var localVarFileName string + var localVarFileBytes []byte + // add default headers if any + for key := range a.Configuration.DefaultHeader { + localVarHeaderParams[key] = a.Configuration.DefaultHeader[key] + } + localVarQueryParams.Add("id", a.Configuration.APIClient.ParameterToString(id, "")) + localVarQueryParams.Add("num", a.Configuration.APIClient.ParameterToString(num, "")) + localVarQueryParams.Add("line_num", a.Configuration.APIClient.ParameterToString(lineNum, "")) + localVarQueryParams.Add("lang", a.Configuration.APIClient.ParameterToString(lang, "")) + localVarQueryParams.Add("status.progress", a.Configuration.APIClient.ParameterToString(statusProgress, "")) + localVarQueryParams.Add("en", a.Configuration.APIClient.ParameterToString(en, "")) + localVarQueryParams.Add("no.progress", a.Configuration.APIClient.ParameterToString(noProgress, "")) + + // to determine the Content-Type header + localVarHttpContentTypes := []string{ "application/json", } + + // set Content-Type header + localVarHttpContentType := a.Configuration.APIClient.SelectHeaderContentType(localVarHttpContentTypes) + if localVarHttpContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHttpContentType + } + // to determine the Accept header + localVarHttpHeaderAccepts := []string{ + "application/json", + } + + // set Accept header + localVarHttpHeaderAccept := a.Configuration.APIClient.SelectHeaderAccept(localVarHttpHeaderAccepts) + if localVarHttpHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHttpHeaderAccept + } + var successPayload = new(ExamplepbSimpleMessage) + localVarHttpResponse, err := a.Configuration.APIClient.CallAPI(localVarPath, localVarHttpMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFileName, localVarFileBytes) + + var localVarURL, _ = url.Parse(localVarPath) + localVarURL.RawQuery = localVarQueryParams.Encode() + var localVarAPIResponse = &APIResponse{Operation: "Echo5", Method: localVarHttpMethod, RequestURL: localVarURL.String()} + if localVarHttpResponse != nil { + localVarAPIResponse.Response = localVarHttpResponse.RawResponse + localVarAPIResponse.Payload = localVarHttpResponse.Body() + } + + if err != nil { + return successPayload, localVarAPIResponse, err + } + err = json.Unmarshal(localVarHttpResponse.Body(), &successPayload) + return successPayload, localVarAPIResponse, err +} + /** * EchoBody method receives a simple message and returns it. * @@ -227,9 +468,16 @@ func (a EchoServiceApi) EchoBody(body ExamplepbSimpleMessage) (*ExamplepbSimpleM * * @param id Id represents the message identifier. * @param num + * @param lineNum + * @param lang + * @param statusProgress + * @param statusNote + * @param en + * @param noProgress + * @param noNote * @return *ExamplepbSimpleMessage */ -func (a EchoServiceApi) EchoDelete(id string, num string) (*ExamplepbSimpleMessage, *APIResponse, error) { +func (a EchoServiceApi) EchoDelete(id string, num string, lineNum string, lang string, statusProgress string, statusNote string, en string, noProgress string, noNote string) (*ExamplepbSimpleMessage, *APIResponse, error) { var localVarHttpMethod = strings.ToUpper("Delete") // create path and map variables @@ -247,6 +495,13 @@ func (a EchoServiceApi) EchoDelete(id string, num string) (*ExamplepbSimpleMessa } localVarQueryParams.Add("id", a.Configuration.APIClient.ParameterToString(id, "")) localVarQueryParams.Add("num", a.Configuration.APIClient.ParameterToString(num, "")) + localVarQueryParams.Add("line_num", a.Configuration.APIClient.ParameterToString(lineNum, "")) + localVarQueryParams.Add("lang", a.Configuration.APIClient.ParameterToString(lang, "")) + localVarQueryParams.Add("status.progress", a.Configuration.APIClient.ParameterToString(statusProgress, "")) + localVarQueryParams.Add("status.note", a.Configuration.APIClient.ParameterToString(statusNote, "")) + localVarQueryParams.Add("en", a.Configuration.APIClient.ParameterToString(en, "")) + localVarQueryParams.Add("no.progress", a.Configuration.APIClient.ParameterToString(noProgress, "")) + localVarQueryParams.Add("no.note", a.Configuration.APIClient.ParameterToString(noNote, "")) // to determine the Content-Type header localVarHttpContentTypes := []string{ "application/json", } diff --git a/examples/clients/echo/examplepb_embedded.go b/examples/clients/echo/examplepb_embedded.go new file mode 100644 index 00000000000..4b5fe265ac9 --- /dev/null +++ b/examples/clients/echo/examplepb_embedded.go @@ -0,0 +1,19 @@ +/* + * Echo Service + * + * Echo Service API consists of a single service which returns a message. + * + * OpenAPI spec version: version not set + * + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ + +package echo + +// Embedded represents a message embedded in SimpleMessage. +type ExamplepbEmbedded struct { + + Progress string `json:"progress,omitempty"` + + Note string `json:"note,omitempty"` +} diff --git a/examples/clients/echo/examplepb_simple_message.go b/examples/clients/echo/examplepb_simple_message.go index 98eb8325083..366a6876665 100644 --- a/examples/clients/echo/examplepb_simple_message.go +++ b/examples/clients/echo/examplepb_simple_message.go @@ -17,4 +17,14 @@ type ExamplepbSimpleMessage struct { Id string `json:"id,omitempty"` Num string `json:"num,omitempty"` + + LineNum string `json:"line_num,omitempty"` + + Lang string `json:"lang,omitempty"` + + Status ExamplepbEmbedded `json:"status,omitempty"` + + En string `json:"en,omitempty"` + + No ExamplepbEmbedded `json:"no,omitempty"` } diff --git a/examples/integration/integration_test.go b/examples/integration/integration_test.go index 97b72dba717..78f05591dd7 100644 --- a/examples/integration/integration_test.go +++ b/examples/integration/integration_test.go @@ -37,6 +37,9 @@ func TestEcho(t *testing.T) { } testEcho(t, 8080, "application/json") + testEchoOneof(t, 8080, "application/json") + testEchoOneof1(t, 8080, "application/json") + testEchoOneof2(t, 8080, "application/json") testEchoBody(t, 8080) } @@ -98,6 +101,105 @@ func testEcho(t *testing.T, port int, contentType string) { } } +func testEchoOneof(t *testing.T, port int, contentType string) { + url := fmt.Sprintf("http://localhost:%d/v1/example/echo/myid/10/golang", port) + resp, err := http.Get(url) + if err != nil { + t.Errorf("http.Get(%q) failed with %v; want success", url, err) + return + } + defer resp.Body.Close() + buf, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Errorf("iotuil.ReadAll(resp.Body) failed with %v; want success", err) + return + } + + if got, want := resp.StatusCode, http.StatusOK; got != want { + t.Errorf("resp.StatusCode = %d; want %d", got, want) + t.Logf("%s", buf) + } + + var msg gw.SimpleMessage + if err := jsonpb.UnmarshalString(string(buf), &msg); err != nil { + t.Errorf("jsonpb.UnmarshalString(%s, &msg) failed with %v; want success", buf, err) + return + } + if got, want := msg.GetLang(), "golang"; got != want { + t.Errorf("msg.GetLang() = %q; want %q", got, want) + } + + if value := resp.Header.Get("Content-Type"); value != contentType { + t.Errorf("Content-Type was %s, wanted %s", value, contentType) + } +} + +func testEchoOneof1(t *testing.T, port int, contentType string) { + url := fmt.Sprintf("http://localhost:%d/v1/example/echo1/myid/10/golang", port) + resp, err := http.Get(url) + if err != nil { + t.Errorf("http.Get(%q) failed with %v; want success", url, err) + return + } + defer resp.Body.Close() + buf, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Errorf("iotuil.ReadAll(resp.Body) failed with %v; want success", err) + return + } + + if got, want := resp.StatusCode, http.StatusOK; got != want { + t.Errorf("resp.StatusCode = %d; want %d", got, want) + t.Logf("%s", buf) + } + + var msg gw.SimpleMessage + if err := jsonpb.UnmarshalString(string(buf), &msg); err != nil { + t.Errorf("jsonpb.UnmarshalString(%s, &msg) failed with %v; want success", buf, err) + return + } + if got, want := msg.GetStatus().GetNote(), "golang"; got != want { + t.Errorf("msg.GetStatus().GetNote() = %q; want %q", got, want) + } + + if value := resp.Header.Get("Content-Type"); value != contentType { + t.Errorf("Content-Type was %s, wanted %s", value, contentType) + } +} + +func testEchoOneof2(t *testing.T, port int, contentType string) { + url := fmt.Sprintf("http://localhost:%d/v1/example/echo2/golang", port) + resp, err := http.Get(url) + if err != nil { + t.Errorf("http.Get(%q) failed with %v; want success", url, err) + return + } + defer resp.Body.Close() + buf, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Errorf("iotuil.ReadAll(resp.Body) failed with %v; want success", err) + return + } + + if got, want := resp.StatusCode, http.StatusOK; got != want { + t.Errorf("resp.StatusCode = %d; want %d", got, want) + t.Logf("%s", buf) + } + + var msg gw.SimpleMessage + if err := jsonpb.UnmarshalString(string(buf), &msg); err != nil { + t.Errorf("jsonpb.UnmarshalString(%s, &msg) failed with %v; want success", buf, err) + return + } + if got, want := msg.GetNo().GetNote(), "golang"; got != want { + t.Errorf("msg.GetNo().GetNote() = %q; want %q", got, want) + } + + if value := resp.Header.Get("Content-Type"); value != contentType { + t.Errorf("Content-Type was %s, wanted %s", value, contentType) + } +} + func testEchoBody(t *testing.T, port int) { sent := gw.SimpleMessage{Id: "example"} var m jsonpb.Marshaler diff --git a/examples/proto/examplepb/echo_service.pb.go b/examples/proto/examplepb/echo_service.pb.go index 2e61c94ed01..f200e4881ac 100644 --- a/examples/proto/examplepb/echo_service.pb.go +++ b/examples/proto/examplepb/echo_service.pb.go @@ -18,6 +18,7 @@ It is generated from these files: examples/proto/examplepb/unannotated_echo_service.proto It has these top-level messages: + Embedded SimpleMessage ABitOfEverything Body @@ -53,17 +54,177 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package +// Embedded represents a message embedded in SimpleMessage. +type Embedded struct { + // Types that are valid to be assigned to Mark: + // *Embedded_Progress + // *Embedded_Note + Mark isEmbedded_Mark `protobuf_oneof:"mark"` +} + +func (m *Embedded) Reset() { *m = Embedded{} } +func (m *Embedded) String() string { return proto.CompactTextString(m) } +func (*Embedded) ProtoMessage() {} +func (*Embedded) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +type isEmbedded_Mark interface { + isEmbedded_Mark() +} + +type Embedded_Progress struct { + Progress int64 `protobuf:"varint,1,opt,name=progress,oneof"` +} +type Embedded_Note struct { + Note string `protobuf:"bytes,2,opt,name=note,oneof"` +} + +func (*Embedded_Progress) isEmbedded_Mark() {} +func (*Embedded_Note) isEmbedded_Mark() {} + +func (m *Embedded) GetMark() isEmbedded_Mark { + if m != nil { + return m.Mark + } + return nil +} + +func (m *Embedded) GetProgress() int64 { + if x, ok := m.GetMark().(*Embedded_Progress); ok { + return x.Progress + } + return 0 +} + +func (m *Embedded) GetNote() string { + if x, ok := m.GetMark().(*Embedded_Note); ok { + return x.Note + } + return "" +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*Embedded) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _Embedded_OneofMarshaler, _Embedded_OneofUnmarshaler, _Embedded_OneofSizer, []interface{}{ + (*Embedded_Progress)(nil), + (*Embedded_Note)(nil), + } +} + +func _Embedded_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*Embedded) + // mark + switch x := m.Mark.(type) { + case *Embedded_Progress: + b.EncodeVarint(1<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.Progress)) + case *Embedded_Note: + b.EncodeVarint(2<<3 | proto.WireBytes) + b.EncodeStringBytes(x.Note) + case nil: + default: + return fmt.Errorf("Embedded.Mark has unexpected type %T", x) + } + return nil +} + +func _Embedded_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*Embedded) + switch tag { + case 1: // mark.progress + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Mark = &Embedded_Progress{int64(x)} + return true, err + case 2: // mark.note + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.Mark = &Embedded_Note{x} + return true, err + default: + return false, nil + } +} + +func _Embedded_OneofSizer(msg proto.Message) (n int) { + m := msg.(*Embedded) + // mark + switch x := m.Mark.(type) { + case *Embedded_Progress: + n += proto.SizeVarint(1<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.Progress)) + case *Embedded_Note: + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.Note))) + n += len(x.Note) + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + // SimpleMessage represents a simple message sent to the Echo service. type SimpleMessage struct { // Id represents the message identifier. Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"` Num int64 `protobuf:"varint,2,opt,name=num" json:"num,omitempty"` + // Types that are valid to be assigned to Code: + // *SimpleMessage_LineNum + // *SimpleMessage_Lang + Code isSimpleMessage_Code `protobuf_oneof:"code"` + Status *Embedded `protobuf:"bytes,5,opt,name=status" json:"status,omitempty"` + // Types that are valid to be assigned to Ext: + // *SimpleMessage_En + // *SimpleMessage_No + Ext isSimpleMessage_Ext `protobuf_oneof:"ext"` } func (m *SimpleMessage) Reset() { *m = SimpleMessage{} } func (m *SimpleMessage) String() string { return proto.CompactTextString(m) } func (*SimpleMessage) ProtoMessage() {} -func (*SimpleMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (*SimpleMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +type isSimpleMessage_Code interface { + isSimpleMessage_Code() +} +type isSimpleMessage_Ext interface { + isSimpleMessage_Ext() +} + +type SimpleMessage_LineNum struct { + LineNum int64 `protobuf:"varint,3,opt,name=line_num,json=lineNum,oneof"` +} +type SimpleMessage_Lang struct { + Lang string `protobuf:"bytes,4,opt,name=lang,oneof"` +} +type SimpleMessage_En struct { + En int64 `protobuf:"varint,6,opt,name=en,oneof"` +} +type SimpleMessage_No struct { + No *Embedded `protobuf:"bytes,7,opt,name=no,oneof"` +} + +func (*SimpleMessage_LineNum) isSimpleMessage_Code() {} +func (*SimpleMessage_Lang) isSimpleMessage_Code() {} +func (*SimpleMessage_En) isSimpleMessage_Ext() {} +func (*SimpleMessage_No) isSimpleMessage_Ext() {} + +func (m *SimpleMessage) GetCode() isSimpleMessage_Code { + if m != nil { + return m.Code + } + return nil +} +func (m *SimpleMessage) GetExt() isSimpleMessage_Ext { + if m != nil { + return m.Ext + } + return nil +} func (m *SimpleMessage) GetId() string { if m != nil { @@ -79,7 +240,153 @@ func (m *SimpleMessage) GetNum() int64 { return 0 } +func (m *SimpleMessage) GetLineNum() int64 { + if x, ok := m.GetCode().(*SimpleMessage_LineNum); ok { + return x.LineNum + } + return 0 +} + +func (m *SimpleMessage) GetLang() string { + if x, ok := m.GetCode().(*SimpleMessage_Lang); ok { + return x.Lang + } + return "" +} + +func (m *SimpleMessage) GetStatus() *Embedded { + if m != nil { + return m.Status + } + return nil +} + +func (m *SimpleMessage) GetEn() int64 { + if x, ok := m.GetExt().(*SimpleMessage_En); ok { + return x.En + } + return 0 +} + +func (m *SimpleMessage) GetNo() *Embedded { + if x, ok := m.GetExt().(*SimpleMessage_No); ok { + return x.No + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*SimpleMessage) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _SimpleMessage_OneofMarshaler, _SimpleMessage_OneofUnmarshaler, _SimpleMessage_OneofSizer, []interface{}{ + (*SimpleMessage_LineNum)(nil), + (*SimpleMessage_Lang)(nil), + (*SimpleMessage_En)(nil), + (*SimpleMessage_No)(nil), + } +} + +func _SimpleMessage_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*SimpleMessage) + // code + switch x := m.Code.(type) { + case *SimpleMessage_LineNum: + b.EncodeVarint(3<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.LineNum)) + case *SimpleMessage_Lang: + b.EncodeVarint(4<<3 | proto.WireBytes) + b.EncodeStringBytes(x.Lang) + case nil: + default: + return fmt.Errorf("SimpleMessage.Code has unexpected type %T", x) + } + // ext + switch x := m.Ext.(type) { + case *SimpleMessage_En: + b.EncodeVarint(6<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.En)) + case *SimpleMessage_No: + b.EncodeVarint(7<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.No); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("SimpleMessage.Ext has unexpected type %T", x) + } + return nil +} + +func _SimpleMessage_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*SimpleMessage) + switch tag { + case 3: // code.line_num + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Code = &SimpleMessage_LineNum{int64(x)} + return true, err + case 4: // code.lang + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.Code = &SimpleMessage_Lang{x} + return true, err + case 6: // ext.en + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Ext = &SimpleMessage_En{int64(x)} + return true, err + case 7: // ext.no + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(Embedded) + err := b.DecodeMessage(msg) + m.Ext = &SimpleMessage_No{msg} + return true, err + default: + return false, nil + } +} + +func _SimpleMessage_OneofSizer(msg proto.Message) (n int) { + m := msg.(*SimpleMessage) + // code + switch x := m.Code.(type) { + case *SimpleMessage_LineNum: + n += proto.SizeVarint(3<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.LineNum)) + case *SimpleMessage_Lang: + n += proto.SizeVarint(4<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.Lang))) + n += len(x.Lang) + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + // ext + switch x := m.Ext.(type) { + case *SimpleMessage_En: + n += proto.SizeVarint(6<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.En)) + case *SimpleMessage_No: + s := proto.Size(x.No) + n += proto.SizeVarint(7<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + func init() { + proto.RegisterType((*Embedded)(nil), "grpc.gateway.examples.examplepb.Embedded") proto.RegisterType((*SimpleMessage)(nil), "grpc.gateway.examples.examplepb.SimpleMessage") } @@ -236,23 +543,35 @@ var _EchoService_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("examples/proto/examplepb/echo_service.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 288 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x4e, 0xad, 0x48, 0xcc, - 0x2d, 0xc8, 0x49, 0x2d, 0xd6, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0xd7, 0x87, 0x72, 0x0b, 0x92, 0xf4, - 0x53, 0x93, 0x33, 0xf2, 0xe3, 0x8b, 0x53, 0x8b, 0xca, 0x32, 0x93, 0x53, 0xf5, 0xc0, 0x92, 0x42, - 0xf2, 0xe9, 0x45, 0x05, 0xc9, 0x7a, 0xe9, 0x89, 0x25, 0xa9, 0xe5, 0x89, 0x95, 0x7a, 0x30, 0x9d, - 0x7a, 0x70, 0x3d, 0x52, 0x32, 0xe9, 0xf9, 0xf9, 0xe9, 0x39, 0xa9, 0xfa, 0x89, 0x05, 0x99, 0xfa, - 0x89, 0x79, 0x79, 0xf9, 0x25, 0x89, 0x25, 0x99, 0xf9, 0x79, 0xc5, 0x10, 0xed, 0x4a, 0x86, 0x5c, - 0xbc, 0xc1, 0x99, 0x20, 0x95, 0xbe, 0xa9, 0xc5, 0xc5, 0x89, 0xe9, 0xa9, 0x42, 0x7c, 0x5c, 0x4c, - 0x99, 0x29, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x4c, 0x99, 0x29, 0x42, 0x02, 0x5c, 0xcc, - 0x79, 0xa5, 0xb9, 0x12, 0x4c, 0x0a, 0x8c, 0x1a, 0xcc, 0x41, 0x20, 0xa6, 0xd1, 0x65, 0x66, 0x2e, - 0x6e, 0xd7, 0xe4, 0x8c, 0xfc, 0x60, 0x88, 0x3b, 0x84, 0x96, 0x30, 0x72, 0xb1, 0x80, 0xf8, 0x42, - 0x7a, 0x7a, 0x04, 0xdc, 0xa2, 0x87, 0x62, 0x95, 0x14, 0x89, 0xea, 0x95, 0x6c, 0x9a, 0x2e, 0x3f, - 0x99, 0xcc, 0x64, 0xa6, 0x24, 0xaa, 0x5f, 0x66, 0x08, 0x0b, 0x14, 0x70, 0x90, 0xe8, 0x57, 0x67, - 0xa6, 0xd4, 0x46, 0xc9, 0x0a, 0x49, 0x63, 0x95, 0xd0, 0xaf, 0xce, 0x2b, 0xcd, 0xad, 0x15, 0xea, - 0x61, 0xe4, 0xe2, 0x00, 0x39, 0xd3, 0x29, 0x3f, 0xa5, 0x92, 0xe6, 0x4e, 0x55, 0x00, 0x3b, 0x55, - 0x0a, 0xd3, 0xa9, 0xf1, 0x49, 0xf9, 0x29, 0x95, 0x56, 0x8c, 0x5a, 0x42, 0xbd, 0x8c, 0x5c, 0x5c, - 0x20, 0xe7, 0xb8, 0xa4, 0xe6, 0xa4, 0x96, 0xa4, 0xd2, 0xdc, 0x41, 0xf2, 0x60, 0x07, 0x49, 0x6a, - 0x89, 0x63, 0x38, 0x28, 0x05, 0xec, 0x00, 0x27, 0xee, 0x28, 0x4e, 0xb8, 0xde, 0x24, 0x36, 0x70, - 0xe2, 0x30, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x46, 0x53, 0x05, 0xe1, 0x8a, 0x02, 0x00, 0x00, + // 470 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x53, 0x3f, 0x6f, 0xd3, 0x40, + 0x14, 0xef, 0xd9, 0x6e, 0x9a, 0xbc, 0x08, 0x54, 0x9d, 0x40, 0x98, 0xb4, 0xa8, 0x91, 0xc5, 0x10, + 0x8a, 0xe4, 0x53, 0xc2, 0x06, 0x13, 0x11, 0x45, 0x5d, 0x60, 0x70, 0xb7, 0x2c, 0xd1, 0xc5, 0xf7, + 0xe4, 0x5a, 0xd8, 0x77, 0x96, 0x7d, 0x29, 0x8d, 0xac, 0x2c, 0x48, 0x6c, 0x30, 0xb1, 0xf3, 0x11, + 0xd8, 0xf8, 0x18, 0x4c, 0x7c, 0x05, 0x3e, 0x08, 0xba, 0x4b, 0x1c, 0x09, 0x5a, 0xb5, 0xea, 0x90, + 0xcd, 0xef, 0xcf, 0xef, 0xfd, 0x7e, 0xf7, 0x7b, 0xcf, 0xf0, 0x1c, 0x2f, 0x79, 0x5e, 0x64, 0x58, + 0xb1, 0xa2, 0x54, 0x5a, 0xb1, 0x75, 0x58, 0xcc, 0x18, 0xc6, 0xe7, 0x6a, 0x5a, 0x61, 0x79, 0x91, + 0xc6, 0x18, 0xda, 0x22, 0x3d, 0x4a, 0xca, 0x22, 0x0e, 0x13, 0xae, 0xf1, 0x23, 0x5f, 0x84, 0x0d, + 0x32, 0xdc, 0x60, 0x7a, 0x87, 0x89, 0x52, 0x49, 0x86, 0x8c, 0x17, 0x29, 0xe3, 0x52, 0x2a, 0xcd, + 0x75, 0xaa, 0x64, 0xb5, 0x82, 0x07, 0x6f, 0xa1, 0x7d, 0x92, 0xcf, 0x50, 0x08, 0x14, 0xf4, 0x10, + 0xda, 0x45, 0xa9, 0x92, 0x12, 0xab, 0xca, 0x27, 0x7d, 0x32, 0x70, 0x4f, 0x77, 0xa2, 0x4d, 0x86, + 0x3e, 0x00, 0x4f, 0x2a, 0x8d, 0xbe, 0xd3, 0x27, 0x83, 0xce, 0xe9, 0x4e, 0x64, 0xa3, 0x71, 0x0b, + 0xbc, 0x9c, 0x97, 0x1f, 0x82, 0xcf, 0x0e, 0xdc, 0x3b, 0x4b, 0x0d, 0xe5, 0x3b, 0xac, 0x2a, 0x9e, + 0x20, 0xbd, 0x0f, 0x4e, 0x2a, 0xec, 0x9c, 0x4e, 0xe4, 0xa4, 0x82, 0xee, 0x83, 0x2b, 0xe7, 0xb9, + 0x85, 0xbb, 0x91, 0xf9, 0xa4, 0x07, 0xd0, 0xce, 0x52, 0x89, 0x53, 0x93, 0x76, 0xd7, 0x7c, 0x7b, + 0x26, 0xf3, 0x7e, 0x9e, 0x1b, 0xba, 0x8c, 0xcb, 0xc4, 0xf7, 0x1a, 0x3a, 0x13, 0xd1, 0xd7, 0xd0, + 0xaa, 0x34, 0xd7, 0xf3, 0xca, 0xdf, 0xed, 0x93, 0x41, 0x77, 0xf4, 0x2c, 0xbc, 0xe5, 0xf9, 0x61, + 0xf3, 0xba, 0x68, 0x0d, 0xa4, 0xfb, 0xe0, 0xa0, 0xf4, 0x5b, 0x96, 0x8f, 0x44, 0x0e, 0x4a, 0xfa, + 0x0a, 0x1c, 0xa9, 0xfc, 0xbd, 0x3b, 0x0e, 0x34, 0x60, 0xa9, 0x8c, 0x01, 0xb1, 0x12, 0x38, 0xde, + 0x05, 0x17, 0x2f, 0xf5, 0xe8, 0x97, 0x07, 0xdd, 0x93, 0xf8, 0x5c, 0x9d, 0xad, 0x96, 0x44, 0xbf, + 0x3b, 0xe0, 0x99, 0x98, 0x86, 0xb7, 0x0e, 0xfe, 0xc7, 0xbe, 0xde, 0x1d, 0xfb, 0x83, 0x9f, 0xe4, + 0xd3, 0xef, 0x3f, 0xdf, 0x9c, 0x1f, 0x24, 0x78, 0xc8, 0x2e, 0x86, 0xcd, 0xcd, 0xd8, 0x8b, 0x61, + 0x75, 0x2a, 0x96, 0x93, 0x27, 0xf4, 0xe0, 0xda, 0x02, 0xab, 0xe5, 0x3c, 0x5f, 0x4e, 0x9e, 0xd2, + 0xe0, 0x86, 0x32, 0xab, 0x8d, 0xfd, 0xcb, 0xc9, 0x90, 0xb2, 0xff, 0xbb, 0x86, 0xeb, 0xb6, 0x66, + 0x95, 0x4b, 0x56, 0xaf, 0x9c, 0x0e, 0xcd, 0x81, 0x5c, 0xcb, 0x3b, 0x62, 0xb5, 0x54, 0xab, 0x32, + 0xfd, 0x42, 0xa0, 0x6d, 0x0c, 0x1a, 0x2b, 0xb1, 0xd8, 0xba, 0x49, 0x7d, 0xeb, 0x51, 0xef, 0xaa, + 0x45, 0xd3, 0x99, 0x12, 0x8b, 0x97, 0xe4, 0x98, 0x7e, 0x25, 0x00, 0x46, 0xce, 0x1b, 0xcc, 0x50, + 0xe3, 0xd6, 0x05, 0x1d, 0x59, 0x41, 0x8f, 0x8f, 0x1f, 0x5d, 0x11, 0x24, 0xac, 0x80, 0x71, 0x77, + 0xd2, 0xd9, 0x60, 0x67, 0x2d, 0xfb, 0xcf, 0xbe, 0xf8, 0x1b, 0x00, 0x00, 0xff, 0xff, 0xe9, 0xdb, + 0x6f, 0x39, 0x21, 0x04, 0x00, 0x00, } diff --git a/examples/proto/examplepb/echo_service.pb.gw.go b/examples/proto/examplepb/echo_service.pb.gw.go index c281543bedb..844ef1418ad 100644 --- a/examples/proto/examplepb/echo_service.pb.gw.go +++ b/examples/proto/examplepb/echo_service.pb.gw.go @@ -63,6 +63,10 @@ func request_EchoService_Echo_0(ctx context.Context, marshaler runtime.Marshaler } +var ( + filter_EchoService_Echo_1 = &utilities.DoubleArray{Encoding: map[string]int{"id": 0, "num": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}} +) + func request_EchoService_Echo_1(ctx context.Context, marshaler runtime.Marshaler, client EchoServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq SimpleMessage var metadata runtime.ServerMetadata @@ -96,6 +100,169 @@ func request_EchoService_Echo_1(ctx context.Context, marshaler runtime.Marshaler return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "num", err) } + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_EchoService_Echo_1); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.Echo(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +var ( + filter_EchoService_Echo_2 = &utilities.DoubleArray{Encoding: map[string]int{"id": 0, "num": 1, "lang": 2}, Base: []int{1, 1, 2, 3, 0, 0, 0}, Check: []int{0, 1, 1, 1, 2, 3, 4}} +) + +func request_EchoService_Echo_2(ctx context.Context, marshaler runtime.Marshaler, client EchoServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq SimpleMessage + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") + } + + protoReq.Id, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) + } + + val, ok = pathParams["num"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "num") + } + + protoReq.Num, err = runtime.Int64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "num", err) + } + + val, ok = pathParams["lang"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "lang") + } + + if protoReq.Code == nil { + protoReq.Code = &SimpleMessage_Lang{} + } else if _, ok := protoReq.Code.(*SimpleMessage_Lang); !ok { + return nil, metadata, grpc.Errorf(codes.InvalidArgument, "expect type: *SimpleMessage_Lang, but: %t\n", protoReq.Code) + } + protoReq.Code.(*SimpleMessage_Lang).Lang, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "lang", err) + } + + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_EchoService_Echo_2); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.Echo(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +var ( + filter_EchoService_Echo_3 = &utilities.DoubleArray{Encoding: map[string]int{"id": 0, "line_num": 1, "status": 2, "note": 3}, Base: []int{1, 1, 2, 1, 3, 0, 0, 0}, Check: []int{0, 1, 1, 1, 4, 2, 3, 5}} +) + +func request_EchoService_Echo_3(ctx context.Context, marshaler runtime.Marshaler, client EchoServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq SimpleMessage + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") + } + + protoReq.Id, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) + } + + val, ok = pathParams["line_num"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "line_num") + } + + if protoReq.Code == nil { + protoReq.Code = &SimpleMessage_LineNum{} + } else if _, ok := protoReq.Code.(*SimpleMessage_LineNum); !ok { + return nil, metadata, grpc.Errorf(codes.InvalidArgument, "expect type: *SimpleMessage_LineNum, but: %t\n", protoReq.Code) + } + protoReq.Code.(*SimpleMessage_LineNum).LineNum, err = runtime.Int64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "line_num", err) + } + + val, ok = pathParams["status.note"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "status.note") + } + + err = runtime.PopulateFieldFromPath(&protoReq, "status.note", val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "status.note", err) + } + + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_EchoService_Echo_3); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.Echo(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +var ( + filter_EchoService_Echo_4 = &utilities.DoubleArray{Encoding: map[string]int{"no": 0, "note": 1}, Base: []int{1, 1, 1, 0}, Check: []int{0, 1, 2, 3}} +) + +func request_EchoService_Echo_4(ctx context.Context, marshaler runtime.Marshaler, client EchoServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq SimpleMessage + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["no.note"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "no.note") + } + + err = runtime.PopulateFieldFromPath(&protoReq, "no.note", val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "no.note", err) + } + + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_EchoService_Echo_4); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := client.Echo(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err @@ -227,6 +394,93 @@ func RegisterEchoServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux }) + mux.Handle("GET", pattern_EchoService_Echo_2, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + if cn, ok := w.(http.CloseNotifier); ok { + go func(done <-chan struct{}, closed <-chan bool) { + select { + case <-done: + case <-closed: + cancel() + } + }(ctx.Done(), cn.CloseNotify()) + } + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_EchoService_Echo_2(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_EchoService_Echo_2(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_EchoService_Echo_3, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + if cn, ok := w.(http.CloseNotifier); ok { + go func(done <-chan struct{}, closed <-chan bool) { + select { + case <-done: + case <-closed: + cancel() + } + }(ctx.Done(), cn.CloseNotify()) + } + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_EchoService_Echo_3(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_EchoService_Echo_3(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_EchoService_Echo_4, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + if cn, ok := w.(http.CloseNotifier); ok { + go func(done <-chan struct{}, closed <-chan bool) { + select { + case <-done: + case <-closed: + cancel() + } + }(ctx.Done(), cn.CloseNotify()) + } + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_EchoService_Echo_4(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_EchoService_Echo_4(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("POST", pattern_EchoService_EchoBody_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -293,6 +547,12 @@ var ( pattern_EchoService_Echo_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 1, 0, 4, 1, 5, 4}, []string{"v1", "example", "echo", "id", "num"}, "")) + pattern_EchoService_Echo_2 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 1, 0, 4, 1, 5, 4, 1, 0, 4, 1, 5, 5}, []string{"v1", "example", "echo", "id", "num", "lang"}, "")) + + pattern_EchoService_Echo_3 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 1, 0, 4, 1, 5, 4, 1, 0, 4, 1, 5, 5}, []string{"v1", "example", "echo1", "id", "line_num", "status.note"}, "")) + + pattern_EchoService_Echo_4 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "example", "echo2", "no.note"}, "")) + pattern_EchoService_EchoBody_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "example", "echo_body"}, "")) pattern_EchoService_EchoDelete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "example", "echo_delete"}, "")) @@ -303,6 +563,12 @@ var ( forward_EchoService_Echo_1 = runtime.ForwardResponseMessage + forward_EchoService_Echo_2 = runtime.ForwardResponseMessage + + forward_EchoService_Echo_3 = runtime.ForwardResponseMessage + + forward_EchoService_Echo_4 = runtime.ForwardResponseMessage + forward_EchoService_EchoBody_0 = runtime.ForwardResponseMessage forward_EchoService_EchoDelete_0 = runtime.ForwardResponseMessage diff --git a/examples/proto/examplepb/echo_service.proto b/examples/proto/examplepb/echo_service.proto index 506917c11c1..710d0576e45 100644 --- a/examples/proto/examplepb/echo_service.proto +++ b/examples/proto/examplepb/echo_service.proto @@ -9,11 +9,28 @@ package grpc.gateway.examples.examplepb; import "google/api/annotations.proto"; +// Embedded represents a message embedded in SimpleMessage. +message Embedded { + oneof mark { + int64 progress = 1; + string note = 2; + } +} + // SimpleMessage represents a simple message sent to the Echo service. message SimpleMessage { // Id represents the message identifier. string id = 1; int64 num = 2; + oneof code { + int64 line_num = 3; + string lang = 4; + } + Embedded status = 5; + oneof ext { + int64 en = 6; + Embedded no = 7; + } } // Echo service responds to incoming echo requests. @@ -28,6 +45,15 @@ service EchoService { additional_bindings { get: "/v1/example/echo/{id}/{num}" } + additional_bindings { + get: "/v1/example/echo/{id}/{num}/{lang}" + } + additional_bindings { + get: "/v1/example/echo1/{id}/{line_num}/{status.note}" + } + additional_bindings { + get: "/v1/example/echo2/{no.note}" + } }; } // EchoBody method receives a simple message and returns it. diff --git a/examples/proto/examplepb/echo_service.swagger.json b/examples/proto/examplepb/echo_service.swagger.json index f76f9289a81..c14354ffbce 100644 --- a/examples/proto/examplepb/echo_service.swagger.json +++ b/examples/proto/examplepb/echo_service.swagger.json @@ -68,6 +68,278 @@ "required": true, "type": "string", "format": "int64" + }, + { + "name": "line_num", + "in": "query", + "required": false, + "type": "string", + "format": "int64" + }, + { + "name": "lang", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "status.progress", + "in": "query", + "required": false, + "type": "string", + "format": "int64" + }, + { + "name": "status.note", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "en", + "in": "query", + "required": false, + "type": "string", + "format": "int64" + }, + { + "name": "no.progress", + "in": "query", + "required": false, + "type": "string", + "format": "int64" + }, + { + "name": "no.note", + "in": "query", + "required": false, + "type": "string" + } + ], + "tags": [ + "EchoService" + ] + } + }, + "/v1/example/echo/{id}/{num}/{lang}": { + "get": { + "summary": "Echo method receives a simple message and returns it.", + "description": "The message posted as the id parameter will also be\nreturned.", + "operationId": "Echo3", + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/examplepbSimpleMessage" + } + } + }, + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "num", + "in": "path", + "required": true, + "type": "string", + "format": "int64" + }, + { + "name": "lang", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "line_num", + "in": "query", + "required": false, + "type": "string", + "format": "int64" + }, + { + "name": "status.progress", + "in": "query", + "required": false, + "type": "string", + "format": "int64" + }, + { + "name": "status.note", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "en", + "in": "query", + "required": false, + "type": "string", + "format": "int64" + }, + { + "name": "no.progress", + "in": "query", + "required": false, + "type": "string", + "format": "int64" + }, + { + "name": "no.note", + "in": "query", + "required": false, + "type": "string" + } + ], + "tags": [ + "EchoService" + ] + } + }, + "/v1/example/echo1/{id}/{line_num}/{status.note}": { + "get": { + "summary": "Echo method receives a simple message and returns it.", + "description": "The message posted as the id parameter will also be\nreturned.", + "operationId": "Echo4", + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/examplepbSimpleMessage" + } + } + }, + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "line_num", + "in": "path", + "required": true, + "type": "string", + "format": "int64" + }, + { + "name": "status.note", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "num", + "in": "query", + "required": false, + "type": "string", + "format": "int64" + }, + { + "name": "lang", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "status.progress", + "in": "query", + "required": false, + "type": "string", + "format": "int64" + }, + { + "name": "en", + "in": "query", + "required": false, + "type": "string", + "format": "int64" + }, + { + "name": "no.progress", + "in": "query", + "required": false, + "type": "string", + "format": "int64" + } + ], + "tags": [ + "EchoService" + ] + } + }, + "/v1/example/echo2/{no.note}": { + "get": { + "summary": "Echo method receives a simple message and returns it.", + "description": "The message posted as the id parameter will also be\nreturned.", + "operationId": "Echo5", + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/examplepbSimpleMessage" + } + } + }, + "parameters": [ + { + "name": "no.note", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "id", + "description": "Id represents the message identifier.", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "num", + "in": "query", + "required": false, + "type": "string", + "format": "int64" + }, + { + "name": "line_num", + "in": "query", + "required": false, + "type": "string", + "format": "int64" + }, + { + "name": "lang", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "status.progress", + "in": "query", + "required": false, + "type": "string", + "format": "int64" + }, + { + "name": "en", + "in": "query", + "required": false, + "type": "string", + "format": "int64" + }, + { + "name": "no.progress", + "in": "query", + "required": false, + "type": "string", + "format": "int64" } ], "tags": [ @@ -128,6 +400,52 @@ "required": false, "type": "string", "format": "int64" + }, + { + "name": "line_num", + "in": "query", + "required": false, + "type": "string", + "format": "int64" + }, + { + "name": "lang", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "status.progress", + "in": "query", + "required": false, + "type": "string", + "format": "int64" + }, + { + "name": "status.note", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "en", + "in": "query", + "required": false, + "type": "string", + "format": "int64" + }, + { + "name": "no.progress", + "in": "query", + "required": false, + "type": "string", + "format": "int64" + }, + { + "name": "no.note", + "in": "query", + "required": false, + "type": "string" } ], "tags": [ @@ -137,6 +455,19 @@ } }, "definitions": { + "examplepbEmbedded": { + "type": "object", + "properties": { + "progress": { + "type": "string", + "format": "int64" + }, + "note": { + "type": "string" + } + }, + "description": "Embedded represents a message embedded in SimpleMessage." + }, "examplepbSimpleMessage": { "type": "object", "properties": { @@ -147,6 +478,23 @@ "num": { "type": "string", "format": "int64" + }, + "line_num": { + "type": "string", + "format": "int64" + }, + "lang": { + "type": "string" + }, + "status": { + "$ref": "#/definitions/examplepbEmbedded" + }, + "en": { + "type": "string", + "format": "int64" + }, + "no": { + "$ref": "#/definitions/examplepbEmbedded" } }, "description": "SimpleMessage represents a simple message sent to the Echo service." diff --git a/protoc-gen-grpc-gateway/descriptor/types.go b/protoc-gen-grpc-gateway/descriptor/types.go index a84b85947ae..6346b68e956 100644 --- a/protoc-gen-grpc-gateway/descriptor/types.go +++ b/protoc-gen-grpc-gateway/descriptor/types.go @@ -267,15 +267,37 @@ func (p FieldPath) AssignableExpr(msgExpr string) string { if l == 0 { return msgExpr } - components := []string{msgExpr} + + var preparations []string + components := msgExpr for i, c := range p { + // Check if it is a oneOf field. + if c.Target.OneofIndex != nil { + index := c.Target.OneofIndex + msg := c.Target.Message + oneOfName := gogen.CamelCase(msg.GetOneofDecl()[*index].GetName()) + oneofFieldName := msg.GetName() + "_" + c.AssignableExpr() + + components = components + "." + oneOfName + s := `if %s == nil { + %s =&%s{} + } else if _, ok := %s.(*%s); !ok { + return nil, metadata, grpc.Errorf(codes.InvalidArgument, "expect type: *%s, but: %%t\n",%s) + }` + + preparations = append(preparations, fmt.Sprintf(s, components, components, oneofFieldName, components, oneofFieldName, oneofFieldName, components)) + components = components + ".(*" + oneofFieldName + ")" + } + if i == l-1 { - components = append(components, c.AssignableExpr()) + components = components + "." + c.AssignableExpr() continue } - components = append(components, c.ValueExpr()) + components = components + "." + c.ValueExpr() } - return strings.Join(components, ".") + + preparations = append(preparations, components) + return strings.Join(preparations, "\n") } // FieldPathComponent is a path component in FieldPath