echo icon indicating copy to clipboard operation
echo copied to clipboard

No Bind Form Data use the pb.go was generated by .proto file when binding slice of struct in formdata request

Open DenisYin66 opened this issue 4 years ago • 3 comments

Issue Description

Hi all. Thank you for this project and all the great work on it.

Recently, we want to use proto file to automatically generate xxx_echo.pb.go file that can register GET/POST http echo service For example, the stuct generated by message SayHelloReq is as follows:

type SayHelloReq struct {
    Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
}

func RegisterHelloEchoServer(s *echo.Server, service HelloServer) {
	s.POST("/hello/", _WrapperHelloSayHello(service))
}

func _WrapperHelloSayHello(service HelloServer) echo.HandlerFunc {
     return func(ctx *echo.Context) error {
          var in SayHelloReq
          ctx.Bind(&in)          //this
          xxx  todo some logic 
     }
}

but when Simulate a form request like this:

curl \
  -X POST \
  http://localhost:1323/hello
  -d 'name=Joe' \

The default binder of echo to find this data,and the data is nil. but the form["name"] = "Joe"

form["name,omitempty"]

but i want the echo to find form["name"]. After that, can echo support the resolution of Google omitempty?

Checklist

  • [ ] Dependencies installed protobuf

Expected behaviour

can echo support the resolution of Google omitempty

Version/commit

DenisYin66 avatar Jul 16 '21 03:07 DenisYin66

Hi, to bind form data you need to add form:"name" to the struct field tag. Please see the documentation about that at https://echo.labstack.com/guide/binding/

		type SayHelloReq struct {
			Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty" form:"name"`
		}

Full example:

func main() {
	e := echo.New()

	e.POST("/post", func(c echo.Context) error {
		type SayHelloReq struct {
			Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty" form:"name"`
		}
		var in SayHelloReq
		c.Bind(&in)
		return c.String(http.StatusOK, in.Name + "\n")
	})

	s := http.Server{Addr: ":8082", Handler: e}
	if err := s.ListenAndServe(); err != http.ErrServerClosed {
		log.Fatal(err)
	}
}

Output:

x@x:~/$ curl -v -X POST  http://localhost:8082/post -d 'name=Joe'
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying 127.0.0.1:8082...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8082 (#0)
> POST /post HTTP/1.1
> Host: localhost:8082
> User-Agent: curl/7.68.0
> Accept: */*
> Content-Length: 8
> Content-Type: application/x-www-form-urlencoded
> 
* upload completely sent off: 8 out of 8 bytes
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=UTF-8
< Date: Fri, 16 Jul 2021 03:18:01 GMT
< Content-Length: 4
< 
Joe
* Connection #0 to host localhost left intact

aldas avatar Jul 16 '21 03:07 aldas

oh,thanks.i can got it. but I mean the sturct is generated automatically by protoc. Is there a better solution without adding form tag? If not, I will add a service to add form tag.

DenisYin66 avatar Jul 16 '21 03:07 DenisYin66

You could write sed awk etc command that does replacement/insertion for those protoc generated files and is executed after protoc call.

aldas avatar Jul 17 '21 08:07 aldas